Skip to contentSkip to conversation

Add online resize for ocfs2-tools,take 3

PATCH In review tao.ma 3 participants 19 messages Dec 17, 2007 – Jan 4, 2008 OCFS2

lore
Share & tools
lore

tao.ma

author
#0 lore raw

cover Add online resize for ocfs2-tools,take 3

Add online resize in tunefs.ocfs2 so that user can increase the volume when it is mounted.

author
#4 lore raw

PATCH 2/6 Abstract some specific process in resize to some individual function.take 3

Some process may be different for online and offline resize, so move them to different functions for future change.

---
 tunefs.ocfs2/resize.c |  248 ++++++++++++++++++++++++++++--------------------
 1 files changed, 145 insertions(+), 103 deletions(-)
tunefs.ocfs2/resize.c +145 -103
index be5ea6b..0466d60 100644
@@ -85,15 +85,152 @@ int validate_vol_size(ocfs2_filesys *fs)
 	return 0;
 }
 
+/*
+ * Initalize the group descriptors in the new added cluster range.
+ *
+ * di: global_bitmap's inode info.
+ * first_new_cluster: the start cluster offset.
+ * num_new_cluster: cluster range length.
+ * chain: the chain position of the last group descriptor. the new
+ *        group will be added to the chain after this one.
+ * total_bits and used_bits will be added according to the new groups.
+ */
+static errcode_t init_new_gd(ocfs2_filesys *fs,
+			     struct ocfs2_dinode *di,
+			     uint32_t first_new_cluster,
+			     uint32_t num_new_clusters,
+			     uint16_t chain,
+			     uint32_t *total_bits,
+			     uint32_t *used_bits)
+{
+	errcode_t ret = 0;
+	uint32_t cluster_chunk;
+	uint64_t gd_blkno = 0;
+	struct ocfs2_chain_list *cl = &di->id2.i_chain;
+	struct ocfs2_chain_rec *cr = NULL;
+	struct ocfs2_group_desc *gd = NULL;
+	char *zero_buf = NULL;
+	char *gd_buf = NULL;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &gd_buf);
+	if (ret) {
+		com_err(opts.progname, ret, "while allocating a block during "
+			"volume resize");
+		goto bail;
+	}
+
+	ret = ocfs2_malloc_blocks(fs->fs_io, ocfs2_clusters_to_blocks(fs, 1),
+				  &zero_buf);
+	if (ret) {
+		com_err(opts.progname, ret, "while allocating a cluster during "
+			"volume resize");
+		goto bail;
+	}
+
+	memset(zero_buf, 0, fs->fs_clustersize);
+	gd = (struct ocfs2_group_desc *)gd_buf;
+
+	while(num_new_clusters) {
+		gd_blkno = ocfs2_which_cluster_group(fs, cl->cl_cpg,
+						     first_new_cluster);
+		cluster_chunk = MIN(num_new_clusters, cl->cl_cpg);
+		num_new_clusters -= cluster_chunk;
+		first_new_cluster += cluster_chunk;
+
+		if (++chain >= cl->cl_count)
+			chain = 0;
+
+		ocfs2_init_group_desc(fs, gd, gd_blkno,
+				      fs->fs_super->i_fs_generation, di->i_blkno,
+				      (cluster_chunk *cl->cl_bpc), chain);
+
+		/* Add group to chain */
+		cr = &(cl->cl_recs[chain]);
+		if (chain >= cl->cl_next_free_rec) {
+			cl->cl_next_free_rec++;
+			cr->c_free = 0;
+			cr->c_total = 0;
+			cr->c_blkno = 0;
+		}
+
+		gd->bg_next_group = cr->c_blkno;
+		cr->c_blkno = gd_blkno;
+		cr->c_free += gd->bg_free_bits_count;
+		cr->c_total += gd->bg_bits;
+
+		*used_bits += (gd->bg_bits - gd->bg_free_bits_count);
+		*total_bits += gd->bg_bits;
+
+		fs->fs_clusters += cluster_chunk;
+		fs->fs_blocks += ocfs2_clusters_to_blocks(fs, cluster_chunk);
+
+		/* Initialize the first cluster in the group */
+		ret = io_write_block(fs->fs_io, gd_blkno,
+				     ocfs2_clusters_to_blocks(fs, 1), zero_buf);
+		if (ret) {
+			com_err(opts.progname, ret, "while initializing the "
+				"cluster starting at block %"PRIu64" during "
+				"volume resize", gd_blkno);
+			goto bail;
+		}
+
+		/* write a new group descriptor */
+		ret = ocfs2_write_group_desc(fs, gd_blkno, gd_buf);
+		if (ret) {
+			com_err(opts.progname, ret, "while writing group "
+				"descriptor at block %"PRIu64" during "
+				"volume resize", gd_blkno);
+			goto bail;
+		}
+	}
+
+bail:
+	if (zero_buf)
+		ocfs2_free(&zero_buf);
+	if (gd_buf)
+		ocfs2_free(&gd_buf);
+	return ret;
+}
+
+static errcode_t update_global_bitmap(ocfs2_filesys *fs,
+				      struct ocfs2_dinode *di,
+				      struct ocfs2_group_desc *lgd,
+				      int flush_lgd)
+{
+	errcode_t ret = 0;
+
+	block_signals(SIG_BLOCK);
+	/* Flush that last group descriptor we updated before the new ones */
+	if (flush_lgd) {
+		ret = ocfs2_write_group_desc(fs, lgd->bg_blkno, (char *)lgd);
+		if (ret) {
+			com_err(opts.progname, ret, "while flushing group "
+				"descriptor at block %"PRIu64" during "
+				"volume resize", lgd->bg_blkno);
+			goto bail;
+		}
+	}
+
+	/* write the global bitmap inode */
+	ret = ocfs2_write_inode(fs, di->i_blkno, (char *)di);
+	if (ret) {
+		com_err(opts.progname, ret, "while writing global bitmap "
+			"inode at block %"PRIu64" during volume resize",
+			di->i_blkno);
+	}
+
+bail:
+	block_signals(SIG_UNBLOCK);
+	return ret;
+}
+
 errcode_t update_volume_size(ocfs2_filesys *fs, int *changed)
 {
 	errcode_t ret = 0;
 	struct ocfs2_dinode *di;
 	uint64_t bm_blkno = 0;
-	uint64_t gd_blkno = 0;
 	uint64_t lgd_blkno = 0;
 	char *in_buf = NULL;
-	char *gd_buf = NULL;
 	char *lgd_buf = NULL;
 	struct ocfs2_chain_list *cl;
 	struct ocfs2_chain_rec *cr;
@@ -106,7 +243,6 @@ errcode_t update_volume_size(ocfs2_filesys *fs, int *changed)
 	uint32_t total_bits;
 	uint32_t num_bits;
 	int flush_lgd = 0;
-	char *zero_buf = NULL;
 
 	ret = ocfs2_malloc_block(fs->fs_io, &in_buf);
 	if (ret) {
@@ -115,13 +251,6 @@ errcode_t update_volume_size(ocfs2_filesys *fs, int *changed)
 		goto bail;
 	}
 
-	ret = ocfs2_malloc_block(fs->fs_io, &gd_buf);
-	if (ret) {
-		com_err(opts.progname, ret, "while allocating a block during "
-			"volume resize");
-		goto bail;
-	}
-
 	ret = ocfs2_malloc_block(fs->fs_io, &lgd_buf);
 	if (ret) {
 		com_err(opts.progname, ret, "while allocating a block during "
@@ -129,16 +258,6 @@ errcode_t update_volume_size(ocfs2_filesys *fs, int *changed)
 		goto bail;
 	}
 
-	ret = ocfs2_malloc_blocks(fs->fs_io, ocfs2_clusters_to_blocks(fs, 1),
-				  &zero_buf);
-	if (ret) {
-		com_err(opts.progname, ret, "while allocating a cluster during "
-			"volume resize");
-		goto bail;
-	}
-
-	memset(zero_buf, 0, fs->fs_clustersize);
-
 	/* read global bitmap */
 	ret = ocfs2_lookup_system_inode(fs, GLOBAL_BITMAP_SYSTEM_INODE, 0,
 					&bm_blkno);
@@ -214,62 +333,10 @@ errcode_t update_volume_size(ocfs2_filesys *fs, int *changed)
 	/* Init the new groups and write to disk */
 	/* Add these groups one by one starting from the first chain after */
 	/* the one containing the last group */
-
-	gd = (struct ocfs2_group_desc *)gd_buf;
-
-	while(num_new_clusters) {
-		gd_blkno = ocfs2_which_cluster_group(fs, cl->cl_cpg,
-						     first_new_cluster);
-		cluster_chunk = MIN(num_new_clusters, cl->cl_cpg);
-		num_new_clusters -= cluster_chunk;
-		first_new_cluster += cluster_chunk;
-
-		if (++chain >= cl->cl_count)
-			chain = 0;
-
-		ocfs2_init_group_desc(fs, gd, gd_blkno,
-				      fs->fs_super->i_fs_generation, di->i_blkno,
-				      (cluster_chunk *cl->cl_bpc), chain);
-
-		/* Add group to chain */
-		cr = &(cl->cl_recs[chain]);
-		if (chain >= cl->cl_next_free_rec) {
-			cl->cl_next_free_rec++;
-			cr->c_free = 0;
-			cr->c_total = 0;
-			cr->c_blkno = 0;
-		}
-
-		gd->bg_next_group = cr->c_blkno;
-		cr->c_blkno = gd_blkno;
-		cr->c_free += gd->bg_free_bits_count;
-		cr->c_total += gd->bg_bits;
-
-		used_bits += (gd->bg_bits - gd->bg_free_bits_count);
-		total_bits += gd->bg_bits;
-
-		fs->fs_clusters += cluster_chunk;
-		fs->fs_blocks += ocfs2_clusters_to_blocks(fs, cluster_chunk);
-
-		/* Initialize the first cluster in the group */
-		ret = io_write_block(fs->fs_io, gd_blkno,
-				     ocfs2_clusters_to_blocks(fs, 1), zero_buf);
-		if (ret) {
-			com_err(opts.progname, ret, "while initializing the "
-				"cluster starting at block %"PRIu64" during "
-				"volume resize", gd_blkno);
-			goto bail;
-		}
-
-		/* write a new group descriptor */
-		ret = ocfs2_write_group_desc(fs, gd_blkno, gd_buf);
-		if (ret) {
-			com_err(opts.progname, ret, "while writing group "
-				"descriptor at block %"PRIu64" during "
-				"volume resize", gd_blkno);
-			goto bail;
-		}
-	}
+	ret = init_new_gd(fs, di, first_new_cluster,
+			  num_new_clusters, chain, &total_bits, &used_bits);
+	if (ret)
+		goto bail;
 
 	di->id1.bitmap1.i_total = total_bits;
 	di->id1.bitmap1.i_used = used_bits;
@@ -279,40 +346,15 @@ errcode_t update_volume_size(ocfs2_filesys *fs, int *changed)
 
 	fs->fs_super->i_clusters = di->i_clusters;
 
-	block_signals(SIG_BLOCK);
-	/* Flush that last group descriptor we updated before the new ones */
-	if (flush_lgd) {
-		ret = ocfs2_write_group_desc(fs, lgd_blkno, lgd_buf);
-		if (ret) {
-			block_signals(SIG_UNBLOCK);
-			com_err(opts.progname, ret, "while flushing group "
-				"descriptor at block %"PRIu64" during "
-				"volume resize", lgd_blkno);
-			goto bail;
-		}
-	}
-
-	/* write the global bitmap inode */
-	ret = ocfs2_write_inode(fs, bm_blkno, in_buf);
-	if (ret) {
-		block_signals(SIG_UNBLOCK);
-		com_err(opts.progname, ret, "while writing global bitmap "
-			"inode at block %"PRIu64" during volume resize",
-			bm_blkno);
+	ret = update_global_bitmap(fs, di, gd, flush_lgd);
+	if (ret)
 		goto bail;
-	}
-
-	block_signals(SIG_UNBLOCK);
 
 	*changed = 1;
 
 bail:
-	if (zero_buf)
-		ocfs2_free(&zero_buf);
 	if (in_buf)
 		ocfs2_free(&in_buf);
-	if (gd_buf)
-		ocfs2_free(&gd_buf);
 	if (lgd_buf)
 		ocfs2_free(&lgd_buf);
 
Signature · 1 line
gitgui.0.9.0.gd794
author
#6 lore raw

PATCH 3/6 Abstract checking and validating process in tunefs.ocfs2.take 3

In reply to tao.ma

In the main function of tunefs.ocfs2, there are a large number of checking and validating process. They are seperated and can be moved out of "main" so that future online resize can skip these check easily. So add 2 new function, volume_check and validate_parameter to organize the complicated process.

There are also 2 minor changes in this patch:
1. the print of "Adding backup superblock for the volume" are moved to validate process as others.
2. remove_slot_check is moved into function volume_check as it does the check work while it was in validate process.

---
 tunefs.ocfs2/tunefs.c |  267 +++++++++++++++++++++++++++----------------------
 1 files changed, 147 insertions(+), 120 deletions(-)
tunefs.ocfs2/tunefs.c +147 -120
index 207431c..cea9eb1 100644
@@ -30,6 +30,9 @@ ocfs2_tune_opts opts;
 ocfs2_filesys *fs_gbl = NULL;
 static int cluster_locked = 0;
 static int resize = 0;
+static uint64_t def_jrnl_size = 0;
+static char old_uuid[OCFS2_VOL_UUID_LEN * 2 + 1];
+static char new_uuid[OCFS2_VOL_UUID_LEN * 2 + 1];
 
 static void usage(const char *progname)
 {
@@ -997,6 +1000,145 @@ static void free_opts(void)
 		free(opts.device);
 }
 
+static errcode_t volume_check(ocfs2_filesys *fs)
+{
+	errcode_t ret;
+	int dirty = 0;
+	uint16_t max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
+
+	ret = journal_check(fs, &dirty, &def_jrnl_size);
+	if (ret || dirty)
+		goto bail;
+
+	ret = 1;
+	if (opts.list_sparse) {
+		if (!ocfs2_sparse_alloc(OCFS2_RAW_SB(fs->fs_super))) {
+			com_err(opts.progname, 0,
+				"sparse_file flag check failed. ");
+			goto bail;
+		}
+		printf("List all the sparse files in the volume\n");
+	}
+
+	if (opts.feature_string) {
+		if (feature_check(fs)) {
+			com_err(opts.progname, 0,
+				"feature check failed. ");
+			goto bail;
+		}
+		printf("Modify feature \"%s\" for the volume\n",
+			opts.feature_string);
+	}
+
+	/* If operation requires touching the global bitmap, ensure it is good */
+	/* This is to handle failed resize */
+	if (opts.num_blocks || opts.num_slots || opts.jrnl_size ||
+	    opts.backup_super) {
+		if (global_bitmap_check(fs)) {
+			com_err(opts.progname, 0, "Global bitmap check failed. "
+				"Run fsck.ocfs2 -f <device>.");
+			goto bail;
+		}
+	}
+
+	/* check whether the block for backup superblock are used. */
+	if (opts.backup_super) {
+		if (backup_super_check(fs))
+			goto bail;
+	}
+
+	/* remove slot check. */
+	if (opts.num_slots && opts.num_slots < max_slots) {
+		ret = remove_slot_check(fs);
+		if (ret) {
+			com_err(opts.progname, 0,
+				"remove slot check failed. ");
+			goto bail;
+		}
+	}
+
+	ret = 0;
+bail:
+	return ret;
+}
+
+static void validate_parameter(ocfs2_filesys *fs)
+{
+	uint16_t max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
+	uint64_t num_clusters;
+	char *tmpstr;
+
+	/* valid backup super. */
+	if (opts.backup_super)
+		printf("Adding backup superblock for the volume\n");
+
+	/* validate volume label */
+	if (opts.vol_label) {
+		printf("Changing volume label from %s to %s\n",
+		       OCFS2_RAW_SB(fs->fs_super)->s_label, opts.vol_label);
+	}
+
+	/* validate volume uuid */
+	if (opts.vol_uuid) {
+		uuid_unparse(OCFS2_RAW_SB(fs->fs_super)->s_uuid, old_uuid);
+		uuid_unparse(opts.vol_uuid, new_uuid);
+		printf("Changing volume uuid from %s to %s\n", old_uuid, new_uuid);
+	}
+
+	/* validate mount type */
+	if (opts.mount) {
+		if (!validate_mount_change(fs)) {
+			if (opts.mount == MOUNT_LOCAL)
+				tmpstr = MOUNT_LOCAL_STR;
+			else
+				tmpstr = MOUNT_CLUSTER_STR;
+			printf("Changing mount type to %s\n", tmpstr);
+		} else
+			opts.mount = 0;
+	}
+
+	/* validate num slots */
+	max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
+	if (opts.num_slots) {
+		if (opts.num_slots > max_slots) {
+			if (!opts.jrnl_size)
+				opts.jrnl_size = def_jrnl_size;
+
+		} else if (opts.num_slots == max_slots) {
+			printf("Giving the same number of nodes. "
+				"Ignore the change of slots.");
+			opts.num_slots = 0;
+		}
+
+		if (opts.num_slots)
+			printf("Changing number of node slots from %d to %d\n",
+			       max_slots, opts.num_slots);
+	}
+
+	/* validate journal size */
+	if (opts.jrnl_size) {
+		num_clusters = (opts.jrnl_size + fs->fs_clustersize - 1) >>
+				OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
+
+		opts.jrnl_size = num_clusters <<
+				OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
+
+		if (opts.jrnl_size != def_jrnl_size)
+			printf("Changing journal size %"PRIu64" to %"PRIu64"\n",
+			       def_jrnl_size, opts.jrnl_size);
+	}
+
+	/* validate volume size */
+	if (opts.num_blocks) {
+		if (validate_vol_size(fs))
+			opts.num_blocks = 0;
+		else
+			printf("Changing volume size from %"PRIu64" blocks to "
+			       "%"PRIu64" blocks\n", fs->fs_blocks,
+			       opts.num_blocks);
+	}
+}
+
 int main(int argc, char **argv)
 {
 	errcode_t ret = 0;
@@ -1011,14 +1153,8 @@ int main(int argc, char **argv)
 	int upd_incompat = 0;
 	int upd_backup_super = 0;
 	int upd_feature = 0;
-	char *tmpstr;
 	uint16_t max_slots;
-	uint64_t def_jrnl_size = 0;
-	uint64_t num_clusters;
 	uint64_t old_blocks = 0;
-	int dirty = 0;
-	char old_uuid[OCFS2_VOL_UUID_LEN * 2 + 1];
-	char new_uuid[OCFS2_VOL_UUID_LEN * 2 + 1];
 
 	initialize_ocfs_error_table();
 	initialize_o2dl_error_table();
@@ -1116,121 +1252,11 @@ int main(int argc, char **argv)
 	 */
 	io_init_cache(fs->fs_io, ocfs2_extent_recs_per_eb(fs->fs_blocksize));
 
-	ret = journal_check(fs, &dirty, &def_jrnl_size);
-	if (ret || dirty)
-		goto unlock;
-
-	if (opts.list_sparse) {
-		if (!ocfs2_sparse_alloc(OCFS2_RAW_SB(fs->fs_super))) {
-			com_err(opts.progname, 0,
-				"sparse_file flag check failed. ");
-			goto unlock;
-		}
-		printf("List all the sparse files in the volume\n");
-	}
-
-	if (opts.feature_string) {
-		if (feature_check(fs)) {
-			com_err(opts.progname, 0,
-				"feature check failed. ");
-			goto unlock;
-		}
-		printf("Modify feature \"%s\" for the volume\n",
-			opts.feature_string);
-	}
-
-	/* If operation requires touching the global bitmap, ensure it is good */
-	/* This is to handle failed resize */
-	if (opts.num_blocks || opts.num_slots || opts.jrnl_size ||
-	    opts.backup_super) {
-		if (global_bitmap_check(fs)) {
-			com_err(opts.progname, 0, "Global bitmap check failed. "
-				"Run fsck.ocfs2 -f <device>.");
-			goto unlock;
-		}
-	}
-
-	/* check whether the block for backup superblock are used. */
-	if (opts.backup_super) {
-		if (backup_super_check(fs))
-			goto unlock;
-		else
-			printf("Adding backup superblock for the volume\n");
-	}
-
-	/* validate volume label */
-	if (opts.vol_label) {
-		printf("Changing volume label from %s to %s\n",
-		       OCFS2_RAW_SB(fs->fs_super)->s_label, opts.vol_label);
-	}
-
-	/* validate volume uuid */
-	if (opts.vol_uuid) {
-		uuid_unparse(OCFS2_RAW_SB(fs->fs_super)->s_uuid, old_uuid);
-		uuid_unparse(opts.vol_uuid, new_uuid);
-		printf("Changing volume uuid from %s to %s\n", old_uuid, new_uuid);
-	}
-
-	/* validate mount type */
-	if (opts.mount) {
-		if (!validate_mount_change(fs)) {
-			if (opts.mount == MOUNT_LOCAL)
-				tmpstr = MOUNT_LOCAL_STR;
-			else
-				tmpstr = MOUNT_CLUSTER_STR;
-			printf("Changing mount type to %s\n", tmpstr);
-		} else
-			opts.mount = 0;
-	}
-
-	/* validate num slots */
-	max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
-	if (opts.num_slots) {
-		if (opts.num_slots < max_slots) {
-			ret = remove_slot_check(fs);
-			if (ret) {
-				com_err(opts.progname, 0,
-					"remove slot check failed. ");
-				goto unlock;
-			}
-		}
-		else if (opts.num_slots > max_slots) {
-			if (!opts.jrnl_size)
-				opts.jrnl_size = def_jrnl_size;
-
-		} else {
-			printf("Giving the same number of nodes. "
-				"Ignore the change of slots.");
-			opts.num_slots = 0;
-		}
-
-		if (opts.num_slots)
-			printf("Changing number of node slots from %d to %d\n",
-			       max_slots, opts.num_slots);
-	}
-
-	/* validate journal size */
-	if (opts.jrnl_size) {
-		num_clusters = (opts.jrnl_size + fs->fs_clustersize - 1) >>
-				OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
-
-		opts.jrnl_size = num_clusters <<
-				OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
-
-		if (opts.jrnl_size != def_jrnl_size)
-			printf("Changing journal size %"PRIu64" to %"PRIu64"\n",
-			       def_jrnl_size, opts.jrnl_size);
-	}
+	ret = volume_check(fs);
+	if (ret)
+ 		goto unlock;
 
-	/* validate volume size */
-	if (opts.num_blocks) {
-		if (validate_vol_size(fs))
-			opts.num_blocks = 0;
-		else
-			printf("Changing volume size from %"PRIu64" blocks to "
-			       "%"PRIu64" blocks\n", fs->fs_blocks,
-			       opts.num_blocks);
-	}
+	validate_parameter(fs);
 
 	if (!opts.vol_label && !opts.vol_uuid && !opts.num_slots &&
 	    !opts.jrnl_size && !opts.num_blocks && !opts.mount &&
@@ -1249,6 +1275,7 @@ int main(int argc, char **argv)
 	}
 
 	/* Set resize incompat flag on superblock */
+	max_slots = OCFS2_RAW_SB(fs->fs_super)->s_max_slots;
 	if (opts.num_blocks ||
 	    (opts.num_slots && opts.num_slots < max_slots)) {
 		if (opts.num_blocks)
Signature · 1 line
gitgui.0.9.0.gd794
author
#1 lore raw

PATCH 1/6 Move resize function out of tunefs.c, take 3

In reply to tao.ma

We will add online resize in tunefs.ocfs2, and it will be complicated. so add a new file resize.c in it and move all resize function out of tunefs.c.

---
 tunefs.ocfs2/Makefile |    2 +-
 tunefs.ocfs2/resize.c |  320 +++++++++++++++++++++++++++++++++++++++++++++++++
 tunefs.ocfs2/tunefs.c |  295 +---------------------------------------------
 tunefs.ocfs2/tunefs.h |    6 +
 4 files changed, 328 insertions(+), 295 deletions(-)
 create mode 100644 tunefs.ocfs2/resize.c
tunefs.ocfs2/Makefile +1 -1
index e6b4427..be68fc8 100644
@@ -31,7 +31,7 @@ DEFINES = -DOCFS2_FLAT_INCLUDES -DVERSION=\"$(VERSION)\" -DO2DLM_FLAT_INCLUDES -
 
 MANS = tunefs.ocfs2.8
 
-CFILES = tunefs.c query.c remove_slot.c sparse_file.c features.c
+CFILES = tunefs.c query.c remove_slot.c sparse_file.c features.c resize.c
 HFILES = tunefs.h
 
 OBJS = $(subst .c,.o,$(CFILES))
tunefs.ocfs2/resize.c new file +320 -0

320 lines not on this page · raw message

tunefs.ocfs2/tunefs.c +1 -294

319 lines not on this page · raw message

tunefs.ocfs2/tunefs.h +6 -0
index 566d746..3863331 100644
@@ -98,6 +98,8 @@ typedef struct _ocfs2_tune_opts {
 	time_t tune_time;
 } ocfs2_tune_opts;
 
+void block_signals(int how);
+
 void print_query(char *queryfmt);
 
 errcode_t remove_slots(ocfs2_filesys *fs);
@@ -113,4 +115,8 @@ void free_clear_ctxt(void);
 
 errcode_t feature_check(ocfs2_filesys *fs);
 errcode_t update_feature(ocfs2_filesys *fs);
+
+void get_vol_size(ocfs2_filesys *fs);
+errcode_t update_volume_size(ocfs2_filesys *fs, int *changed);
+int validate_vol_size(ocfs2_filesys *fs);
 #endif /* _TUNEFS_H */
Signature · 1 line
gitgui.0.9.0.gd794
author
#8 lore raw

PATCH 4/6 Modfiy cl_cpg in global_bitmap to be maximum value during mkfs.take 3

In reply to tao.ma

cl_cpg is used in ocfs2 kernel to calculate the group no for a given cluster. Change it to maximum number so that there is no need to update it durin online resize.

---
 fsck.ocfs2/pass0.c |    2 +-
 mkfs.ocfs2/mkfs.c  |    3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)
fsck.ocfs2/pass0.c +1 -1
index d53c76d..1e4c243 100644
@@ -393,7 +393,7 @@ static void mark_group_used(o2fsck_state *ost, struct chain_state *cs,
 }
 
 /*
- * Due to a glitch in mkfs, cl->cl_cpg for the GLOBAL BITMAP could be
+ * Due to a glitch in old mkfs, cl->cl_cpg for the GLOBAL BITMAP could be
  * less than the max possible for volumes having just one cluster
  * group. Fix.
  */
mkfs.ocfs2/mkfs.c +2 -1
index 0ade0ab..57784a6 100644
@@ -1910,7 +1910,8 @@ format_file(State *s, SystemFileDiskRecord *rec)
 	if (rec->cluster_bitmap) {
 		di->id2.i_chain.cl_count = 
 			ocfs2_chain_recs_per_inode(s->blocksize);
-		di->id2.i_chain.cl_cpg = s->global_cpg;
+		di->id2.i_chain.cl_cpg =
+				 ocfs2_group_bitmap_size(s->blocksize) * 8;
 		di->id2.i_chain.cl_bpc = 1;
 		if (s->nr_cluster_groups > 
 		    ocfs2_chain_recs_per_inode(s->blocksize)) {
Signature · 1 line
gitgui.0.9.0.gd794
author
#18 lore raw

PATCH 6/6 Add online resize support in tunefs.ocfs2.take 3

In reply to tao.ma

User can do offline resize using tunefs.ocfs2 when a volume isn't mounted. Now the support for online resize is added.

Please note that the node where online resize goes must already has the volume mounted. We don't mount it behind the user and the operation would fail if we find it isn't mounted. As for other nodes, we don't care whether the volume is mounted or not.

global_bitmap, super block and all the backups will be updated in the kernel. And if super block or backup's update fails, we just output some error message in dmesg and continue the work.

The whole process is derived from ext3 and divided into 2 steps:
1. OCFS2_IOC_GROUP_EXTEND: We will extend the last group first if it isn't full. All the work is done in kernel.
2. For every new group, call OCFS2_IOC_GROUP_ADD to add them one by one. We initialize the new group descriptor in userspace, and let the kernel update the global_bitap etc.

---
 libocfs2/include/ocfs2_fs.h |   14 ++
 tunefs.ocfs2/resize.c       |  277 ++++++++++++++++++++++++++++++++++++++-----
 tunefs.ocfs2/tunefs.c       |   53 ++++++++-
 tunefs.ocfs2/tunefs.h       |    6 +-
 4 files changed, 314 insertions(+), 36 deletions(-)
libocfs2/include/ocfs2_fs.h +14 -0
index cfaf28f..9d3b307 100644
@@ -230,6 +230,20 @@ struct ocfs2_space_resv {
 #define OCFS2_IOC_RESVSP64	_IOW ('X', 42, struct ocfs2_space_resv)
 #define OCFS2_IOC_UNRESVSP64	_IOW ('X', 43, struct ocfs2_space_resv)
 
+/* Used to pass group descriptor data when online resize is done */
+struct ocfs2_new_group_input {
+	__u64 group;		/* Group descriptor's blkno. */
+	__u32 clusters;		/* Total number of clusters in this group */
+	__u32 frees;		/* Total free number of clusters in this group */
+	__u16 chain;		/* Chain for this group */
+	__u16 reserved1;
+	__u32 reserved2;
+};
+
+#define OCFS2_IOC_GROUP_EXTEND	_IOW('o', 1, int)
+#define OCFS2_IOC_GROUP_ADD	_IOW('o', 2,struct ocfs2_new_group_input)
+#define OCFS2_IOC_GROUP_ADD64	_IOW('o', 3,struct ocfs2_new_group_input)
+
 /*
  * Journal Flags (ocfs2_dinode.id1.journal1.i_flags)
  */
tunefs.ocfs2/resize.c +248 -29

341 lines not on this page · raw message

tunefs.ocfs2/tunefs.c +47 -6

92 lines not on this page · raw message

tunefs.ocfs2/tunefs.h +5 -1
index 3863331..b1ad470 100644
@@ -117,6 +117,10 @@ errcode_t feature_check(ocfs2_filesys *fs);
 errcode_t update_feature(ocfs2_filesys *fs);
 
 void get_vol_size(ocfs2_filesys *fs);
-errcode_t update_volume_size(ocfs2_filesys *fs, int *changed);
+errcode_t update_volume_size(ocfs2_filesys *fs, int *changed, int online);
 int validate_vol_size(ocfs2_filesys *fs);
+
+errcode_t online_resize_check(ocfs2_filesys *fs);
+errcode_t online_resize_lock(ocfs2_filesys *fs);
+errcode_t online_resize_unlock(ocfs2_filesys *fs);
 #endif /* _TUNEFS_H */
Signature · 1 line
gitgui.0.9.0.gd794
author
#10 lore raw

PATCH 5/6 Modify fsck to trust global bitmap than super block.take 3

In reply to tao.ma

In resize, we update the global_bitmap first and then the super block. So if there is any corruption between these 2 steps, there will be a inconsistence. In kernel we use the information in global_bitmap, so fsck.ocfs2 should also trust it during the check.

---
 fsck.ocfs2/pass0.c |   25 ++++++++++++++++++-------
 1 files changed, 18 insertions(+), 7 deletions(-)
fsck.ocfs2/pass0.c +18 -7
index 1e4c243..c88ab31 100644
@@ -1075,19 +1075,30 @@ errcode_t o2fsck_pass0(o2fsck_state *ost)
 	if (ret)
 		goto out;
 
+	/*
+	 * during resize, we may update the global bitmap but fails to
+	 * to update i_clusters in superblock, so ask the user which one
+	 * to use before checking.
+	 */
+	if (fs->fs_super->i_clusters != di->i_clusters) {
+		if (prompt(ost, PY, PR_SUPERBLOCK_CLUSTERS,
+			   "Superblock has clusters set to %u instead of %u "
+			   "recorded in global_bitmap, it may be caused by an "
+			   "unsuccessful resize. Trust global_bitmap?",
+			   fs->fs_super->i_clusters, di->i_clusters)) {
+			ost->ost_num_clusters = di->i_clusters;
+			fs->fs_clusters = di->i_clusters;
+			fs->fs_blocks = ocfs2_clusters_to_blocks(fs,
+							 fs->fs_clusters);
+		}
+	}
+
 	ret = verify_bitmap_descs(ost, di, blocks + ost->ost_fs->fs_blocksize,
 				  blocks + (ost->ost_fs->fs_blocksize * 2));
 
 	if (ret)
 		goto out;
 
-	if (fs->fs_super->i_clusters != di->i_clusters) {
-		if (prompt(ost, PY, PR_SUPERBLOCK_CLUSTERS,
-			   "Superblock has clusters set to %u instead of %u. Fix?",
-			   fs->fs_super->i_clusters, di->i_clusters))
-			ost->ost_num_clusters = di->i_clusters;
-	}
-
 	printf("Pass 0b: Checking inode allocation chains\n");
 
 	/* first the global inode alloc and then each of the node's
Signature · 1 line
gitgui.0.9.0.gd794
#11 lore raw

[Ocfs2-devel] Re: [Ocfs2-tools-devel] [PATCH 5/6] Modify fsck to trust global bitmap than super block.take 3

Quoted 6 lines · tao.ma

In resize, we update the global_bitmap first and then the super block. So if there is any corruption between these 2 steps, there will be a inconsistence. In kernel we use the information in global_bitmap, so fsck.ocfs2 should also trust it during the check.

--
Mark Fasheh
Senior Software Developer, Oracle
[email protected]

#7 lore raw

[Ocfs2-devel] Re: [Ocfs2-tools-devel] [PATCH 3/6] Abstract checking and validating process in tunefs.ocfs2.take 3

In reply to Tao Ma
Quoted 6 lines · Tao Ma

In the main function of tunefs.ocfs2, there are a large number of checking and validating process. They are seperated and can be moved out of "main" so that future online resize can skip these check easily. So add 2 new function, volume_check and validate_parameter to organize the complicated process.

Quoted 8 lines

There are also 2 minor changes in this patch:
1. the print of "Adding backup superblock for the volume" are moved to validate process as others.
2. remove_slot_check is moved into function volume_check as it does the check work while it was in validate process.

--

Remind me... some of the error messages need some polishing. Nothing big. I can handle that later.

#12 lore raw

[Ocfs2-devel] Re: [Ocfs2-tools-devel] [PATCH 5/6] Modify fsck to trust global bitmap than super block.take 3

In reply to Tao Ma
Quoted 8 lines · Tao Ma

In resize, we update the global_bitmap first and then the super block. So if there is any corruption between these 2 steps, there will be a inconsistence. In kernel we use the information in global_bitmap, so fsck.ocfs2 should also trust it during the check.

---

This looks correct. However, I am still confused as to how I managed to get clean runs when testing aborted offline resize cases.

author
#13 lore raw

[Ocfs2-devel] Re: [Ocfs2-tools-devel] [PATCH 5/6] Modify fsck to trust global bitmap than super block.take 3

Quoted 6 lines · Sunil Mushran
Quoted 5 lines · Tao Ma

In resize, we update the global_bitmap first and then the super block. So if there is any corruption between these 2 steps, there will be a inconsistence. In kernel we use the information in global_bitmap, so fsck.ocfs2 should also trust it during the check.

Quoted 7 lines
Quoted 3 lines

---

This looks correct. However, I am still confused as to how I managed to get clean runs when testing aborted offline resize cases.

In your offline resize design, you write this:

* Segfault after writing global bitmap but before the superblock.

/fsck will remove all the new BGs that are beyond the end-of-volume as determined by the superblock->num_clusters.

So we trust superblock rather than global_bitmap and it works as the design expects when testing aborted offline resize cases. Now the order is reversed, so I think maybe I need to revise your design doc so that it doesn't lead to the "strange" result.
Agree?
/

#14 lore raw

[Ocfs2-devel] Re: [Ocfs2-tools-devel] [PATCH 5/6] Modify fsck to trust global bitmap than super block.take 3

I still need to go thru the fs code for resize. But under what condition will the global bitmap be updated and not the superblock?

My problem with the fsck change is that we are manipulating fs->fs_clusters directly. This will just cause us grief later. It is best if this is populated only in ocfs2_open().

Sunil

Quoted 28 lines · tao.ma
Quoted 6 lines · Sunil Mushran
Quoted 5 lines · Tao Ma

In resize, we update the global_bitmap first and then the super block. So if there is any corruption between these 2 steps, there will be a inconsistence. In kernel we use the information in global_bitmap, so fsck.ocfs2 should also trust it during the check.

Quoted 7 lines
Quoted 3 lines

---

This looks correct. However, I am still confused as to how I managed to get clean runs when testing aborted offline resize cases.

In your offline resize design, you write this:

* Segfault after writing global bitmap but before the superblock.

/fsck will remove all the new BGs that are beyond the end-of-volume as determined by the superblock->num_clusters.

So we trust superblock rather than global_bitmap and it works as the design expects when testing aborted offline resize cases. Now the order is reversed, so I think maybe I need to revise your design doc so that it doesn't lead to the "strange" result. Agree?
/

author
#15 lore raw

[Ocfs2-devel] Re: [Ocfs2-tools-devel] [PATCH 5/6] Modify fsck to trust global bitmap than super block.take 3

Quoted 3 lines · Sunil Mushran

I still need to go thru the fs code for resize. But under what condition will the global bitmap be updated and not the superblock?

Actually in kernel, we update the global_bitmap first and then the super block and backups.
And if the super block and backups' update fail, the kernel doesn't care about it and only output some in message since the kernel only use the info stored in global_bitmap.

Quoted 4 lines

My problem with the fsck change is that we are manipulating fs->fs_clusters directly. This will just cause us grief later. It is best if this is populated only in ocfs2_open().

If we populate in ocfs2_open, maybe we need another flag and check global_bitmap if needed?

Quoted 33 lines

Sunil

Quoted 28 lines · tao.ma
Quoted 6 lines · Sunil Mushran
Quoted 5 lines · Tao Ma

In resize, we update the global_bitmap first and then the super block. So if there is any corruption between these 2 steps, there will be a inconsistence. In kernel we use the information in global_bitmap, so fsck.ocfs2 should also trust it during the check.

Quoted 7 lines
Quoted 3 lines

---

This looks correct. However, I am still confused as to how I managed to get clean runs when testing aborted offline resize cases.

In your offline resize design, you write this:

* Segfault after writing global bitmap but before the superblock.

/fsck will remove all the new BGs that are beyond the end-of-volume as determined by the superblock->num_clusters.

So we trust superblock rather than global_bitmap and it works as the design expects when testing aborted offline resize cases. Now the order is reversed, so I think maybe I need to revise your design doc so that it doesn't lead to the "strange" result. Agree?
/

#16 lore raw

[Ocfs2-devel] Re: [Ocfs2-tools-devel] [PATCH 5/6] Modify fsck to trust global bitmap than super block.take 3

So the problem is as follows:

In offline resize, if we crash after updating globalbitmap but before superblock, we have a incompat flag to force users to run fsck to fix the volume. Currently our fix in fsck revokes the resize.

If the same crash happened in online, other nodes will carry on no problems. The same node can remount the volume and continue. The problem will be if someone runs any usertool that writes (say tunefs) without running fsck (on the same now unmounted vol).

One solution is to read the global bitmap in ocfs2_open(). If the user opens with write and the values are inconsistent, bail unless the tool is fsck (via some flag). If the user opens with read, we could ignore the inconsistency but use the global bitmap value. My only worry is that this will make ocfs2_open() slower. But we can address that later.

Thoughts?

Quoted 56 lines · tao.ma
Quoted 3 lines · Sunil Mushran

I still need to go thru the fs code for resize. But under what condition will the global bitmap be updated and not the superblock?

Actually in kernel, we update the global_bitmap first and then the super block and backups.
And if the super block and backups' update fail, the kernel doesn't care about it and only output some in message since the kernel only use the info stored in global_bitmap.

Quoted 4 lines

My problem with the fsck change is that we are manipulating fs->fs_clusters directly. This will just cause us grief later. It is best if this is populated only in ocfs2_open().

If we populate in ocfs2_open, maybe we need another flag and check global_bitmap if needed?

Quoted 35 lines

Sunil

Quoted 30 lines · tao.ma
Quoted 7 lines · Sunil Mushran
Quoted 6 lines · Tao Ma

In resize, we update the global_bitmap first and then the super block.
So if there is any corruption between these 2 steps, there will be a inconsistence. In kernel we use the information in global_bitmap, so fsck.ocfs2 should also trust it during the check.

Quoted 8 lines
Quoted 3 lines

---

This looks correct. However, I am still confused as to how I managed to
get clean runs when testing aborted offline resize cases.

In your offline resize design, you write this:

* Segfault after writing global bitmap but before the superblock.

/fsck will remove all the new BGs that are beyond the end-of-volume as determined by the superblock->num_clusters.

So we trust superblock rather than global_bitmap and it works as the design expects when testing aborted offline resize cases. Now the order is reversed, so I think maybe I need to revise your design doc so that it doesn't lead to the "strange" result. Agree?
/

_______________________________________________
Ocfs2-devel mailing list
[email protected]
http://oss.oracle.com/mailman/listinfo/ocfs2-devel

author
#17 lore raw

[Ocfs2-devel] Re: [Ocfs2-tools-devel] [PATCH 5/6] Modify fsck to trust global bitmap than super block.take 3

Quoted 5 lines · Sunil Mushran

So the problem is as follows:

In offline resize, if we crash after updating globalbitmap but before superblock, we have a incompat flag to force users to run fsck to fix the volume. Currently our fix in fsck revokes the resize.

That is the old solution. If this patch is merged, we will treat it as online resize. That is we will modify the i_cluster in superbock instead and the resize is completed by fsck.

Quoted 11 lines

If the same crash happened in online, other nodes will carry on no problems. The same node can remount the volume and continue. The problem will be if someone runs any usertool that writes (say tunefs) without running fsck (on the same now unmounted vol).

One solution is to read the global bitmap in ocfs2_open(). If the user opens with write and the values are inconsistent, bail unless the tool is fsck (via some flag). If the user opens with read, we could ignore the inconsistency but use the global bitmap value. My only worry is that this will make ocfs2_open() slower. But we can address that later.

Yes, that is what I am thinking.
Since the kernel use the i_clusters in global_bitmap to indicate the size of the volume, the user space should also trust that.

Quoted 54 lines

Thoughts?

Quoted 49 lines · tao.ma
Quoted 3 lines · Sunil Mushran

I still need to go thru the fs code for resize. But under what condition will the global bitmap be updated and not the superblock?

Actually in kernel, we update the global_bitmap first and then the super block and backups.
And if the super block and backups' update fail, the kernel doesn't care about it and only output some in message since the kernel only use the info stored in global_bitmap.

Quoted 4 lines

My problem with the fsck change is that we are manipulating fs->fs_clusters directly. This will just cause us grief later. It is best if this is populated only in ocfs2_open().

If we populate in ocfs2_open, maybe we need another flag and check global_bitmap if needed?

Quoted 34 lines

Sunil

Quoted 30 lines · tao.ma
Quoted 7 lines · Sunil Mushran
Quoted 6 lines · Tao Ma

In resize, we update the global_bitmap first and then the super block.
So if there is any corruption between these 2 steps, there will be a inconsistence. In kernel we use the information in global_bitmap, so fsck.ocfs2 should also trust it during the check.

Quoted 8 lines
Quoted 3 lines

---

This looks correct. However, I am still confused as to how I managed to
get clean runs when testing aborted offline resize cases.

In your offline resize design, you write this:

* Segfault after writing global bitmap but before the superblock.

/fsck will remove all the new BGs that are beyond the end-of-volume as determined by the superblock->num_clusters.

So we trust superblock rather than global_bitmap and it works as the design expects when testing aborted offline resize cases. Now the order is reversed, so I think maybe I need to revise your design doc so that it doesn't lead to the "strange" result. Agree?
/