* Re: [linux-lvm] ext2online and 2.4.18
2002-06-19 16:49 ` Andreas Dilger
@ 2002-06-19 17:27 ` Ian Prowell
2002-06-20 6:28 ` sander
0 siblings, 1 reply; 14+ messages in thread
From: Ian Prowell @ 2002-06-19 17:27 UTC (permalink / raw)
To: Andreas Dilger; +Cc: linux-lvm
[-- Attachment #1: Type: text/plain, Size: 2060 bytes --]
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 #2: super.c.rej --]
[-- Type: application/x-reject, Size: 1460 bytes --]
[-- Attachment #3: online-ext2-2.4.18.diff --]
[-- Type: text/x-patch, Size: 20345 bytes --]
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
^ permalink raw reply [flat|nested] 14+ messages in thread