Index: linux-2.6.12/fs/ext3/super.c =================================================================== --- linux-2.6.12.orig/fs/ext3/super.c 2005-06-17 13:48:29.000000000 -0600 +++ linux-2.6.12/fs/ext3/super.c 2005-11-25 05:59:47.000000000 -0700 @@ -2165,13 +2165,13 @@ { struct ext3_super_block *es = EXT3_SB(sb)->s_es; unsigned long overhead; - int i; if (test_opt (sb, MINIX_DF)) overhead = 0; else { - unsigned long ngroups; - ngroups = EXT3_SB(sb)->s_groups_count; + unsigned long ngroups = EXT3_SB(sb)->s_groups_count, group; + unsigned long three = 1, five = 5, seven = 7; + unsigned long metabg = -1UL; smp_rmb(); /* @@ -2189,11 +2188,14 @@ * block group descriptors. If the sparse superblocks * feature is turned on, then not all groups have this. */ - for (i = 0; i < ngroups; i++) { - overhead += ext3_bg_has_super(sb, i) + - ext3_bg_num_gdb(sb, i); - cond_resched(); - } + overhead += 1 + EXT3_SB(sb)->s_gdb_count; /* group 0 */ + if (EXT3_HAS_INCOMPAT_FEATURE(sb,EXT3_FEATURE_INCOMPAT_META_BG)) + metabg =le32_to_cpu(EXT3_SB(sb)->s_es->s_first_meta_bg); + + while ((group = ext3_list_backups(sb, &three, &five, &seven)) < + ngroups) /* sb + group descriptors backups */ + overhead += 1 + (group >= metabg ? 1 : + EXT3_SB(sb)->s_gdb_count); /* * Every block group has an inode bitmap, a block @@ -2205,12 +2204,16 @@ buf->f_type = EXT3_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead; - buf->f_bfree = ext3_count_free_blocks (sb); + buf->f_bfree = percpu_counter_read(&EXT3_SB(sb)->s_freeblocks_counter); + if (buf->f_bfree < 0) + buf->f_bfree = 0; buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) buf->f_bavail = 0; buf->f_files = le32_to_cpu(es->s_inodes_count); - buf->f_ffree = ext3_count_free_inodes (sb); + buf->f_ffree = percpu_counter_read(&EXT3_SB(sb)->s_freeinodes_counter); + if (buf->f_ffree < 0) + buf->f_ffree = 0; buf->f_namelen = EXT3_NAME_LEN; return 0; } Index: linux-2.6.12/fs/ext3/resize.c =================================================================== --- linux-2.6.12.orig/fs/ext3/resize.c 2005-11-24 15:17:06.000000000 -0700 +++ linux-2.6.12/fs/ext3/resize.c 2005-11-25 06:01:01.000000000 -0700 @@ -285,17 +285,17 @@ * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ... * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ... */ -static unsigned ext3_list_backups(struct super_block *sb, unsigned *three, - unsigned *five, unsigned *seven) +unsigned long ext3_list_backups(struct super_block *sb, unsigned long *three, + unsigned long *five, unsigned long *seven) { - unsigned *min = three; + unsigned long metabg = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_meta_bg); + unsigned long *min = three, ret; int mult = 3; - unsigned ret; if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)) { - ret = *min; - *min += 1; + ret = *three; + *three += 1; return ret; } @@ -308,8 +307,26 @@ mult = 7; } - ret = *min; - *min *= mult; + if (EXT3_HAS_INCOMPAT_FEATURE(sb,EXT3_FEATURE_INCOMPAT_META_BG) && + *min >= metabg * EXT3_DESC_PER_BLOCK(sb)) { + ret = *min; + switch (ret & (EXT3_DESC_PER_BLOCK(sb) - 1)) { + case 0: + *three = ret + 1; + break; + case 1: + *three = ret + EXT3_DESC_PER_BLOCK(sb) - 2; + break; + default: + *three = (ret | (EXT3_DESC_PER_BLOCK(sb) - 1)) + 1; + break; + } + *five = -1UL; + *seven = -1UL; + } else { + ret = *min; + *min *= mult; + } return ret; } @@ -324,17 +337,17 @@ { const unsigned long blk = primary->b_blocknr; const unsigned long end = EXT3_SB(sb)->s_groups_count; - unsigned three = 1; - unsigned five = 5; - unsigned seven = 7; - unsigned grp; + unsigned long three = 1; + unsigned long five = 5; + unsigned long seven = 7; + unsigned long grp; __u32 *p = (__u32 *)primary->b_data; int gdbackups = 0; while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) { if (le32_to_cpu(*p++) != grp * EXT3_BLOCKS_PER_GROUP(sb) + blk){ ext3_warning(sb, __FUNCTION__, - "reserved GDT %ld missing grp %d (%ld)\n", + "reserved GDT %ld missing grp %ld (%ld)\n", blk, grp, grp * EXT3_BLOCKS_PER_GROUP(sb) + blk); return -EINVAL; @@ -618,10 +631,8 @@ struct ext3_sb_info *sbi = EXT3_SB(sb); const unsigned long last = sbi->s_groups_count; const int bpg = EXT3_BLOCKS_PER_GROUP(sb); - unsigned three = 1; - unsigned five = 5; - unsigned seven = 7; - unsigned group; + unsigned long three = 1, five = 5, seven = 7; + unsigned long group; int rest = sb->s_blocksize - size; handle_t *handle; int err = 0, err2; @@ -672,7 +683,7 @@ exit_err: if (err) { ext3_warning(sb, __FUNCTION__, - "can't update backup for group %d (err %d), " + "can't update backup for group %ld (err %d), " "forcing fsck on next reboot\n", group, err); sbi->s_mount_state &= ~EXT3_VALID_FS; sbi->s_es->s_state &= ~cpu_to_le16(EXT3_VALID_FS); Index: linux-2.6.12/include/linux/ext3_fs.h =================================================================== --- linux-2.6.12.orig/include/linux/ext3_fs.h 2005-06-17 13:48:29.000000000 -0600 +++ linux-2.6.12/include/linux/ext3_fs.h 2005-11-25 05:59:47.000000000 -0700 @@ -788,6 +788,10 @@ extern int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, unsigned long n_blocks_count); +extern unsigned long ext3_list_backups(struct super_block *sb, + unsigned long *three, + unsigned long *five, + unsigned long *seven); /* super.c */ extern void ext3_error (struct super_block *, const char *, const char *, ...)