[Ocfs2-tools-devel] [PATCH 2/2] tunefs: support for turning off unwritten extents

Mark Fasheh mark.fasheh at oracle.com
Thu Nov 8 11:01:27 PST 2007


This can just make re-use of the inode walk which is done for clearing the
sparse files flag.

Signed-off-by: Mark Fasheh <mark.fasheh at oracle.com>
---
 tunefs.ocfs2/features.c    |   30 +++++++++++++++++++++++++++---
 tunefs.ocfs2/sparse_file.c |   31 +++++++++++++++++++++++++------
 tunefs.ocfs2/tunefs.h      |    3 ++-
 3 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/tunefs.ocfs2/features.c b/tunefs.ocfs2/features.c
index 69c0a8a..856e833 100644
--- a/tunefs.ocfs2/features.c
+++ b/tunefs.ocfs2/features.c
@@ -32,7 +32,7 @@ extern ocfs2_tune_opts opts;
 #define TUNEFS_COMPAT_SET	0
 #define TUNEFS_COMPAT_CLEAR	0
 #define TUNEFS_RO_COMPAT_SET	OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
-#define TUNEFS_RO_COMPAT_CLEAR	0
+#define TUNEFS_RO_COMPAT_CLEAR	OCFS2_FEATURE_RO_COMPAT_UNWRITTEN
 #define TUNEFS_INCOMPAT_SET	OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC
 #define TUNEFS_INCOMPAT_CLEAR	OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC
 
@@ -73,8 +73,15 @@ errcode_t feature_check(ocfs2_filesys *fs)
 		if (!ocfs2_sparse_alloc(OCFS2_RAW_SB(fs->fs_super)))
 			goto bail;
 
+		/*
+		 * Turning off sparse files means we must also turn
+		 * off unwritten extents.
+		 */
+		if (ocfs2_writes_unwritten_extents(OCFS2_RAW_SB(fs->fs_super)))
+			opts.clear_feature.ro_compat |= OCFS2_FEATURE_RO_COMPAT_UNWRITTEN;
+
 		sparse_on = 0;
-		ret = clear_sparse_file_check(fs, opts.progname);
+		ret = clear_sparse_file_check(fs, opts.progname, 0);
 		if (ret)
 			goto bail;
 	}
@@ -95,6 +102,21 @@ errcode_t feature_check(ocfs2_filesys *fs)
 		if (OCFS2_HAS_RO_COMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super),
 					OCFS2_FEATURE_RO_COMPAT_UNWRITTEN))
 		    goto bail;
+	} else if (opts.clear_feature.ro_compat &
+		   OCFS2_FEATURE_RO_COMPAT_UNWRITTEN) {
+		if (!ocfs2_writes_unwritten_extents(OCFS2_RAW_SB(fs->fs_super)))
+			goto bail;
+
+		if (sparse_on) {
+			/*
+			 * If we haven't run through the file system
+			 * yet, do it now in order to build up our
+			 * list of files with unwritten extents.
+			 */
+			ret = clear_sparse_file_check(fs, opts.progname, 1);
+			if (ret)
+				goto bail;
+		}
 	}
 
 	ret = 0;
@@ -109,7 +131,9 @@ errcode_t update_feature(ocfs2_filesys *fs)
 	if (opts.set_feature.incompat & OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC)
 		ret = set_sparse_file_flag(fs, opts.progname);
 	else if (opts.clear_feature.incompat
-		 & OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC)
+		 & OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC ||
+		 opts.clear_feature.ro_compat
+		 & OCFS2_FEATURE_RO_COMPAT_UNWRITTEN)
 		ret = clear_sparse_file_flag(fs, opts.progname);
 	if (ret)
 		goto bail;
diff --git a/tunefs.ocfs2/sparse_file.c b/tunefs.ocfs2/sparse_file.c
index 2d2ba01..8ef6710 100644
--- a/tunefs.ocfs2/sparse_file.c
+++ b/tunefs.ocfs2/sparse_file.c
@@ -26,6 +26,8 @@
 #include <tunefs.h>
 #include <assert.h>
 
