[Ocfs2-tools-devel] [PATCH 8/9] libocfs2: Allow callers to specify the free_clusters routine in ocfs2_truncate

Joel Becker joel.becker at oracle.com
Thu Jul 30 12:25:06 PDT 2009


o2fsck wants to call ocfs2_truncate but handle freeing the clusters
itself.  Rather than reimplementing the truncate code in fsck, we create
ocfs2_truncate_full() that can take a free_clusters() routine.
ocfs2_truncate() just calls ocfs2_truncate_full() with a NULL routine
pointer.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 include/ocfs2/ocfs2.h |    7 +++
 libocfs2/truncate.c   |  112 +++++++++++++++++++++++++++++++++----------------
 2 files changed, 82 insertions(+), 37 deletions(-)

diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index be7a000..8bf22c9 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -549,6 +549,13 @@ errcode_t ocfs2_allocate_unwritten_extents(ocfs2_filesys *fs, uint64_t ino,
 					   uint64_t offset, uint64_t len);
 
 errcode_t ocfs2_truncate(ocfs2_filesys *fs, uint64_t ino, uint64_t new_i_size);
+errcode_t ocfs2_truncate_full(ocfs2_filesys *fs, uint64_t ino,
+			      uint64_t new_i_size,
+			      errcode_t (*free_clusters)(ocfs2_filesys *fs,
+							 uint32_t len,
+							 uint64_t start,
+							 void *free_data),
+			      void *free_data);
 errcode_t ocfs2_zero_tail_and_truncate(ocfs2_filesys *fs,
 				       ocfs2_cached_inode *ci,
 				       uint64_t new_size,
diff --git a/libocfs2/truncate.c b/libocfs2/truncate.c
index c18a247..680fca5 100644
--- a/libocfs2/truncate.c
+++ b/libocfs2/truncate.c
@@ -35,6 +35,11 @@
 struct truncate_ctxt {
 	uint64_t new_size_in_clusters;
 	uint32_t new_i_clusters;
+	errcode_t (*free_clusters)(ocfs2_filesys *fs,
+				   uint32_t len,
+				   uint64_t start_blkno,
+				   void *free_data);
+	void *free_data;
 };
 
 /*
@@ -120,7 +125,11 @@ static int truncate_iterate(ocfs2_filesys *fs,
 	}
 
 	if (start) {
-		ret = ocfs2_free_clusters(fs, len, start);
+		if (ctxt->free_clusters)
+			ret = ctxt->free_clusters(fs, len, start,
+						  ctxt->free_data);
+		else
+			ret = ocfs2_free_clusters(fs, len, start);
 		if (ret)
 			goto bail;
 		ctxt->new_i_clusters -= len;
@@ -184,9 +193,67 @@ out:
 	return ret;
 }
 
+/*
+ * This function will truncate the file's cluster which exceeds
+ * the cluster where new_size resides in and empty all the
+ * bytes in the same cluster which exceeds new_size.
+ */
+static errcode_t ocfs2_zero_tail_and_truncate_full(ocfs2_filesys *fs,
+						   ocfs2_cached_inode *ci,
+						   uint64_t new_i_size,
+						   uint32_t *new_clusters,
+			      errcode_t (*free_clusters)(ocfs2_filesys *fs,
+							 uint32_t len,
+							 uint64_t start,
+							 void *free_data),
+						   void *free_data)
+{
+	errcode_t ret;
+	uint64_t new_size_in_blocks;
+	struct truncate_ctxt ctxt;
+
+	new_size_in_blocks = ocfs2_blocks_in_bytes(fs, new_i_size);
+	ctxt.new_i_clusters = ci->ci_inode->i_clusters;
+	ctxt.new_size_in_clusters =
+			ocfs2_clusters_in_blocks(fs, new_size_in_blocks);
+	ctxt.free_clusters = free_clusters;
+	ctxt.free_data = free_data;
+
+	ret = ocfs2_extent_iterate_inode(fs, ci->ci_inode,
+					 OCFS2_EXTENT_FLAG_DEPTH_TRAVERSE,
+					 NULL, truncate_iterate,
+					 &ctxt);
+	if (ret)
+		goto out;
+
+	ret = ocfs2_zero_tail_for_truncate(ci, new_i_size);
+	if (ret)
+		goto out;
+
+	if (new_clusters)
+		*new_clusters = ctxt.new_i_clusters;
+out:
+	return ret;
+}
+
+errcode_t ocfs2_zero_tail_and_truncate(ocfs2_filesys *fs,
+				       ocfs2_cached_inode *ci,
+				       uint64_t new_i_size,
+				       uint32_t *new_clusters)
+{
+	return ocfs2_zero_tail_and_truncate_full(fs, ci, new_i_size,
+						 new_clusters, NULL, NULL);
+}
+
 /* XXX care about zeroing new clusters and final partially truncated 
  * clusters */
-errcode_t ocfs2_truncate(ocfs2_filesys *fs, uint64_t ino, uint64_t new_i_size)
+errcode_t ocfs2_truncate_full(ocfs2_filesys *fs, uint64_t ino,
+			      uint64_t new_i_size,
+			      errcode_t (*free_clusters)(ocfs2_filesys *fs,
+							 uint32_t len,
+							 uint64_t start,
+							 void *free_data),
+			      void *free_data)
 {
 	errcode_t ret;
 	uint32_t new_clusters;
@@ -202,8 +269,10 @@ errcode_t ocfs2_truncate(ocfs2_filesys *fs, uint64_t ino, uint64_t new_i_size)
 	if (ci->ci_inode->i_size < new_i_size)
 		ret = ocfs2_extend_file(fs, ino, new_i_size);
 	else {
-		ret = ocfs2_zero_tail_and_truncate(fs, ci, new_i_size,
-						   &new_clusters);
+		ret = ocfs2_zero_tail_and_truncate_full(fs, ci, new_i_size,
+							&new_clusters,
+							free_clusters,
+							free_data);
 		if (ret)
 			goto out;
 
@@ -225,40 +294,9 @@ out:
 	return ret;
 }
 
-/*
- * This fucntion will truncate the file's cluster which exceeds
- * the cluster where new_size resides in and empty all the
- * bytes in the same cluster which exceeds new_size.
- */
-errcode_t ocfs2_zero_tail_and_truncate(ocfs2_filesys *fs,
-				       ocfs2_cached_inode *ci,
-				       uint64_t new_i_size,
-				       uint32_t *new_clusters)
+errcode_t ocfs2_truncate(ocfs2_filesys *fs, uint64_t ino, uint64_t new_i_size)
 {
-	errcode_t ret;
-	uint64_t new_size_in_blocks;
-	struct truncate_ctxt ctxt;
-
-	new_size_in_blocks = ocfs2_blocks_in_bytes(fs, new_i_size);
-	ctxt.new_i_clusters = ci->ci_inode->i_clusters;
-	ctxt.new_size_in_clusters =
-			ocfs2_clusters_in_blocks(fs, new_size_in_blocks);
-
-	ret = ocfs2_extent_iterate_inode(fs, ci->ci_inode,
-					 OCFS2_EXTENT_FLAG_DEPTH_TRAVERSE,
-					 NULL, truncate_iterate,
-					 &ctxt);
-	if (ret)
-		goto out;
-
-	ret = ocfs2_zero_tail_for_truncate(ci, new_i_size);
-	if (ret)
-		goto out;
-
-	if (new_clusters)
-		*new_clusters = ctxt.new_i_clusters;
-out:
-	return ret;
+	return ocfs2_truncate_full(fs, ino, new_i_size, NULL, NULL);
 }
 
 errcode_t ocfs2_xattr_value_truncate(ocfs2_filesys *fs,
-- 
1.6.3.3




More information about the Ocfs2-tools-devel mailing list