[PATCH] ext2 code cleanup

From: Andreas Dilger (adilger@turbolabs.com)
Date: Thu May 18 2000 - 01:10:52 EST


Hello Linus,
please consider the following patch against 2.3.99 for inclusion into
the kernel. It moves some of the code out of ext2_read_super() into
a new function - ext2_read_descriptors() - which, as you would expect,
reads the ext2 group descriptors from disk. It makes ext2_read_super()
a bit more clear, but is also allows the ext2 online resize code (patch
not included here) to read new group descriptors from disk starting at
a non-zero group number.

As the patch stands, the ext2_read_descriptors() function is only called
from ext2_read_super() with a zero starting group number and a NULL
group descriptor struct, so it can trivially be seen as identical to
the existing code.

This is the first patch (of two) required to allow resizing of ext2
filesystems while they are mounted (in conjunction with LVM). IMHO,
this patch is "obviously correct" and justified on its own merits by
the CodingStyle, since it makes a nice simple helper function for a
very long function. It also happens to be needed for online resizing.
Now that LVM is in the base kernel, it is very useful to also be able to
resize a filesystem when you resize the LV that it is in. Without this
capability, the usefulness of LVM is greatly reduced, IMHO, since you
need to unmount your filesystems to resize them, or even reboot in the
case of /. How will we ever consistently get 400+ days uptime if you
need to reboot your system in order to resize your root partition ;-)?

Comments/criticism appreciated; flames will at least tell me someone cares...

Cheers, Andreas

--- cut here ---
diff -ru -X linux-2.3.99p2-ext2base/exclude.lst linux-2.3.99p2/fs/ext2/super.c linux-2.3.99p2-ext2base/fs/ext2/super.c
--- linux-2.3.99p2/fs/ext2/super.c Sun Mar 19 22:24:11 2000
+++ linux-2.3.99p2-ext2base/fs/ext2/super.c Sun Mar 19 23:11:33 2000
@@ -29,6 +29,10 @@
 
 static char error_buf[1024];
 
+#ifndef MIN
+# define MIN(m,n) ((m) < (n) ? (m) : (n))
+#endif
+
 void ext2_error (struct super_block * sb, const char * function,
                  const char * fmt, ...)
 {
@@ -362,6 +366,96 @@
         return 1;
 }
 
