[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [linux-lvm] ext2online and 2.4.18



Attached is the reject file.  It looks like hunk 10 removes 27 lines
from super.c around line 594, but these were not getting removed in
2.4.18.  Also attached is what I think the 2.4.18 patch should be.

-Ian


On Wed, 2002-06-19 at 14:47, Andreas Dilger wrote:
> On Jun 19, 2002  14:10 -0700, Ian Prowell wrote:
> > Andreas,
> > Thanks for the prompt reply.  To be more specific I am using RedHat's
> > 2.4.18-4 kernel.  When I apply the patch I get the following output.
> > 
> > [root metaverse src]# cat /root/online-ext2-2.4.17.diff | patch -p0
> > patching file linux/fs/ext2/super.c
> > Hunk #9 succeeded at 730 (offset -1 lines).
> > Hunk #10 FAILED at 883.
> > Hunk #11 succeeded at 893 (offset 1 line).
> > Hunk #12 succeeded at 917 (offset -1 lines).
> > Hunk #13 succeeded at 979 (offset 1 line).
> > Hunk #14 succeeded at 987 (offset -1 lines).
> > Hunk #15 succeeded at 1024 (offset 1 line).
> > 1 out of 15 hunks FAILED -- saving rejects to file
> > linux/fs/ext2/super.c.rej
> > 
> > It looks like most of the patch is working, but I am not a kernel
> > developer and really have no idea what failed on hunk 10.  If it would
> > be useful I can send the rejects file.
> 
> It won't really be useful for you to send the failed hunk, because I
> have no idea why it is failing.  I would suggest firing up a text editor
> with fs/ext2/super.c and fs/ext2/super.c.rej and just manually cut-paste
> the failed parts in.
> 
> Unified diffs are rather simple to understand.
> 
> Lines like "@@ -123,6 +234,8 @@" are telling you that the original file
> had this hunk at line 123 and the modified file had the replacement
> hunk at line 234.
> 
> Lines like "-                blah" are removing that line from the
> original file and replacing it with "+           blarg" in the new file.
> 
> Hopefully hunk #10 isn't too large...  Sadly, the larger the hunk, the
> more likely it is to not apply cleanly...
> 
> Cheers, Andreas
> --
> Andreas Dilger
> http://www-mddsp.enel.ucalgary.ca/People/adilger/
> http://sourceforge.net/projects/ext2resize/

Attachment: super.c.rej
Description: application/reject

diff -ru linux-2.4.18.orig/CREDITS linux/CREDITS
--- linux-2.4.18.orig/CREDITS	Mon Feb 25 11:37:50 2002
+++ linux/CREDITS	Wed Jun 19 14:56:34 2002
@@ -694,6 +694,15 @@
 S: Warrendale, Pennsylvania 15086
 S: USA
 
+N: Andreas Dilger
+E: adilger turbolinux com
+W: http://www-mddsp.enel.ucalgary.ca/People/adilger/
+D: Ext2 filesystem online resize capability
+D: Ext3/LVM hacking
+S: 630 Schooner Cove N.W.
+S: Calgary, AB
+S: Canada   T3L 1Z1
+
 N: Alex deVries
 E: adevries thepuffingroup com
 D: Various SGI parts, bits of HAL2 and Newport, PA-RISC Linux.
diff -ru linux-2.4.18.orig/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.18.orig/Documentation/Configure.help	Mon Feb 25 11:37:51 2002
+++ linux/Documentation/Configure.help	Wed Jun 19 14:56:34 2002
@@ -14016,6 +14016,20 @@
   be compiled as a module, and so this could be dangerous.  Most
   everyone wants to say Y here.
 
+Online resize for ext2 filesystems
+CONFIG_EXT2_RESIZE
+  This option gives you the ability to increase the size of an ext2
+  filesystem while it is mounted (in use).  In order to do this, you
+  must also be able to resize the underlying disk partition, probably
+  via a Logical Volume Manager (LVM), metadevice (MD), or hardware
+  RAID device - none of that capability is included in this feature.
+  If you don't know what any of these things are, or you haven't
+  configured your kernel for them, you should probably say N here.  If
+  you choose Y, then your kernel will be about 3k larger, and you need
+  to get some more software (http://ext2resize.sourceforge.net/) in
+  order to actually resize your filesystem, otherwise this feature
+  will just sit unused inside the kernel.
+
 Ext3 journalling file system support (EXPERIMENTAL)
 CONFIG_EXT3_FS
   This is the journalling version of the Second extended file system
diff -ru linux-2.4.18.orig/fs/Config.in linux/fs/Config.in
--- linux-2.4.18.orig/fs/Config.in	Mon Feb 25 11:38:07 2002
+++ linux/fs/Config.in	Wed Jun 19 14:56:34 2002
@@ -77,6 +77,7 @@
 tristate 'ROM file system support' CONFIG_ROMFS_FS
 
 tristate 'Second extended fs support' CONFIG_EXT2_FS
+dep_mbool '  Online ext2 resize support (DANGEROUS)' CONFIG_EXT2_RESIZE $CONFIG_EXT2_FS $CONFIG_EXPERIMENTAL
 
 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
 
diff -ru linux-2.4.18.orig/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- linux-2.4.18.orig/fs/ext2/balloc.c	Mon Feb 25 11:38:08 2002
+++ linux/fs/ext2/balloc.c	Wed Jun 19 14:56:34 2002
@@ -616,13 +616,13 @@
 
 unsigned long ext2_count_free_blocks (struct super_block * sb)
 {
-#ifdef EXT2FS_DEBUG
 	struct ext2_super_block * es;
 	unsigned long desc_count, bitmap_count, x;
 	int bitmap_nr;
 	struct ext2_group_desc * gdp;
 	int i;
-	
+
+	if (test_opt(sb, DEBUG) && test_opt(sb, CHECK)) {
 	lock_super (sb);
 	es = sb->u.ext2_sb.s_es;
 	desc_count = 0;
@@ -643,13 +643,12 @@
 			i, le16_to_cpu(gdp->bg_free_blocks_count), x);
 		bitmap_count += x;
 	}
-	printk("ext2_count_free_blocks: stored = %lu, computed = %lu, %lu\n",
+	printk(__FUNCTION__": stored = %u, computed gdt = %lu, bitmap = %lu\n",
 	       le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count);
 	unlock_super (sb);
 	return bitmap_count;
-#else
+	} else
 	return le32_to_cpu(sb->u.ext2_sb.s_es->s_free_blocks_count);
-#endif
 }
 
 static inline int block_in_use (unsigned long block,
diff -ru linux-2.4.18.orig/fs/ext2/super.c linux/fs/ext2/super.c
--- linux-2.4.18.orig/fs/ext2/super.c	Mon Feb 25 11:38:08 2002
+++ linux/fs/ext2/super.c	Wed Jun 19 15:16:33 2002
@@ -14,6 +14,7 @@
  *
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem caip rutgers edu), 1995
+ *  Online resize by Andreas Dilger (adilger turbolinux com), July 1999
  */
 
 #include <linux/config.h>
@@ -163,7 +164,9 @@
  */
 static int parse_options (char * options, unsigned long * sb_block,
 			  unsigned short *resuid, unsigned short * resgid,
-			  unsigned long * mount_options)
+			  unsigned long *mount_options,
+			  unsigned long *n_blocks_count,
+			  unsigned long *resgdt)
 {
 	char * this_char;
 	char * value;
@@ -229,6 +232,31 @@
 		else if (!strcmp (this_char, "nogrpid") ||
 			 !strcmp (this_char, "sysvgroups"))
 			clear_opt (*mount_options, GRPID);
+#ifdef CONFIG_EXT2_RESIZE
+		else if (!strcmp(this_char, "resize")) {
+			printk("EXT2-fs: parse_options: resize=%s\n", value);
+			if (!n_blocks_count) {
+				printk("EXT2-fs: resize option only available "
+				       "for remount\n");
+				return 0;
+			}
+			if (!value || !*value) {
+				printk("EXT2-fs: resize requires number of "
+				       "blocks\n");
+				return 0;
+			}
+			*n_blocks_count = simple_strtoul(value, &value, 0);
+			if (*value == ':') {
+				value++;
+				*resgdt = simple_strtoul(value, &value, 0);
+			}
+			if (*value) {
+				printk("EXT2-fs: invalid resize option: %s\n",
+				       value);
+				return 0;
+			}
+		}
+#endif /* CONFIG_EXT2_RESIZE */
 		else if (!strcmp (this_char, "resgid")) {
 			if (!value || !*value) {
 				printk ("EXT2-fs: the resgid option requires "
@@ -314,10 +342,10 @@
 	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
 	ext2_write_super(sb);
 	if (test_opt (sb, DEBUG))
-		printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
+		printk ("[EXT II FS %s, %s, bs=%lu, bc=%u, gc=%lu, "
 			"bpg=%lu, ipg=%lu, mo=%04lx]\n",
 			EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize,
-			sb->u.ext2_sb.s_frag_size,
+			le32_to_cpu(es->s_blocks_count),
 			sb->u.ext2_sb.s_groups_count,
 			EXT2_BLOCKS_PER_GROUP(sb),
 			EXT2_INODES_PER_GROUP(sb),
@@ -331,7 +359,9 @@
 	return res;
 }
 
-static int ext2_check_descriptors (struct super_block * sb)
+static int ext2_check_descriptors(struct super_block *sb,
+				  struct buffer_head **group_desc,
+				  unsigned long groups_count)
 {
 	int i;
 	int desc_block = 0;
@@ -340,10 +370,10 @@
 
 	ext2_debug ("Checking group descriptors");
 
-	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++)
+	for (i = 0; i < groups_count; i++)
 	{
 		if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
-			gdp = (struct ext2_group_desc *) sb->u.ext2_sb.s_group_desc[desc_block++]->b_data;
+			gdp = (struct ext2_group_desc *)group_desc[desc_block++]->b_data;
 		if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
 		    le32_to_cpu(gdp->bg_block_bitmap) >= block + EXT2_BLOCKS_PER_GROUP(sb))
 		{
@@ -378,6 +408,267 @@
 	return 1;
 }
 
+static int ext2_read_descriptors(struct super_block *sb,
+				 unsigned long blocks_count)
+{
+	struct buffer_head **group_desc;
+	struct buffer_head **o_group_desc;
+	unsigned long groups_count;
+	unsigned long o_groups_count;
+	unsigned long gdb_count;
+	unsigned long o_gdb_count;
+
+	o_group_desc = EXT2_SB(sb)->s_group_desc;
+	o_groups_count = EXT2_SB(sb)->s_groups_count;
+	o_gdb_count = EXT2_SB(sb)->s_gdb_count;
+
+	groups_count = (blocks_count -
+			le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
+			EXT2_BLOCKS_PER_GROUP(sb) - 1) /
+			EXT2_BLOCKS_PER_GROUP(sb);
+	gdb_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: o_gdb_count=%lu, "
+		       "gdb_count=%lu\n", o_gdb_count, gdb_count);
+	}
+
+	if (o_gdb_count != gdb_count) {
+		unsigned long logic_gd_block = EXT2_SB(sb)->s_sbh->b_blocknr +1;
+		unsigned long i;
+
+		group_desc = (struct buffer_head **)kmalloc(gdb_count *
+				sizeof(struct buffer_head *), GFP_KERNEL);
+		if (group_desc == NULL) {
+			ext2_warning(sb, __FUNCTION__,
+				     "not enough memory for %ld group blocks",
+				     gdb_count);
+			return -ENOMEM;
+		}
+		for (i = o_gdb_count; i < gdb_count; i++) {	/* Add blocks */
+			group_desc[i] = bread(sb->s_dev, logic_gd_block + i,
+					      sb->s_blocksize);
+			if (!group_desc[i]) {
+				unsigned long j;
+
+				for (j = o_gdb_count; j < i; j++)
+					brelse(group_desc[j]);
+				kfree(group_desc);
+				ext2_warning(sb, __FUNCTION__,
+					     "can't read group block %ld",
+					     i);
+				return -EIO;
+			}
+		}
+
+		/*
+		 * Copy over pointers to old descriptor blocks already loaded.
+		 */
+		memcpy(group_desc, o_group_desc,
+		       (o_gdb_count < gdb_count ? o_gdb_count : gdb_count) *
+		       sizeof(struct buffer_head *));
+	} else
+		group_desc = o_group_desc; /* this will never be NULL */
+
+	if (!ext2_check_descriptors(sb, group_desc, groups_count)) {
+		unsigned long j;
+
+		for (j = o_gdb_count; j < gdb_count; j++)
+			brelse(group_desc[j]);
+		if (group_desc != o_group_desc)
+			kfree(group_desc);
+		return -EINVAL;
+	}
+
+	EXT2_SB(sb)->s_group_desc = group_desc;
+	EXT2_SB(sb)->s_groups_count = groups_count;
+	EXT2_SB(sb)->s_gdb_count = gdb_count;
+
+	if (o_group_desc && o_group_desc != EXT2_SB(sb)->s_group_desc)
+		kfree(o_group_desc);
+
+	return 0;
+} /* ext2_read_descriptors */
+
+#ifdef CONFIG_EXT2_RESIZE
+/* Make the disk blocks in a new group available to the filesystem */
+static int ext2_update_group(struct super_block *sb, unsigned int block_group,
+			     unsigned int reserved, unsigned int resgdt)
+{
+	struct ext2_group_desc *gdp;
+	struct ext2_super_block *es;
+	int blocks;
+	int m_blocks;
+	int inodes;
+	unsigned long gdb;
+	int shrink = reserved > 100 ? 1 : 0;
+
+	es = EXT2_SB(sb)->s_es;
+	gdp = ext2_get_group_desc(sb, block_group, NULL);
+	gdb = ext2_bg_num_gdb(sb, block_group);
+
+	inodes = le32_to_cpu(gdp->bg_free_inodes_count);
+	blocks = le32_to_cpu(gdp->bg_free_blocks_count);
+	m_blocks = EXT2_SB(sb)->s_itb_per_group + 2 +
+		ext2_bg_has_super(sb, block_group) +
+		(gdb ? gdb + resgdt : 0) + blocks;
+
+	if (block_group < EXT2_SB(sb)->s_groups_count - 1 &&
+	    m_blocks != EXT2_BLOCKS_PER_GROUP(sb)) {
+		ext2_warning(sb, __FUNCTION__,
+			     "bad group size for %s group %d (%d blocks) "
+			     "(iblk = %ld, GDT blk %ld, resgdt %d, blocks %d\n",
+			     ext2_bg_has_super(sb, block_group) ? "normal" :
+			     "no-backup", block_group, m_blocks,
+			     EXT2_SB(sb)->s_itb_per_group, gdb, resgdt, blocks);
+		return -EINVAL;
+	}
+
+	es->s_free_inodes_count =
+		cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + inodes);
+	es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) +
+		inodes);
+
+	es->s_free_blocks_count =
+		cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) + blocks);
+	es->s_blocks_count = cpu_to_le32(le32_to_cpu(es->s_blocks_count) +
+		m_blocks);
+	es->s_r_blocks_count = cpu_to_le32(le32_to_cpu(es->s_r_blocks_count) +
+		m_blocks * reserved / 100);
+
+	mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
+	sb->s_dirt = 1;
+
+	if (test_opt(sb, DEBUG)) {
+		printk("EXT2-fs: ext2_update_group: %s %s group %u: "
+		       "%u inodes, %u blocks (%u free), %d (%d%%) reserved\n",
+		       shrink ? "removing" : "adding",
+		       ext2_bg_has_super(sb, block_group) ? "normal" :
+		       "no-super", block_group, inodes, m_blocks, blocks,
+		       m_blocks * reserved / 100, reserved);
+		printk("EXT2-fs: ext2_update_group: %u inodes (%u free), "
+		       "%u blocks (%u free)\n",
+		       le32_to_cpu(es->s_inodes_count),
+		       le32_to_cpu(es->s_free_inodes_count),
+		       le32_to_cpu(es->s_blocks_count),
+		       le32_to_cpu(es->s_free_blocks_count));
+	}
+
+	return 0;
+} /* ext2_update_group */
+
+/* Resize the filesystem to the new number of blocks specified.  If required,
+ * the new group descriptors should have already been configured for us (we
+ * only check that they are valid).
+ */
+static int ext2_resize_fs(struct super_block *sb,
+			  struct ext2_super_block *es,
+			  unsigned long n_blocks_count, unsigned long resgdt)
+{
+	unsigned long o_blocks_count;
+	unsigned long o_groups_count;
+	unsigned long last, add;
+	unsigned long reserved;
+	struct buffer_head *bh;
+	unsigned long i;
+	int err = 0;
+
+	o_blocks_count = le32_to_cpu(es->s_blocks_count);
+	o_groups_count = EXT2_SB(sb)->s_groups_count;
+
+	if (test_opt(sb, DEBUG))
+		printk("EXT2-fs: ext2_resize_fs: from %lu to %lu blocks\n",
+		       o_blocks_count, n_blocks_count);
+
+	if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
+		return 0;
+
+	if (n_blocks_count < o_blocks_count) {
+		ext2_warning(sb, __FUNCTION__, "error: can't shrink FS!");
+		return -EBUSY;
+	}
+
+	/* See if the device is actually as big as what was requested */
+	bh = bread(sb->s_dev, n_blocks_count - 1, EXT2_BLOCK_SIZE(sb));
+	if (!bh) {
+		ext2_warning(sb, __FUNCTION__,
+			     "unable to read last block, resize aborted");
+		return -ENOSPC;
+	}
+	brelse(bh);
+
+	/* For reserved percentage calculation, we avoid 32-bit overflow. */
+	reserved = o_blocks_count > 10000000 ?
+		(le32_to_cpu(es->s_r_blocks_count) + o_blocks_count / 200) /
+			(o_blocks_count / 100) :
+		(le32_to_cpu(es->s_r_blocks_count) * 100 + o_blocks_count / 2) /
+			o_blocks_count;
+
+	if ((err = ext2_read_descriptors(sb, n_blocks_count))) {
+		ext2_warning(sb, __FUNCTION__,
+			     "group descriptor error %d, resize aborted", err);
+		return err;
+	}
+
+	/* Handle the remaining blocks in the last partial group. */
+	last = (o_blocks_count - le32_to_cpu(es->s_first_data_block)) %
+		EXT2_BLOCKS_PER_GROUP(sb);
+	if (last != 0) {	/* The last group isn't full yet */
+		struct inode inode;
+		add = EXT2_BLOCKS_PER_GROUP(sb) - last;
+		if (add + o_blocks_count > n_blocks_count)
+			add = n_blocks_count - o_blocks_count;
+		es->s_blocks_count =
+			cpu_to_le32(le32_to_cpu(es->s_blocks_count) + add);
+		es->s_r_blocks_count =
+			cpu_to_le32(le32_to_cpu(es->s_r_blocks_count) +
+				    add * reserved / 100);
+		mark_buffer_dirty(EXT2_SB(sb)->s_sbh);
+		sb->s_dirt = 1;
+		unlock_super(sb);
+		/*
+		 * Fake out an inode enough to "free" the new blocks in this
+		 * group.  Turn off quotas for this inode so it doesn't get
+		 * confused by freeing blocks that don't really exist yet.
+		 */
+		inode.i_sb = sb;
+		inode.i_state = I_DIRTY;
+		INIT_LIST_HEAD(&inode.i_hash);
+		for (i = 0; i < MAXQUOTAS; i++)
+			inode.i_dquot[i] = NODQUOT;
+		ext2_free_blocks(&inode, o_blocks_count, add);
+		if (test_opt(sb, DEBUG))
+			printk("EXT2-fs: ext2_resize_fs: added %lu new blocks "
+			       "to %lu blocks in last group\n",
+			       add, o_blocks_count);
+		lock_super(sb);
+	}
+
+	/*
+	 * Update superblock with remaining new group block/inode counts
+	 */
+	for (i = o_groups_count; i < EXT2_SB(sb)->s_groups_count &&
+	     !(err = ext2_update_group(sb, i, reserved, resgdt)); i++)
+		/* empty loop */;
+
+	if (err || le32_to_cpu(es->s_blocks_count) != n_blocks_count) {
+		ext2_warning(sb, __FUNCTION__,
+			     "specified size does not match new block count "
+			     "(%lu != %u) (err %d)", n_blocks_count,
+			     le32_to_cpu(es->s_blocks_count), err);
+		EXT2_SB(sb)->s_mount_state &= ~EXT2_VALID_FS;
+	} else
+		EXT2_SB(sb)->s_mount_state |= EXT2_VALID_FS;
+
+	return err;
+} /* ext2_resize_fs */
+#else  /* !CONFIG_EXT2_RESIZE */
+#define ext2_resize_fs(sb, es, n_blocks_count, resgdt) 0
+#endif /* CONFIG_EXT2_RESIZE */
+
 #define log2(n) ffz(~(n))
  
 /*
@@ -409,8 +700,7 @@
 	unsigned long offset = 0;
 	kdev_t dev = sb->s_dev;
 	int blocksize = BLOCK_SIZE;
-	int db_count;
-	int i, j;
+	int i;
 
 	/*
 	 * See what the current blocksize for the device is, and
@@ -425,7 +715,7 @@
 
 	sb->u.ext2_sb.s_mount_opt = 0;
 	if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
-	    &sb->u.ext2_sb.s_mount_opt)) {
+	    &sb->u.ext2_sb.s_mount_opt, NULL, NULL)) {
 		return NULL;
 	}
 
@@ -596,32 +886,6 @@
 		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] = sb_bread(sb, logic_sb_block + i + 1);
-		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(sb->u.ext2_sb.s_group_desc);
-			printk ("EXT2-fs: unable to read group descriptors\n");
-			goto failed_mount;
-		}
-	}
-	if (!ext2_check_descriptors (sb)) {
-		printk ("EXT2-fs: group descriptors corrupted!\n");
-		db_count = i;
-		goto failed_mount2;
-	}
 	for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
 		sb->u.ext2_sb.s_inode_bitmap_number[i] = 0;
 		sb->u.ext2_sb.s_inode_bitmap[i] = NULL;
@@ -630,11 +894,18 @@
 	}
 	sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
 	sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
-	sb->u.ext2_sb.s_gdb_count = db_count;
 	/*
 	 * set up enough so that it can read an inode
 	 */
 	sb->s_op = &ext2_sops;
