[Ocfs2-tools-devel] [PATCH 10/15] dx_dirs v11: add disable indexed-dirs support in tunefs.ocfs2

Coly Li coly.li at suse.de
Sun Apr 11 01:10:07 PDT 2010


This patch truncates all directories' indexed tree if '--fs-features
noindexed-tree' option is given. The indexed dirs
related flags on directory inodes and superblock are cleared too.

Signed-off-by: Coly Li <coly.li at suse.de>
Acked-by: Mark Fasheh <mfasheh at suse.com>
---
 tunefs.ocfs2/feature_indexed_dirs.c |  192 ++++++++++++++++++++++++++++++++++-
 tunefs.ocfs2/o2ne_err.et            |    9 ++
 2 files changed, 199 insertions(+), 2 deletions(-)

diff --git a/tunefs.ocfs2/feature_indexed_dirs.c b/tunefs.ocfs2/feature_indexed_dirs.c
index 368eb87..e9f87fb 100644
--- a/tunefs.ocfs2/feature_indexed_dirs.c
+++ b/tunefs.ocfs2/feature_indexed_dirs.c
@@ -6,7 +6,7 @@
  * ocfs2 tune utility for enabling and disabling the directory indexing
  * feature.
  *
- * Copyright (C) 2009 Novell.  All rights reserved.
+ * Copyright (C) 2009, 2010 Novell.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public
@@ -30,6 +30,17 @@
 
 #include "libocfs2ne.h"
 
+struct dx_dirs_inode {
+	struct list_head list;
+	uint64_t ino;
+};
+
+struct dx_dirs_context {
+	errcode_t ret;
+	uint64_t dx_dirs_nr;
+	struct list_head inodes;
+	struct tools_progress *prog;
+};
 
 static int enable_indexed_dirs(ocfs2_filesys *fs, int flags)
 {
@@ -71,6 +82,183 @@ out:
 	return ret;
 }
 