+static int ext2_read_descriptors (struct super_block * sb,
+ unsigned long logic_sb_block,
+ unsigned long blocks_count)
+{
+ int db_start;
+ int db_count;
+ unsigned long groups_count;
+ unsigned long o_groups_count;
+ struct buffer_head ** group_desc = NULL;
+ struct buffer_head ** o_group_desc;
+ int i, j;
+
+ o_group_desc = sb->u.ext2_sb.s_group_desc;
+ o_groups_count = sb->u.ext2_sb.s_groups_count;
+
+ /* If we already have some groups loaded, start on the next one. */
+ db_start = sb->u.ext2_sb.s_db_per_group + o_groups_count ? 1 : 0;
+ groups_count = (blocks_count -
+ le32_to_cpu(sb->u.ext2_sb.s_es->s_first_data_block) +
+ EXT2_BLOCKS_PER_GROUP(sb) - 1) /
+ EXT2_BLOCKS_PER_GROUP(sb);
+ db_count = (groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
+ EXT2_DESC_PER_BLOCK(sb);
+ if (test_opt (sb, DEBUG)) {
+ printk ("EXT2-fs: ext2_read_descriptors: o_groups_count=%lu, "
+ "groups_count=%lu, blocks_count=%lu\n", o_groups_count,
+ groups_count, blocks_count);
+ printk ("EXT2-fs: ext2_read_descriptors: db_orig=%lu, "
+ "db_start=%d, db_count=%d\n",
+ sb->u.ext2_sb.s_db_per_group, db_start, db_count);
+ }
+
+ if (db_start != db_count) {
+ group_desc = (struct buffer_head **) kmalloc (db_count *
+ sizeof (struct buffer_head *), GFP_KERNEL);
+ if (group_desc == NULL) {
+ ext2_warning (sb, __FUNCTION__,
+ "not enough memory for %d groups",
+ db_count);
+ return -ENOMEM;
+ }
+ for (i = db_start; i < db_count; i++) { /* Add group blocks */
+ group_desc[i] = bread (sb->s_dev,
+ logic_sb_block + i + 1,
+ sb->s_blocksize);
+ if (!group_desc[i]) {
+ for (j = db_start; j < i; j++)
+ brelse (group_desc[j]);
+ kfree_s (group_desc, db_count *
+ sizeof (struct buffer_head *));
+ ext2_warning (sb, __FUNCTION__,
+ "unable to read group block %d",
+ i);
+ return -EIO;
+ }
+ }
+
+ /*
+ * Copy over old descriptor blocks previously loaded, if any.
+ * We need to set s_group_desc and s_groups_count now so that
+ * ext2_check_descriptors() will check the new groups as well.
+ */
+ memcpy (group_desc, o_group_desc,
+ MIN(sb->u.ext2_sb.s_db_per_group, db_count) *
+ sizeof (struct buffer_head *));
+ sb->u.ext2_sb.s_group_desc = group_desc;
+ }
+ sb->u.ext2_sb.s_groups_count = groups_count;
+
+ if (!ext2_check_descriptors (sb)) {
+ sb->u.ext2_sb.s_groups_count = o_groups_count;
+ sb->u.ext2_sb.s_group_desc = o_group_desc;
+ for (j = db_start; j < db_count; j++)
+ brelse (group_desc[j]);
+ if (group_desc != NULL)
+ kfree_s (group_desc,
+ db_count * sizeof (struct buffer_head *));
+ return -EINVAL;
+ }
+
+ if (o_group_desc && o_group_desc != sb->u.ext2_sb.s_group_desc)
+ kfree_s (o_group_desc, sb->u.ext2_sb.s_db_per_group *
+ sizeof (struct buffer_head *));
+
+ sb->u.ext2_sb.s_db_per_group = db_count;
+
+ return 0;
+} /* ext2_read_descriptors */
+
+
 #define log2(n) ffz(~(n))
 
 struct super_block * ext2_read_super (struct super_block * sb, void * data,
@@ -370,8 +465,7 @@
         kdev_t dev = sb->s_dev;
         int blocksize = BLOCK_SIZE;
         int hblock;
- int db_count;
- int i, j;
+ int i;
 
         /*
          * See what the current blocksize for the device is, and
@@ -561,35 +655,13 @@
                 goto failed_mount;
         }
 
- sb->u.ext2_sb.s_groups_count = (le32_to_cpu(es->s_blocks_count) -
- le32_to_cpu(es->s_first_data_block) +
- EXT2_BLOCKS_PER_GROUP(sb) - 1) /
- EXT2_BLOCKS_PER_GROUP(sb);
- db_count = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
- EXT2_DESC_PER_BLOCK(sb);
- sb->u.ext2_sb.s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
- if (sb->u.ext2_sb.s_group_desc == NULL) {
- printk ("EXT2-fs: not enough memory\n");
- goto failed_mount;
- }
- for (i = 0; i < db_count; i++) {
- sb->u.ext2_sb.s_group_desc[i] = bread (dev, logic_sb_block + i + 1,
- sb->s_blocksize);
- if (!sb->u.ext2_sb.s_group_desc[i]) {
- for (j = 0; j < i; j++)
- brelse (sb->u.ext2_sb.s_group_desc[j]);
- kfree_s (sb->u.ext2_sb.s_group_desc,
- db_count * sizeof (struct buffer_head *));
- printk ("EXT2-fs: unable to read group descriptors\n");
- goto failed_mount;
- }
- }
- if (!ext2_check_descriptors (sb)) {
- for (j = 0; j < db_count; j++)
- brelse (sb->u.ext2_sb.s_group_desc[j]);
- kfree_s (sb->u.ext2_sb.s_group_desc,
- db_count * sizeof (struct buffer_head *));
- printk ("EXT2-fs: group descriptors corrupted !\n");
+ sb->u.ext2_sb.s_db_per_group = 0;
+ sb->u.ext2_sb.s_groups_count = 0;
+ sb->u.ext2_sb.s_group_desc = NULL;
+ if ((i = ext2_read_descriptors (sb, logic_sb_block,
+ le32_to_cpu(es->s_blocks_count)))) {
+ ext2_error (sb, __FUNCTION__,
+ "group descriptor error %d, unable to mount", i);
                 goto failed_mount;
         }
         for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
@@ -594,7 +666,6 @@
         }
         sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
         sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
- sb->u.ext2_sb.s_db_per_group = db_count;
         /*
          * set up enough so that it can read an inode
          */
@@ -608,11 +679,12 @@
         sb->s_op = &ext2_sops;
         sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO));
         if (!sb->s_root) {
- for (i = 0; i < db_count; i++)
+ for (i = 0; i < sb->u.ext2_sb.s_db_per_group; i++)
                         if (sb->u.ext2_sb.s_group_desc[i])
                                 brelse (sb->u.ext2_sb.s_group_desc[i]);
                 kfree_s (sb->u.ext2_sb.s_group_desc,
- db_count * sizeof (struct buffer_head *));
+ sb->u.ext2_sb.s_db_per_group *
+ sizeof (struct buffer_head *));
                 brelse (bh);
                 printk ("EXT2-fs: get root inode failed\n");
                 return NULL;
--- cut here ---

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Tue May 23 2000 - 21:00:14 EST