[Ocfs2-tools-devel] [PATCH 1/1] Add truncate for "clear sparse" function in tunefs,

Tao Ma tao.ma at oracle.com
Tue Nov 13 00:41:26 PST 2007


take 2

Modification from V1 to V2:
Move truncate process to the end of operation.
We may need to truncate an unwritten extent sometime. So if we truncate the file
first, the unwritten extent information stored in clear_ctxt may be outdated.
So move it to the end.

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 tunefs.ocfs2/sparse_file.c |   65 +++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/tunefs.ocfs2/sparse_file.c b/tunefs.ocfs2/sparse_file.c
index 8ef6710..06782f6 100644
--- a/tunefs.ocfs2/sparse_file.c
+++ b/tunefs.ocfs2/sparse_file.c
@@ -67,10 +67,14 @@ struct unwritten_list {
  * unwritten_list. Since filling up a hole may need a new extent record and
  * lead to some new extent block, the total hole number in the sparse file
  * will also be recorded.
+ *
+ * Some sparse file may also have some clusters which exceed the limit of
+ * i_size, and they should be truncated.
  */
 struct sparse_file {
 	uint64_t blkno;
 	uint32_t holes_num;
+	int truncate;
 	struct hole_list *holes;
 	struct unwritten_list *unwritten;
 	struct sparse_file *next;
@@ -208,6 +212,7 @@ static void list_sparse_iterate(void *priv_data,
  * Iterate a file.
  * Call "func" when we meet with a hole.
  * Call "unwritten_func" when we meet with unwritten clusters.
+ * Call "seen_exceed" when we see some clusters exceed i_size.
  */
 static errcode_t iterate_file(ocfs2_filesys *fs,
 			      struct ocfs2_dinode *di,
@@ -218,10 +223,12 @@ static errcode_t iterate_file(ocfs2_filesys *fs,
 						     uint32_t start,
 						     uint32_t len,
 						     uint64_t p_start),
+			      void (*seen_exceed)(void *priv_data),
 			      void *priv_data)
 {
 	errcode_t ret;
 	uint32_t clusters, v_cluster = 0, p_cluster, num_clusters;
+	uint32_t get_clusters = 0;
 	uint64_t p_blkno;
 	uint16_t extent_flags;
 	ocfs2_cached_inode *ci = NULL;
@@ -250,7 +257,8 @@ static errcode_t iterate_file(ocfs2_filesys *fs,
 
 			if (func)
 				func(priv_data, v_cluster, num_clusters);
-		}
+		} else
+			get_clusters += num_clusters;
 
 		if ((extent_flags & OCFS2_EXT_UNWRITTEN) && unwritten_func) {
 			p_blkno = ocfs2_clusters_to_blocks(fs, p_cluster);
@@ -261,6 +269,17 @@ static errcode_t iterate_file(ocfs2_filesys *fs,
 		v_cluster += num_clusters;
 	}
 
+	/*
+	 * If there are some extra clusters we need to record them.
+	 * There are 2 scenarios:
+	 * 1. there are more cotinguous clusters allocated in which case
+	 *    get_clusters > di->i_clusters
+	 * 2. there are more clusters allocated after i_size in which case
+	 *    get_clusters < di->i_clusters
+	 */
+	if (get_clusters != di->i_clusters && seen_exceed)
+		seen_exceed(priv_data);
+
 bail:
 	if (ci)
 		ocfs2_free_cached_inode(fs, ci);
@@ -297,7 +316,7 @@ static errcode_t list_sparse_file(ocfs2_filesys *fs,
 		}
 	}
 
-	ret = iterate_file(fs, di, ctxt->func, NULL, ctxt);
+	ret = iterate_file(fs, di, ctxt->func, NULL, NULL, ctxt);
 	if (ret)
 		goto bail;
 
@@ -521,7 +540,11 @@ out:
 	return ret;
 }
 
-static errcode_t set_func(ocfs2_filesys *fs, struct ocfs2_dinode *di)
+/*
+ * Truncate file according to i_size.
+ * All allocated clusters which exceeds i_size will be released.
+ */
+static errcode_t truncate_file(ocfs2_filesys *fs, struct ocfs2_dinode *di)
 {
 	errcode_t ret;
 	uint32_t new_clusters;
@@ -558,7 +581,7 @@ errcode_t set_sparse_file_flag(ocfs2_filesys *fs, char *progname)
 	if (ocfs2_sparse_alloc(super))
 		return 0;
 
-	ret = iterate_all_regular(fs, progname, set_func);
+	ret = iterate_all_regular(fs, progname, truncate_file);
 
 	if (ret)
 		goto bail;
@@ -634,6 +657,14 @@ static void add_unwritten(void *priv_data, uint32_t start,
 	ctxt->files->unwritten = unwritten;
 }
 
+static void add_truncate(void *priv_data)
+{
+	struct clear_hole_unwritten_ctxt *ctxt =
+			(struct clear_hole_unwritten_ctxt *)priv_data;
+
+	ctxt->files->truncate = 1;
+}
+
 static errcode_t calc_hole_and_unwritten(ocfs2_filesys *fs,
 					 struct ocfs2_dinode *di)
 {
@@ -652,14 +683,18 @@ static errcode_t calc_hole_and_unwritten(ocfs2_filesys *fs,
 	file->blkno = di->i_blkno;
 	old_files = clear_ctxt.files;
 	clear_ctxt.files = file;
-	ret = iterate_file(fs, di, add_hole, add_unwritten, &clear_ctxt);
+	ret = iterate_file(fs, di, add_hole, add_unwritten,
+			   add_truncate, &clear_ctxt);
 	if (ret || clear_ctxt.ret) {
 		clear_ctxt.files = old_files;
 		goto bail;
 	}
 
-	/* If there is no hole or unwritten extents in the file, free it. */
-	if (!file->unwritten && !file->holes) {
+	/*
+	 * If there is no hole or unwritten extents in the file and we don't
+	 * need to truncate it, just free it.
+	 */
+	if (!file->unwritten && !file->holes && !file->truncate) {
 		clear_ctxt.files = old_files;
 		goto bail;
 	}
@@ -832,6 +867,22 @@ next_file:
 		file = file->next;
 	}
 
+	/* Iterate all the files and truncate them if needed. */
+	file = clear_ctxt.files;
+	while (file) {
+		if (file->truncate) {
+			ret = ocfs2_read_inode(fs, file->blkno, buf);
+			if (ret)
+				goto bail;
+
+			di = (struct ocfs2_dinode *)buf;
+			ret = truncate_file(fs, di);
+			if (ret)
+				goto bail;
+		}
+		file = file->next;
+	}
+
 	if(ocfs2_writes_unwritten_extents(super))
 		OCFS2_CLEAR_RO_COMPAT_FEATURE(super,
 					 OCFS2_FEATURE_RO_COMPAT_UNWRITTEN);
-- 
1.5.3.2.g4f337



More information about the Ocfs2-tools-devel mailing list