+static errcode_t dx_dir_iterate(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+				void *user_data)
+{
+	errcode_t ret = 0;
+	struct dx_dirs_inode *dx_di = NULL;
+	struct dx_dirs_context *ctxt= (struct dx_dirs_context *)user_data;
+
+	if (!S_ISDIR(di->i_mode))
+		goto bail;
+
+	if (!(di->i_dyn_features & OCFS2_INDEXED_DIR_FL))
+		goto bail;
+
+	ret = ocfs2_malloc0(sizeof(struct dx_dirs_inode), &dx_di);
+	if (ret) {
+		ret = TUNEFS_ET_NO_MEMORY;
+		goto bail;
+	}
+
+	dx_di->ino = di->i_blkno;
+	ctxt->dx_dirs_nr ++;
+	list_add_tail(&dx_di->list, &ctxt->inodes);
+
+	tools_progress_step(ctxt->prog, 1);
+
+bail:
+	return ret;
+}
+
+
+static errcode_t find_indexed_dirs(ocfs2_filesys *fs,
+				   struct dx_dirs_context *ctxt)
+{
+	errcode_t ret;
+
+	ctxt->prog = tools_progress_start("Scanning filesystem", "scanning", 0);
+	if (!ctxt->prog) {
+		ret = TUNEFS_ET_NO_MEMORY;
+		goto bail;
+	}
+
+	ret = tunefs_foreach_inode(fs, dx_dir_iterate, ctxt);
+	if (ret) {
+		if (ret != TUNEFS_ET_NO_MEMORY)
+			ret = TUNEFS_ET_DX_DIRS_SCAN_FAILED;
+		goto bail;
+	}
+
+	verbosef(VL_APP,
+		"We have %lu indexed %s to truncate.\n",
+		ctxt->dx_dirs_nr,
+		(ctxt->dx_dirs_nr > 1)?"directories":"directory");
+
+bail:
+	if (ctxt->prog)
+		tools_progress_stop(ctxt->prog);
+
+	return ret;
+}
+
+static errcode_t clean_indexed_dirs(ocfs2_filesys *fs,
+				    struct dx_dirs_context *ctxt)
+{
+	errcode_t ret = 0;
+	struct list_head *pos;
+	struct dx_dirs_inode *dx_di;
+	struct tools_progress *prog;
+	uint64_t dirs_truncated = 0;
+
+	prog = tools_progress_start("Truncating indexed dirs", "truncating",
+				    ctxt->dx_dirs_nr);
+	if (!prog) {
+		ret = TUNEFS_ET_NO_MEMORY;
+		goto bail;
+	}
+
+	list_for_each(pos, &ctxt->inodes) {
+		dx_di = list_entry(pos, struct dx_dirs_inode, list);
+
+		ret = ocfs2_dx_dir_truncate(fs, dx_di->ino);
+		if (ret) {
+			verbosef(VL_APP,
+				"Truncate directory (ino \"%lu\") failed.",
+				dx_di->ino);
+			ret = TUNEFS_ET_DX_DIRS_TRUNCATE_FAILED;
+			goto bail;
+		}
+		dirs_truncated ++;
+		tools_progress_step(prog, 1);
+	}
+
+bail:
+	tools_progress_stop(prog);
+	verbosef(VL_APP,
+		"\"%lu\" from \"%lu\" indexed %s truncated.",
+		dirs_truncated, ctxt->dx_dirs_nr,
+		(dirs_truncated <= 1) ? "directory is" : "directories are");
+
+	return ret;
+}
+
+static void release_dx_dirs_context(struct dx_dirs_context *ctxt)
+{
+	struct list_head *pos, *n;
+	struct dx_dirs_inode *dx_di;
+
+	list_for_each_safe(pos, n, &ctxt->inodes) {
+		dx_di = list_entry(pos, struct dx_dirs_inode, list);
+		list_del(&dx_di->list);
+		ocfs2_free(&dx_di);
+	}
+}
+
+static int disable_indexed_dirs(ocfs2_filesys *fs, int flags)
+{
+	errcode_t ret = 0;
+	struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
+	struct dx_dirs_context ctxt;
+	struct tools_progress *prog = NULL;
+
+	if (!ocfs2_supports_indexed_dirs(super)) {
+		verbosef(VL_APP,
+			"Directory indexing feature is not enabled; "
+			"nothing to disable\n");
+		goto out;
+	}
+
+	if (!tools_interact("Disabling the directory indexing feature on "
+			    "device \"%s\"? ",
+			    fs->fs_devname))
+		goto out;
+
+	prog = tools_progress_start("Disable directory indexing", "no dir idx", 2);
+	if (!prog) {
+		ret = TUNEFS_ET_NO_MEMORY;
+		tcom_err(ret, "while initializing the progress display");
+		goto out;
+	}
+
+	memset(&ctxt, 0, sizeof (struct dx_dirs_context));
+	INIT_LIST_HEAD(&ctxt.inodes);
+	ret = find_indexed_dirs(fs, &ctxt);
+	if (ret) {
+		tcom_err(ret, "while scanning indexed directories");
+		goto out_cleanup;
+	}
+
+	tools_progress_step(prog, 1);
+
+	tunefs_block_signals();
+	ret = clean_indexed_dirs(fs, &ctxt);
+	if (ret) {
+		tcom_err(ret, "while truncate indexed directories");
+	}
+
+	/* We already touched file system, must disable dx dirs flag here.
+	 * fsck.ocfs2 will handle the orphan indexed trees. */
+	OCFS2_CLEAR_INCOMPAT_FEATURE(super,
+				     OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS);
+	ret = ocfs2_write_super(fs);
+	tunefs_unblock_signals();
+
+	if (ret) {
+		ret = TUNEFS_ET_IO_WRITE_FAILED;
+		tcom_err(ret, "while writing super block");
+	}
+
+	tools_progress_step(prog, 1);
+out_cleanup:
+	release_dx_dirs_context(&ctxt);
+out:
+	if (prog)
+		tools_progress_stop(prog);
+
+	return ret;
+}
+
 /*
  * TUNEFS_FLAG_ALLOCATION because disabling will want to dealloc
  * blocks.
@@ -79,7 +267,7 @@ DEFINE_TUNEFS_FEATURE_INCOMPAT(indexed_dirs,
 			       OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS,
 			       TUNEFS_FLAG_RW | TUNEFS_FLAG_ALLOCATION,
 			       enable_indexed_dirs,
-			       NULL);
+			       disable_indexed_dirs);
 
 #ifdef DEBUG_EXE
 int main(int argc, char *argv[])
diff --git a/tunefs.ocfs2/o2ne_err.et b/tunefs.ocfs2/o2ne_err.et
index 20031a5..c2f700b 100644
--- a/tunefs.ocfs2/o2ne_err.et
+++ b/tunefs.ocfs2/o2ne_err.et
@@ -85,4 +85,13 @@ ec	TUNEFS_ET_ONLINE_NOT_SUPPORTED,
 ec	TUNEFS_ET_CLUSTER_SKIPPED,
 	"Cluster stack initialization was skipped"
 
+ec	TUNEFS_ET_DX_DIRS_SCAN_FAILED,
+	"Scanning inodes for directory indexing failed"
+
+ec	TUNEFS_ET_IO_WRITE_FAILED,
+	"Write I/O failed"
+
+ec	TUNEFS_ET_DX_DIRS_TRUNCATE_FAILED,
+	"Truncate directory indexed tree failed"
+
 	end
-- 
1.7.0.2




More information about the Ocfs2-tools-devel mailing list