+	sb->u.ext2_sb.s_group_desc = NULL;
+	sb->u.ext2_sb.s_groups_count = 0;
+	sb->u.ext2_sb.s_gdb_count = 0;
+	if ((i = ext2_read_descriptors(sb, le32_to_cpu(es->s_blocks_count)))) {
+		ext2_error(sb, __FUNCTION__,
+			   "group descriptor error %d, unable to mount", i);
+		goto failed_mount;
+	}
 	sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO));
 	if (!sb->s_root || !S_ISDIR(sb->s_root->d_inode->i_mode) ||
 	    !sb->s_root->d_inode->i_blocks || !sb->s_root->d_inode->i_size) {
@@ -649,7 +920,7 @@
 	ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
 	return sb;
 failed_mount2:
-	for (i = 0; i < db_count; i++)
+	for (i = 0; i < sb->u.ext2_sb.s_gdb_count; i++)
 		brelse(sb->u.ext2_sb.s_group_desc[i]);
 	kfree(sb->u.ext2_sb.s_group_desc);
 failed_mount:
@@ -709,6 +980,8 @@
 	struct ext2_super_block * es;
 	unsigned short resuid = sb->u.ext2_sb.s_resuid;
 	unsigned short resgid = sb->u.ext2_sb.s_resgid;
+	unsigned long n_blocks_count = 0;
+	unsigned long resgdt = 0;
 	unsigned long new_mount_opt;
 	unsigned long tmp;
 
@@ -717,14 +990,16 @@
 	 */
 	new_mount_opt = sb->u.ext2_sb.s_mount_opt;
 	if (!parse_options (data, &tmp, &resuid, &resgid,
-			    &new_mount_opt))
+			    &new_mount_opt, &n_blocks_count, &resgdt))
 		return -EINVAL;
 
 	sb->u.ext2_sb.s_mount_opt = new_mount_opt;
 	sb->u.ext2_sb.s_resuid = resuid;
 	sb->u.ext2_sb.s_resgid = resgid;
 	es = sb->u.ext2_sb.s_es;
