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

Tao Ma tao.ma at oracle.com
Mon Nov 12 22:59:08 PST 2007


When we remove "sparse" flag from the OCFS2 volume, we need to truncate
all the blocks that exceed i_size. They are illegal in a non-sparse
OCFS2 system.

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..427dae9 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;
 	}
@@ -763,7 +798,23 @@ errcode_t clear_sparse_file_flag(ocfs2_filesys *fs, char *progname)
 	if (clear_ctxt.unwritten_only)
 		goto fill_unwritten;
 
+	/* Iterate all the files and truncate them if needed. */
+	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;
+	}
+
 	/* Iterate all the holes and fill them. */
+	file = clear_ctxt.files;
 	while (file) {
 		hole = file->holes;
 		while (hole) {
-- 
1.5.3.2.g4f337



More information about the Ocfs2-tools-devel mailing list