Add RAID stride support to resize2fs

Resize2fs will now automatically determine the RAID stride parameter that
had been used to create the filesystem, and use that for newly created
block groups.   The RAID stride parameter may also be manually specified
on the command line using the new -S option to resize2fs.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

diff --git a/resize/ChangeLog b/resize/ChangeLog
index 3a972d5..ce8e2f6 100644
--- a/resize/ChangeLog
+++ b/resize/ChangeLog
@@ -1,3 +1,12 @@
+2006-05-14  Theodore Tso  <tytso@mit.edu>
+
+	* main.c (main, determine_fs_stride), resize2fs.8.in: Add a new
+		option (-S) to resize2fs which allows the user to specify
+		the RAID stride parameter to be used on new block groups.
+		In addition, add code so that resize2fs can automatically
+		determine the RAID stride parameter that had been
+		previously used on the filesystem.
+
 2006-03-18  Theodore Ts'o  <tytso@mit.edu>
 
 	* main.c, resize2fs.c: Change printf statements to use %u instead
diff --git a/resize/main.c b/resize/main.c
index 0632c07..537c9a6 100644
--- a/resize/main.c
+++ b/resize/main.c
@@ -94,6 +94,50 @@
 	return 0;
 }
 
+static void determine_fs_stride(ext2_filsys fs)
+{
+	unsigned int	group;
+	unsigned long long sum;
+	unsigned int	has_sb, prev_has_sb, num;
+	int		i_stride, b_stride;
+
+	num = 0; sum = 0;
+	for (group = 0; group < fs->group_desc_count; group++) {
+		has_sb = ext2fs_bg_has_super(fs, group);
+		if (group == 0 || has_sb != prev_has_sb)
+			goto next;
+		b_stride = fs->group_desc[group].bg_block_bitmap - 
+			fs->group_desc[group-1].bg_block_bitmap - 
+			fs->super->s_blocks_per_group;
+		i_stride = fs->group_desc[group].bg_inode_bitmap - 
+			fs->group_desc[group-1].bg_inode_bitmap - 
+			fs->super->s_blocks_per_group;
+		if (b_stride != i_stride ||
+		    b_stride < 0)
+			goto next;
+
+		/* printf("group %d has stride %d\n", group, b_stride); */
+		sum += b_stride;
+		num++;
+			
+	next:
+		prev_has_sb = has_sb;
+	}
+
+	if (fs->group_desc_count > 12 && num < 3)
+		sum = 0;
+
+	if (num)
+		fs->stride = sum / num;
+	else
+		fs->stride = 0;
+
+#if 0
+	if (fs->stride)
+		printf("Using RAID stride of %d\n", fs->stride);
+#endif
+}
+
 int main (int argc, char ** argv)
 {
 	errcode_t	retval;
@@ -108,6 +152,7 @@
 	blk_t		max_size = 0;
 	io_manager	io_ptr;
 	char		*new_size_str = 0;
+	int		use_stride = -1;
 #ifdef HAVE_FSTAT64
 	struct stat64	st_buf;
 #else
@@ -133,7 +178,7 @@
 	if (argc && *argv)
 		program_name = *argv;
 
-	while ((c = getopt (argc, argv, "d:fFhp")) != EOF) {
+	while ((c = getopt (argc, argv, "d:fFhpS:")) != EOF) {
 		switch (c) {
 		case 'h':
 			usage(program_name);
@@ -150,6 +195,9 @@
 		case 'p':
 			flags |= RESIZE_PERCENT_COMPLETE;
 			break;
+		case 'S':
+			use_stride = atoi(optarg);
+			break;
 		default:
 			usage(program_name);
 		}
@@ -293,6 +341,16 @@
 		if (sys_page_size > fs->blocksize)
 			new_size &= ~((sys_page_size / fs->blocksize)-1);
 	}
+
+	if (use_stride >= 0) {
+		if (use_stride >= fs->super->s_blocks_per_group) {
+			com_err(program_name, 0, 
+				_("Invalid stride length"));
+			exit(1);
+		}
+		fs->stride = use_stride;
+	} else
+		  determine_fs_stride(fs);
 	
 	/*
 	 * If we are resizing a plain file, and it's not big enough,
diff --git a/resize/resize2fs.8.in b/resize/resize2fs.8.in
index 426c3ce..4f869e9 100644
--- a/resize/resize2fs.8.in
+++ b/resize/resize2fs.8.in
@@ -12,6 +12,10 @@
 .I debug-flags
 ]
 [
+.B \-S
+.I RAID-stride
+]
+[
 .B \-f
 ]
 [
@@ -78,7 +82,7 @@
 of the ext2 filesystem!
 .SH OPTIONS
 .TP
-.I \-d debug-flags
+.B \-d \fIdebug-flags
 Turns on various resize2fs debugging features, if they have been compiled 
 into the binary.
 .I debug-flags
@@ -93,17 +97,24 @@
 .br
 \	16\	\-\ Debug moving the inode table
 .TP
-.I \-p
+.B \-S \fIRAID-stride
+The 
+.B resize2fs
+program will hueristically determine the RAID stride that was specified 
+when the filesystem was created.  This option allows the user to 
+explicitly specify a RAID stride setting to be used by resize2fs instead.
+.TP
+.B \-p
 Prints out a percentage completion bars for each 
 .B resize2fs
 operation, so that the user can keep track of what
 the program is doing.
 .TP 
-.I \-f
+.B \-f
 Forces resize2fs to proceed with the filesystem resize operation, overriding 
 some safety checks which resize2fs normally enforces.
 .TP
-.I \-F
+.B \-F
 Flush the filesystem device's buffer caches before beginning.  Only
 really useful for doing 
 .B resize2fs