+extern ocfs2_tune_opts opts;
+
 struct multi_link_file {
 	struct rb_node br_node;
 	uint64_t blkno;
@@ -76,8 +78,10 @@ struct sparse_file {
 
 struct clear_hole_unwritten_ctxt {
 	errcode_t ret;
+	int unwritten_only;
 	uint32_t more_clusters;
 	uint32_t more_ebs;
+	uint32_t total_unwritten;
 	struct sparse_file *files;
 };
 
@@ -588,6 +592,9 @@ static void add_hole(void *priv_data, uint32_t hole_start, uint32_t hole_len)
 	struct clear_hole_unwritten_ctxt *ctxt =
 			(struct clear_hole_unwritten_ctxt *)priv_data;
 
+	if (clear_ctxt.unwritten_only)
+		return;
+
 	ret = ocfs2_malloc0(sizeof(struct hole_list), &hole);
 	if (ret) {
 		ctxt->ret = ret;
@@ -617,6 +624,8 @@ static void add_unwritten(void *priv_data, uint32_t start,
 		return;
 	}
 
+	clear_ctxt.total_unwritten += len;
+
 	unwritten->start = start;
 	unwritten->len = len;
 	unwritten->p_start = p_start;
@@ -674,12 +683,15 @@ bail:
 	return ret;
 }
 
-errcode_t clear_sparse_file_check(ocfs2_filesys *fs, char *progname)
+errcode_t clear_sparse_file_check(ocfs2_filesys *fs, char *progname,
+				  int unwritten_only)
 {
 	errcode_t ret;
 	uint32_t free_clusters = 0;
 
 	memset(&clear_ctxt, 0, sizeof(clear_ctxt));
+	clear_ctxt.unwritten_only = unwritten_only;
+
 	ret = iterate_all_regular(fs, progname, calc_hole_and_unwritten);
 	if (ret)
 		goto bail;
@@ -688,9 +700,11 @@ errcode_t clear_sparse_file_check(ocfs2_filesys *fs, char *progname)
 	if (ret)
 		goto bail;
 
-	printf("We have %u clusters free and need %u clusters for sparse files "
-		"and %u clusters for more extent blocks\n",
-		free_clusters, clear_ctxt.more_clusters, clear_ctxt.more_ebs);
+	printf("We have %u clusters free and need %u clusters for sparse "
+	       "files, %u clusters for more extent blocks and will need to "
+	       "clear %u clusters of unwritten extents.\n",
+	       free_clusters, clear_ctxt.more_clusters, clear_ctxt.more_ebs,
+	       clear_ctxt.total_unwritten);
 
 	if (free_clusters < clear_ctxt.more_clusters + clear_ctxt.more_ebs) {
 		com_err(progname, 0, "Don't have enough free space.");
@@ -746,6 +760,9 @@ errcode_t clear_sparse_file_flag(ocfs2_filesys *fs, char *progname)
 	if (ret)
 		goto bail;
 
+	if (clear_ctxt.unwritten_only)
+		goto fill_unwritten;
+
 	/* Iterate all the holes and fill them. */
 	while (file) {
 		hole = file->holes;
@@ -785,6 +802,7 @@ errcode_t clear_sparse_file_flag(ocfs2_filesys *fs, char *progname)
 	 * mark it written.
 	 */
 	file = clear_ctxt.files;
+fill_unwritten:
 	while (file) {
 		if (!file->unwritten)
 			goto next_file;
@@ -818,8 +836,9 @@ next_file:
 		OCFS2_CLEAR_RO_COMPAT_FEATURE(super,
 					 OCFS2_FEATURE_RO_COMPAT_UNWRITTEN);
 
-	OCFS2_CLEAR_INCOMPAT_FEATURE(super,
-				     OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC);
+	if (!clear_ctxt.unwritten_only)
+		OCFS2_CLEAR_INCOMPAT_FEATURE(super,
+					OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC);
 
 bail:
 	return ret;
diff --git a/tunefs.ocfs2/tunefs.h b/tunefs.ocfs2/tunefs.h
index e7f8c88..566d746 100644
--- a/tunefs.ocfs2/tunefs.h
+++ b/tunefs.ocfs2/tunefs.h
@@ -105,7 +105,8 @@ errcode_t remove_slot_check(ocfs2_filesys *fs);
 
 errcode_t list_sparse(ocfs2_filesys *fs);
 errcode_t set_sparse_file_flag(ocfs2_filesys *fs, char *progname);
-errcode_t clear_sparse_file_check(ocfs2_filesys *fs, char *progname);
+errcode_t clear_sparse_file_check(ocfs2_filesys *fs, char *progname,
+				  int unwritten_only);
 errcode_t clear_sparse_file_flag(ocfs2_filesys *fs, char *progname);
 void set_unwritten_extents_flag(ocfs2_filesys *fs);
 void free_clear_ctxt(void);
-- 
1.5.0.6




More information about the Ocfs2-tools-devel mailing list