[Ocfs2-tools-commits] taoma commits r1323 -
branches/sparse-files/libocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Wed Mar 21 23:09:21 PDT 2007
Author: taoma
Date: 2007-03-21 23:09:18 -0700 (Wed, 21 Mar 2007)
New Revision: 1323
Modified:
branches/sparse-files/libocfs2/extents.c
branches/sparse-files/libocfs2/truncate.c
Log:
Modify ocfs2_truncate to be fit for sparse file.
Now ocfs2_truncate can truncate a file to a new size. The excess extent block and clusters
will be freed according to the real allocation of the sparse file.
Modified: branches/sparse-files/libocfs2/extents.c
===================================================================
--- branches/sparse-files/libocfs2/extents.c 2007-03-21 06:37:23 UTC (rev 1322)
+++ branches/sparse-files/libocfs2/extents.c 2007-03-22 06:09:18 UTC (rev 1323)
@@ -344,9 +344,11 @@
if (flags & (OCFS2_EXTENT_ABORT | OCFS2_EXTENT_ERROR))
iret |= flags & (OCFS2_EXTENT_ABORT | OCFS2_EXTENT_ERROR);
- /* if the list was changed and we still have recs then we need
- * to write the changes to disk */
- if (changed & OCFS2_EXTENT_CHANGED && el->l_next_free_rec) {
+ /* If the list was changed, we should write the changes to disk.
+ * Note:
+ * For a sparse file, we may have an empty extent block.
+ */
+ if (changed & OCFS2_EXTENT_CHANGED) {
ctxt->errcode = ocfs2_write_extent_block(ctxt->fs,
eb_rec->e_blkno,
ctxt->eb_bufs[tree_depth]);
Modified: branches/sparse-files/libocfs2/truncate.c
===================================================================
--- branches/sparse-files/libocfs2/truncate.c 2007-03-21 06:37:23 UTC (rev 1322)
+++ branches/sparse-files/libocfs2/truncate.c 2007-03-22 06:09:18 UTC (rev 1323)
@@ -32,6 +32,11 @@
#include "ocfs2.h"
+struct truncate_ctxt {
+ uint64_t new_size_in_clusters;
+ uint32_t new_i_clusters;
+};
+
/*
* Delete and free clusters if needed. This only works with DEPTH_TRAVERSE.
*/
@@ -41,15 +46,19 @@
uint64_t ref_blkno, int ref_recno,
void *priv_data)
{
- uint32_t len, rec_clusters, new_i_clusters = *(uint32_t *)priv_data;
+ struct truncate_ctxt *ctxt = (struct truncate_ctxt *)priv_data;
+ uint32_t len, new_size_in_clusters = ctxt->new_size_in_clusters;
uint64_t start = 0;
errcode_t ret;
+ int func_ret = OCFS2_EXTENT_ERROR;
+ char *buf = NULL;
+ struct ocfs2_extent_list *el = NULL;
if ((rec->e_cpos + ocfs2_rec_clusters(tree_depth, rec)) <=
- new_i_clusters)
+ new_size_in_clusters)
return 0;
- if (rec->e_cpos >= new_i_clusters) {
+ if (rec->e_cpos >= new_size_in_clusters) {
/* the rec is entirely outside the new size, free it */
if (!tree_depth) {
start = rec->e_blkno;
@@ -69,28 +78,59 @@
/* we're truncating into the middle of the rec */
len = rec->e_cpos +
ocfs2_rec_clusters(tree_depth, rec);
- len -= new_i_clusters;
+ len -= new_size_in_clusters;
if (!tree_depth) {
ocfs2_set_rec_clusters(tree_depth, rec,
- new_i_clusters - rec->e_cpos);
+ new_size_in_clusters - rec->e_cpos);
start = rec->e_blkno +
ocfs2_clusters_to_blocks(fs,
ocfs2_rec_clusters(tree_depth,
rec));
- } else
+ } else {
ocfs2_set_rec_clusters(tree_depth, rec,
- new_i_clusters - rec->e_cpos);
+ new_size_in_clusters - rec->e_cpos);
+ /*
+ * For a sparse file, we may meet with another
+ * situation here:
+ * The start of the left most extent rec is greater
+ * than the new size we truncate the file to, but the
+ * start of the extent block is less than that size.
+ * In this case, actually all the extent records in
+ * this extent block have been removed. So we have
+ * to remove the extent block also.
+ * In this function, we have to reread the extent list
+ * to see whether the extent block is empty or not.
+ */
+ ret = ocfs2_malloc_block(fs->fs_io, &buf);
+ if (ret)
+ goto bail;
+
+ ret = ocfs2_read_extent_block(fs, rec->e_blkno, buf);
+ if (ret)
+ goto bail;
+
+ el = &((struct ocfs2_extent_block *)buf)->h_list;
+ if (el->l_next_free_rec == 0) {
+ ret = ocfs2_delete_extent_block(fs, rec->e_blkno);
+ if (ret)
+ goto bail;
+ memset(rec, 0, sizeof(struct ocfs2_extent_rec));
+ }
+ }
}
if (start) {
ret = ocfs2_free_clusters(fs, len, start);
if (ret)
goto bail;
+ ctxt->new_i_clusters -= len;
}
- return OCFS2_EXTENT_CHANGED;
+ func_ret = OCFS2_EXTENT_CHANGED;
bail:
- return OCFS2_EXTENT_ERROR;
+ if (buf)
+ ocfs2_free(&buf);
+ return func_ret;
}
/* XXX care about zeroing new clusters and final partially truncated
@@ -100,8 +140,8 @@
errcode_t ret;
char *buf;
struct ocfs2_dinode *di;
- uint32_t new_i_clusters, old_i_clusters;
- uint64_t new_i_blocks, old_i_blocks;
+ uint32_t new_size_in_clusters;
+ uint64_t new_size_in_blocks;
ret = ocfs2_malloc_block(fs->fs_io, &buf);
if (ret)
@@ -115,12 +155,10 @@
if (di->i_size == new_i_size)
goto out;
- new_i_blocks = ocfs2_blocks_in_bytes(fs, new_i_size);
- new_i_clusters = ocfs2_clusters_in_blocks(fs, new_i_blocks);
- old_i_blocks = ocfs2_blocks_in_bytes(fs, di->i_size);
- old_i_clusters = ocfs2_clusters_in_blocks(fs, old_i_blocks);
+ new_size_in_blocks = ocfs2_blocks_in_bytes(fs, new_i_size);
+ new_size_in_clusters = ocfs2_clusters_in_blocks(fs, new_size_in_blocks);
- if (old_i_clusters < new_i_clusters) {
+ if (di->i_size < new_i_size) {
ret = ocfs2_extend_file(fs, ino, new_i_size);
if (ret)
goto out;
@@ -132,23 +170,27 @@
if (ret)
goto out;
} else {
+ struct truncate_ctxt ctxt = {
+ .new_i_clusters = di->i_clusters,
+ .new_size_in_clusters = new_size_in_clusters,
+ };
+
ret = ocfs2_extent_iterate_inode(fs, di,
OCFS2_EXTENT_FLAG_DEPTH_TRAVERSE,
NULL, truncate_iterate,
- &new_i_clusters);
+ &ctxt);
if (ret)
goto out;
+ di->i_clusters = ctxt.new_i_clusters;
/* now all the clusters and extent blocks are freed.
* only when the file's content is empty, should the tree depth
* change.
*/
- if (new_i_clusters == 0)
+ if (ctxt.new_i_clusters == 0)
di->id2.i_list.l_tree_depth = 0;
-
}
- di->i_clusters = new_i_clusters;
di->i_size = new_i_size;
ret = ocfs2_write_inode(fs, ino, buf);
More information about the Ocfs2-tools-commits
mailing list