-	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY) &&
+	    (n_blocks_count == 0 ||
+	     n_blocks_count == le32_to_cpu(es->s_blocks_count)))
 		return 0;
 	if (*flags & MS_RDONLY) {
 		if (le16_to_cpu(es->s_state) & EXT2_VALID_FS ||
@@ -751,6 +1026,8 @@
 		 * by e2fsck since we originally mounted the partition.)
 		 */
 		sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state);
+		if ((ret = ext2_resize_fs(sb, es, n_blocks_count, resgdt)))
+			return ret;
 		if (!ext2_setup_super (sb, es, 0))
 			sb->s_flags &= ~MS_RDONLY;
 	}
diff -ru linux-2.4.18.orig/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h
--- linux-2.4.18.orig/include/linux/ext2_fs.h	Thu Nov 22 11:46:52 2001
+++ linux/include/linux/ext2_fs.h	Wed Jun 19 14:56:34 2002
@@ -26,6 +26,7 @@
  * Define EXT2FS_DEBUG to produce debug messages
  */
 #undef EXT2FS_DEBUG
+#define CONFIG_EXT2_CHECK
 
 /*
  * Define EXT2_PREALLOCATE to preallocate data blocks for expanding files
@@ -61,6 +62,7 @@
 #define EXT2_ACL_DATA_INO	 4	/* ACL inode */
 #define EXT2_BOOT_LOADER_INO	 5	/* Boot loader inode */
 #define EXT2_UNDEL_DIR_INO	 6	/* Undelete directory inode */
+#define EXT2_RESIZE_INO		 7	/* Reserved group descriptors inode */
 
 /* First non-reserved inode for old ext2 filesystems */
 #define EXT2_GOOD_OLD_FIRST_INO	11

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]