[Ocfs2-tools-devel] [PATCH 14/20] tunefs.ocfs2: Add support for disabling discontig-bg.

Tao Ma tao.ma at oracle.com
Mon May 17 01:47:01 PDT 2010


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

diff --git a/tunefs.ocfs2/feature_discontig_bg.c b/tunefs.ocfs2/feature_discontig_bg.c
index caba0d9..6c903f1 100644
--- a/tunefs.ocfs2/feature_discontig_bg.c
+++ b/tunefs.ocfs2/feature_discontig_bg.c
@@ -68,12 +68,257 @@ out:
 	return ret;
 }
 
+struct discontig_bg {
+	uint64_t bg_blkno;
+	struct discontig_bg *next;
+};
+
+struct no_discontig_bg_ctxt {
+	ocfs2_filesys *fs;
+	struct tools_progress *prog;
+	char *bg_buf;
+	errcode_t ret;
+	int has_discontig;
+	struct discontig_bg *bg_list;
+};
+
+/*
+ * Check whether the gd_blkno is a discontig block group, and
+ * if yes set has_discontig and abort.
+ * It also check whether bg_size is a new value, if yes, add
+ * it to the list so that we can change it later.
+ */
+static int check_discontig_bg(ocfs2_filesys *fs, uint64_t gd_blkno,
+			     int chain_num, void *priv_data)
+{
+	struct no_discontig_bg_ctxt *ctxt = priv_data;
+	struct ocfs2_group_desc *gd;
+	struct discontig_bg *bg;
+
+	ctxt->ret = ocfs2_read_group_desc(fs, gd_blkno, ctxt->bg_buf);
+	if (ctxt->ret) {
+		tcom_err(ctxt->ret, "while reading group descriptor %"PRIu64,
+			 gd_blkno);
+		return OCFS2_CHAIN_ERROR;
+	}
+
+	gd = (struct ocfs2_group_desc *)ctxt->bg_buf;
+
+	if (ocfs2_gd_is_discontig(gd)) {
+		ctxt->has_discontig = 1;
+		return OCFS2_CHAIN_ABORT;
+	}
+
+	if (gd->bg_size == ocfs2_group_bitmap_size(fs->fs_blocksize, 0,
+			OCFS2_RAW_SB(fs->fs_super)->s_feature_incompat))
+		return 0;
+
+	/*
+	 * OK, now the gd isn't discontiguous while bg_size has
+	 * the new size. Record it so that we can change it later.
+	 */
+	ctxt->ret = ocfs2_malloc0(sizeof(struct discontig_bg), &bg);
+	if (ctxt->ret) {
+		tcom_err(ctxt->ret, "while allocating discontig_bg");
+		return OCFS2_CHAIN_ABORT;
+	}
+
+	bg->bg_blkno = gd_blkno;
+	bg->next = ctxt->bg_list;
+	ctxt->bg_list = bg;
+	return 0;
+}
+
+static errcode_t find_discontig_bg(struct no_discontig_bg_ctxt *ctxt)
+{
+	int i, iret;
+	uint64_t blkno;
+
+	ctxt->prog = tools_progress_start("Scanning suballocators",
+					  "scanning", 0);
+	if (!ctxt->prog) {
+		ctxt->ret = TUNEFS_ET_NO_MEMORY;
+		tcom_err(ctxt->ret, "while initializing the progress display");
+		goto out;
+	}
+
+	/* iterate every inode_alloc first. */
+	for (i = 0; i < OCFS2_RAW_SB(ctxt->fs->fs_super)->s_max_slots; i++) {
+		ctxt->ret = ocfs2_lookup_system_inode(ctxt->fs,
+						INODE_ALLOC_SYSTEM_INODE,
+						i, &blkno);
+		if (ctxt->ret) {
+			tcom_err(ctxt->ret, "while finding inode alloc %d", i);
+			goto out;
+		}
+
+		iret = ocfs2_chain_iterate(ctxt->fs, blkno,
+					   check_discontig_bg, ctxt);
+		if (ctxt->ret) {
+			tcom_err(ctxt->ret, "while iterating inode alloc "
+				 "%d", i);
+			goto out;
+		}
+		if (iret == OCFS2_CHAIN_ABORT || iret == OCFS2_CHAIN_ERROR)
+			goto out;
+		tools_progress_step(ctxt->prog, 1);
+	}
+
+	/* iterate every extent_alloc now. */
+	for (i = 0; i < OCFS2_RAW_SB(ctxt->fs->fs_super)->s_max_slots; i++) {
+		ctxt->ret = ocfs2_lookup_system_inode(ctxt->fs,
+						EXTENT_ALLOC_SYSTEM_INODE,
+						i, &blkno);
+		if (ctxt->ret) {
+			tcom_err(ctxt->ret, "while finding extent alloc %d", i);
+			goto out;
+		}
+
+		iret = ocfs2_chain_iterate(ctxt->fs, blkno,
+					   check_discontig_bg, ctxt);
+		if (ctxt->ret) {
+			tcom_err(ctxt->ret, "while iterating extent alloc "
+				 "%d", i);
+			goto out;
+		}
+		if (iret == OCFS2_CHAIN_ABORT || iret == OCFS2_CHAIN_ERROR)
+			goto out;
+		tools_progress_step(ctxt->prog, 1);
+	}
+
+out:
+	if (ctxt->prog) {
+		tools_progress_stop(ctxt->prog);
+		ctxt->prog = NULL;
+	}
+
+	return ctxt->ret;
+}
+
+static errcode_t change_bg_size(struct no_discontig_bg_ctxt *ctxt)
+{
+	errcode_t ret = 0;
+	uint64_t bg_blkno;
+	struct discontig_bg *bg;
+	struct ocfs2_group_desc *gd;
+
+	while (ctxt->bg_list) {
+		bg = ctxt->bg_list;
+		ctxt->bg_list = bg->next;
+		bg_blkno = bg->bg_blkno;
+		ocfs2_free(&bg);
+
+		ret = ocfs2_read_group_desc(ctxt->fs, bg_blkno, ctxt->bg_buf);
+		if (ret) {
+			tcom_err(ctxt->ret, "while reading group descriptor "
+				 "%"PRIu64, bg_blkno);
+			goto out;
+		}
+
+		gd = (struct ocfs2_group_desc *)ctxt->bg_buf;
+
+		gd->bg_size = ocfs2_group_bitmap_size(ctxt->fs->fs_blocksize,
+						      0, 0);
+
+		ret = ocfs2_write_group_desc(ctxt->fs,
+					     bg_blkno, ctxt->bg_buf);
+		if (ret) {
+			tcom_err(ctxt->ret, "while writing group descriptor "
+				 "%"PRIu64, bg->bg_blkno);
+			goto out;
+		}
+	}
+
+out:
+	return ret;
+}
+
+static int disable_discontig_bg(ocfs2_filesys *fs, int flags)
+{
+	errcode_t ret = 0;
+	struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
+	struct tools_progress *prog;
+	struct no_discontig_bg_ctxt ctxt;
+	struct discontig_bg *tmp;
+
+	memset(&ctxt, 0, sizeof(ctxt));
+
+	if (!ocfs2_supports_discontig_bg(super)) {
+		verbosef(VL_APP,
+			 "Discontiguous block group feature is already "
+			 "disabled; nothing to disable\n");
+		goto out;
+	}
+
+	if (!tools_interact("Disable the discontiguous block group feature on "
+			    "device \"%s\"? ",
+			    fs->fs_devname))
+		goto out;
+
+	prog = tools_progress_start("Enable discontig block group",
+				    "nodiscontig-bg", 4);
+	if (!prog) {
+		ret = TUNEFS_ET_NO_MEMORY;
+		tcom_err(ret, "while initializing the progress display");
+		goto out;
+	}
+
+	ctxt.fs = fs;
+	ret = ocfs2_malloc_block(fs->fs_io, &ctxt.bg_buf);
+	if (ret) {
+		tcom_err(ret, "while mallocing blocks for group read");
+		goto out;
+	}
+
+	ret = find_discontig_bg(&ctxt);
+	if (ret) {
+		tcom_err(ret, "while finding discontiguous block group");
+		goto out;
+	}
+
+	tools_progress_step(prog, 1);
+
+	if (ctxt.has_discontig) {
+		tcom_err(0, "We can't disable discontig feature while "
+			 "we have some discontiguous block groups");
+		goto out;
+	}
+
+	ret = change_bg_size(&ctxt);
+	if (ret) {
+		tcom_err(ret, "while changing bg size for block group");
+		goto out;
+	}
+
+	OCFS2_CLEAR_INCOMPAT_FEATURE(super,
+				     OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG);
+	tunefs_block_signals();
+	ret = ocfs2_write_super(fs);
+	tunefs_unblock_signals();
+	if (ret)
+		tcom_err(ret, "while writing out the superblock");
+
+	tools_progress_step(prog, 1);
+out:
+	if (ctxt.bg_buf)
+		ocfs2_free(&ctxt.bg_buf);
+	while (ctxt.bg_list) {
+		tmp = ctxt.bg_list;
+		ctxt.bg_list = tmp->next;
+		ocfs2_free(&tmp);
+	}
+
+	if (prog)
+		tools_progress_stop(prog);
+	return ret;
+}
+
 DEFINE_TUNEFS_FEATURE_INCOMPAT(discontig_bg,
 			       OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG,
 			       TUNEFS_FLAG_RW | TUNEFS_FLAG_ALLOCATION |
 			       TUNEFS_FLAG_LARGECACHE,
 			       enable_discontig_bg,
-			       NULL);
+			       disable_discontig_bg);
 
 #ifdef DEBUG_EXE
 int main(int argc, char *argv[])
-- 
1.5.5




More information about the Ocfs2-tools-devel mailing list