On-disk and in-kernel super block changes to support >32 bit free blocks numbers. --- linux-2.6.16-ming/fs/ext3/balloc.c | 40 +++++++++--------- linux-2.6.16-ming/fs/ext3/ialloc.c | 12 +++-- linux-2.6.16-ming/fs/ext3/inode.c | 4 - linux-2.6.16-ming/fs/ext3/resize.c | 26 +++++------ linux-2.6.16-ming/fs/ext3/super.c | 49 ++++++++++++---------- linux-2.6.16-ming/include/linux/ext3_fs.h | 66 +++++++++++++++++++++++++++++- 6 files changed, 135 insertions(+), 62 deletions(-) diff -puN include/linux/ext3_fs.h~64bit-metadata include/linux/ext3_fs.h --- linux-2.6.16/include/linux/ext3_fs.h~64bit-metadata 2006-05-08 11:04:19.342322798 -0700 +++ linux-2.6.16-ming/include/linux/ext3_fs.h 2006-05-08 11:04:19.363320366 -0700 @@ -139,6 +139,40 @@ struct ext3_group_desc __le32 bg_reserved[3]; }; +#define EXT3_GROUP_BASE(s,g) ((sector_t)le32_to_cpu((s)->s_first_data_block) + \ + (sector_t)le32_to_cpu((s)->s_blocks_per_group) * (g)) + +#define EXT3_RELATIVE(group_base, block) \ + ((sector_t)(group_base) & 0xFFFFFFFF00000000ULL ? \ + (sector_t)(block) + (sector_t)(group_base) - 1 : \ + (sector_t)(block)) +#define EXT3_RELATIVE_SET(group_base, block, value) \ + (block) = cpu_to_le32((((sector_t)(group_base) & 0xFFFFFFFF00000000ULL) && \ + ((sector_t)(value) >= (sector_t)(group_base))) ? \ + (sector_t)(value) - (sector_t)(group_base) + 1 : \ + (sector_t)(value)) + +#define EXT3_BLOCK_BITMAP(bg, group_base) \ + EXT3_RELATIVE((group_base),le32_to_cpu((bg)->bg_block_bitmap)) +#define EXT3_INODE_BITMAP(bg, group_base) \ + EXT3_RELATIVE((group_base),le32_to_cpu((bg)->bg_inode_bitmap)) +#define EXT3_INODE_TABLE(bg, group_base) \ + EXT3_RELATIVE((group_base),le32_to_cpu((bg)->bg_inode_table)) + +#define EXT3_BLOCK_BITMAP_SET(bg, group_base, value) \ + EXT3_RELATIVE_SET((group_base),(bg)->bg_block_bitmap, value) +#define EXT3_INODE_BITMAP_SET(bg, group_base, value) \ + EXT3_RELATIVE_SET((group_base),(bg)->bg_inode_bitmap, value) +#define EXT3_INODE_TABLE_SET(bg, group_base, value) \ + EXT3_RELATIVE_SET((group_base),(bg)->bg_inode_table, value) + +#define EXT3_IS_USED_BLOCK_BITMAP(bg) \ + ((bg)->bg_block_bitmap != 0) +#define EXT3_IS_USED_INODE_BITMAP(bg) \ + ((bg)->bg_inode_bitmap != 0) +#define EXT3_IS_USED_INODE_TABLE(bg) \ + ((bg)->bg_inode_table != 0) + /* * Macro-instructions used to manage group descriptors */ @@ -493,9 +527,35 @@ struct ext3_super_block { __u16 s_reserved_word_pad; __le32 s_default_mount_opts; __le32 s_first_meta_bg; /* First metablock block group */ - __u32 s_reserved[190]; /* Padding to the end of the block */ + /* 64bit support valid if EXT3_FEATURE_COMPAT_64BIT */ + __le32 s_blocks_count_hi; /* Blocks count */ +/*100*/ __le32 s_r_blocks_count_hi; /* Reserved blocks count */ + __le32 s_free_blocks_count_hi; /* Free blocks count */ + __u32 s_reserved[187]; /* Padding to the end of the block */ }; + +#define EXT3_BLOCKS_COUNT(s) (((s)->s_feature_ro_compat & EXT3_FEATURE_RO_COMPAT_64BIT ? ((__u64)le32_to_cpu((s)->s_blocks_count_hi) << 32) : 0) | (__u64)le32_to_cpu((s)->s_blocks_count)) +#define EXT3_BLOCKS_COUNT_SET(s,v) do { \ + (s)->s_blocks_count = cpu_to_le32((v)); \ + if ((s)->s_feature_ro_compat & EXT3_FEATURE_RO_COMPAT_64BIT) \ + (s)->s_blocks_count_hi = cpu_to_le32(((__u64)(v)) >> 32); \ +} while (0) + +#define EXT3_R_BLOCKS_COUNT(s) (((s)->s_feature_ro_compat & EXT3_FEATURE_RO_COMPAT_64BIT ? ((__u64)le32_to_cpu((s)->s_r_blocks_count_hi) << 32) : 0) | (__u64)le32_to_cpu((s)->s_r_blocks_count)) +#define EXT3_R_BLOCKS_COUNT_SET(s,v) do { \ + (s)->s_r_blocks_count = cpu_to_le32((v)); \ + if ((s)->s_feature_ro_compat & EXT3_FEATURE_RO_COMPAT_64BIT) \ + (s)->s_r_blocks_count_hi = cpu_to_le32(((__u64)(v)) >> 32); \ +} while (0) + +#define EXT3_FREE_BLOCKS_COUNT(s) (((s)->s_feature_ro_compat & EXT3_FEATURE_RO_COMPAT_64BIT ? ((__u64)le32_to_cpu((s)->s_free_blocks_count_hi) << 32) : 0) | (__u64)le32_to_cpu((s)->s_free_blocks_count)) +#define EXT3_FREE_BLOCKS_COUNT_SET(s,v) do { \ + (s)->s_free_blocks_count = cpu_to_le32((v)); \ + if ((s)->s_feature_ro_compat & EXT3_FEATURE_RO_COMPAT_64BIT) \ + (s)->s_free_blocks_count_hi = cpu_to_le32(((__u64)(v)) >> 32); \ +} while (0) + #ifdef __KERNEL__ static inline struct ext3_sb_info * EXT3_SB(struct super_block *sb) { @@ -567,6 +627,7 @@ static inline struct ext3_inode_info *EX #define EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 #define EXT3_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 #define EXT3_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 +#define EXT3_FEATURE_RO_COMPAT_64BIT 0x0010 #define EXT3_FEATURE_INCOMPAT_COMPRESSION 0x0001 #define EXT3_FEATURE_INCOMPAT_FILETYPE 0x0002 @@ -582,7 +643,8 @@ static inline struct ext3_inode_info *EX EXT3_FEATURE_INCOMPAT_EXTENTS) #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \ EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \ - EXT3_FEATURE_RO_COMPAT_BTREE_DIR) + EXT3_FEATURE_RO_COMPAT_BTREE_DIR| \ + EXT3_FEATURE_RO_COMPAT_64BIT) /* * Default values for user and/or group using reserved blocks diff -puN fs/ext3/balloc.c~64bit-metadata fs/ext3/balloc.c --- linux-2.6.16/fs/ext3/balloc.c~64bit-metadata 2006-05-08 11:04:19.345322451 -0700 +++ linux-2.6.16-ming/fs/ext3/balloc.c 2006-05-08 11:04:19.367319903 -0700 @@ -92,12 +92,12 @@ read_block_bitmap(struct super_block *sb desc = ext3_get_group_desc (sb, block_group, NULL); if (!desc) goto error_out; - bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap)); + bh = sb_bread(sb, EXT3_BLOCK_BITMAP(desc, EXT3_GROUP_BASE(EXT3_SB(sb)->s_es,block_group))); if (!bh) ext3_error (sb, "read_block_bitmap", "Cannot read block bitmap - " - "block_group = %d, block_bitmap = %u", - block_group, le32_to_cpu(desc->bg_block_bitmap)); + "block_group = %d, block_bitmap = %llu", + block_group, EXT3_BLOCK_BITMAP(desc, EXT3_GROUP_BASE(EXT3_SB(sb)->s_es,block_group))); error_out: return bh; } @@ -333,7 +333,7 @@ void ext3_free_blocks_sb(handle_t *handl es = sbi->s_es; if (block < le32_to_cpu(es->s_first_data_block) || block + count < block || - block + count > le32_to_cpu(es->s_blocks_count)) { + block + count > EXT3_BLOCKS_COUNT(es)) { ext3_error (sb, "ext3_free_blocks", "Freeing blocks not in datazone - " "block = %llu, count = %llu", @@ -363,11 +363,11 @@ do_more: if (!desc) goto error_return; - if (in_range (le32_to_cpu(desc->bg_block_bitmap), block, count) || - in_range (le32_to_cpu(desc->bg_inode_bitmap), block, count) || - in_range (block, le32_to_cpu(desc->bg_inode_table), + if (in_range (EXT3_BLOCK_BITMAP(desc, EXT3_GROUP_BASE(es, block_group)), block, count) || + in_range (EXT3_INODE_BITMAP(desc, EXT3_GROUP_BASE(es, block_group)), block, count) || + in_range (block, EXT3_INODE_TABLE(desc, EXT3_GROUP_BASE(es, block_group)), sbi->s_itb_per_group) || - in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table), + in_range (block + count - 1, EXT3_INODE_TABLE(desc, EXT3_GROUP_BASE(es, block_group)), sbi->s_itb_per_group)) ext3_error (sb, "ext3_free_blocks", "Freeing blocks in system zones - " @@ -1130,7 +1130,7 @@ static int ext3_has_free_blocks(struct e sector_t free_blocks, root_blocks; free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter); - root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count); + root_blocks = EXT3_R_BLOCKS_COUNT(sbi->s_es); if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) && sbi->s_resuid != current->fsuid && (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) { @@ -1227,7 +1227,7 @@ sector_t ext3_new_block(handle_t *handle * First, test whether the goal block is free. */ if (goal < le32_to_cpu(es->s_first_data_block) || - goal >= le32_to_cpu(es->s_blocks_count)) + goal >= EXT3_BLOCKS_COUNT(es)) goal = le32_to_cpu(es->s_first_data_block); EXT3_BLOCK_GROUP(sb, group_no, ret_block, goal - le32_to_cpu(es->s_first_data_block)); gdp = ext3_get_group_desc(sb, group_no, &gdp_bh); @@ -1323,9 +1323,9 @@ allocated: target_block = ret_block + group_no * EXT3_BLOCKS_PER_GROUP(sb) + le32_to_cpu(es->s_first_data_block); - if (target_block == le32_to_cpu(gdp->bg_block_bitmap) || - target_block == le32_to_cpu(gdp->bg_inode_bitmap) || - in_range(target_block, le32_to_cpu(gdp->bg_inode_table), + if (target_block == EXT3_BLOCK_BITMAP(gdp, EXT3_GROUP_BASE(es, group_no)) || + target_block == EXT3_INODE_BITMAP(gdp, EXT3_GROUP_BASE(es, group_no)) || + in_range(target_block, EXT3_INODE_TABLE(gdp, EXT3_GROUP_BASE(es, group_no)), EXT3_SB(sb)->s_itb_per_group)) ext3_error(sb, "ext3_new_block", "Allocating block in system zone - " @@ -1359,12 +1359,12 @@ allocated: jbd_unlock_bh_state(bitmap_bh); #endif - if (target_block >= le32_to_cpu(es->s_blocks_count)) { + if (target_block >= EXT3_BLOCKS_COUNT(es)) { ext3_error(sb, "ext3_new_block", - "block(%llu) >= blocks count(%d) - " + "block(%llu) >= blocks count(%llu) - " "block_group = %llu, es == %p ", (unsigned long long)target_block, - le32_to_cpu(es->s_blocks_count), + EXT3_BLOCKS_COUNT(es), (unsigned long long)group_no, es); goto out; } @@ -1414,13 +1414,13 @@ out: sector_t ext3_count_free_blocks(struct super_block *sb) { - unsigned long desc_count; + sector_t desc_count; struct ext3_group_desc *gdp; int i; unsigned long ngroups = EXT3_SB(sb)->s_groups_count; #ifdef EXT3FS_DEBUG struct ext3_super_block *es; - unsigned long bitmap_count, x; + sector_t bitmap_count, x; struct buffer_head *bitmap_bh = NULL; es = EXT3_SB(sb)->s_es; @@ -1445,8 +1445,8 @@ sector_t ext3_count_free_blocks(struct s bitmap_count += x; } brelse(bitmap_bh); - printk("ext3_count_free_blocks: stored = %u, computed = %lu, %lu\n", - le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count); + printk("ext3_count_free_blocks: stored = %llu, computed = %llu, %lu\n", + EXT3_FREE_BLOCKS_COUNT(es), (unsigned long long)desc_count, bitmap_count); return bitmap_count; #else desc_count = 0; diff -puN fs/ext3/ialloc.c~64bit-metadata fs/ext3/ialloc.c --- linux-2.6.16/fs/ext3/ialloc.c~64bit-metadata 2006-05-08 11:04:19.348322103 -0700 +++ linux-2.6.16-ming/fs/ext3/ialloc.c 2006-05-08 11:04:19.369319671 -0700 @@ -60,12 +60,13 @@ read_inode_bitmap(struct super_block * s if (!desc) goto error_out; - bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap)); + bh = sb_bread(sb, EXT3_INODE_BITMAP(desc, EXT3_GROUP_BASE(EXT3_SB(sb)->s_es, block_group))); if (!bh) ext3_error(sb, "read_inode_bitmap", "Cannot read inode bitmap - " - "block_group = %lu, inode_bitmap = %u", - block_group, le32_to_cpu(desc->bg_inode_bitmap)); + "block_group = %lu, inode_bitmap = %llu", + block_group, + EXT3_INODE_BITMAP(desc, EXT3_GROUP_BASE(EXT3_SB(sb)->s_es, block_group))); error_out: return bh; } @@ -268,6 +269,7 @@ static int find_group_orlov(struct super int group = -1, i; struct ext3_group_desc *desc; struct buffer_head *bh; + __u64 block_counts; freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); avefreei = freei / ngroups; @@ -301,7 +303,9 @@ static int find_group_orlov(struct super goto fallback; } - blocks_per_dir = (le32_to_cpu(es->s_blocks_count) - freeb) / ndirs; + block_counts = EXT3_BLOCKS_COUNT(es) - freeb; + do_div(block_counts, ndirs); + blocks_per_dir = block_counts; max_dirs = ndirs / ngroups + inodes_per_group / 16; min_inodes = avefreei - inodes_per_group / 4; diff -puN fs/ext3/inode.c~64bit-metadata fs/ext3/inode.c --- linux-2.6.16/fs/ext3/inode.c~64bit-metadata 2006-05-08 11:04:19.352321640 -0700 +++ linux-2.6.16-ming/fs/ext3/inode.c 2006-05-08 11:04:19.373319208 -0700 @@ -2304,7 +2304,7 @@ static sector_t ext3_get_inode_block(str */ offset = ((ino - 1) % EXT3_INODES_PER_GROUP(sb)) * EXT3_INODE_SIZE(sb); - block = le32_to_cpu(gdp[desc].bg_inode_table) + + block = EXT3_INODE_TABLE((gdp+desc), EXT3_GROUP_BASE(EXT3_SB(sb)->s_es, block_group)) + (offset >> EXT3_BLOCK_SIZE_BITS(sb)); iloc->block_group = block_group; @@ -2372,7 +2372,7 @@ static int __ext3_get_inode_loc(struct i goto make_io; bitmap_bh = sb_getblk(inode->i_sb, - le32_to_cpu(desc->bg_inode_bitmap)); + EXT3_INODE_BITMAP(desc, EXT3_GROUP_BASE(EXT3_SB(inode->i_sb)->s_es, block_group))); if (!bitmap_bh) goto make_io; diff -puN fs/ext3/resize.c~64bit-metadata fs/ext3/resize.c --- linux-2.6.16/fs/ext3/resize.c~64bit-metadata 2006-05-08 11:04:19.355321293 -0700 +++ linux-2.6.16-ming/fs/ext3/resize.c 2006-05-08 11:04:19.376318861 -0700 @@ -29,7 +29,7 @@ static int verify_group_input(struct sup { struct ext3_sb_info *sbi = EXT3_SB(sb); struct ext3_super_block *es = sbi->s_es; - unsigned start = le32_to_cpu(es->s_blocks_count); + unsigned start = EXT3_BLOCKS_COUNT(es); unsigned end = start + input->blocks_count; unsigned group = input->group; unsigned itend = input->inode_table + sbi->s_itb_per_group; @@ -815,9 +815,9 @@ int ext3_group_add(struct super_block *s /* Update group descriptor block for new group */ gdp = (struct ext3_group_desc *)primary->b_data + gdb_off; - gdp->bg_block_bitmap = cpu_to_le32(input->block_bitmap); - gdp->bg_inode_bitmap = cpu_to_le32(input->inode_bitmap); - gdp->bg_inode_table = cpu_to_le32(input->inode_table); + EXT3_BLOCK_BITMAP_SET(gdp, EXT3_GROUP_BASE(es, gdb_num), input->block_bitmap); /* LV FIXME */ + EXT3_INODE_BITMAP_SET(gdp, EXT3_GROUP_BASE(es, gdb_num), input->inode_bitmap); /* LV FIXME */ + EXT3_INODE_TABLE_SET(gdp, EXT3_GROUP_BASE(es, gdb_num), input->inode_table); /* LV FIXME */ gdp->bg_free_blocks_count = cpu_to_le16(input->free_blocks_count); gdp->bg_free_inodes_count = cpu_to_le16(EXT3_INODES_PER_GROUP(sb)); @@ -831,7 +831,7 @@ int ext3_group_add(struct super_block *s * blocks/inodes before the group is live won't actually let us * allocate the new space yet. */ - es->s_blocks_count = cpu_to_le32(le32_to_cpu(es->s_blocks_count) + + EXT3_BLOCKS_COUNT_SET(es, EXT3_BLOCKS_COUNT(es) + input->blocks_count); es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb)); @@ -867,7 +867,7 @@ int ext3_group_add(struct super_block *s /* Update the reserved block counts only once the new group is * active. */ - es->s_r_blocks_count = cpu_to_le32(le32_to_cpu(es->s_r_blocks_count) + + EXT3_R_BLOCKS_COUNT_SET(es, EXT3_R_BLOCKS_COUNT(es) + input->reserved_blocks); /* Update the free space counts */ @@ -909,7 +909,7 @@ int ext3_group_extend(struct super_block sector_t o_blocks_count; unsigned long o_groups_count; unsigned long last; - int add; + sector_t add; struct buffer_head * bh; handle_t *handle; int err; @@ -918,7 +918,7 @@ int ext3_group_extend(struct super_block /* We don't need to worry about locking wrt other resizers just * yet: we're going to revalidate es->s_blocks_count after * taking lock_super() below. */ - o_blocks_count = le32_to_cpu(es->s_blocks_count); + o_blocks_count = EXT3_BLOCKS_COUNT(es); o_groups_count = EXT3_SB(sb)->s_groups_count; if (test_opt(sb, DEBUG)) @@ -952,7 +952,7 @@ int ext3_group_extend(struct super_block if (o_blocks_count + add < n_blocks_count) ext3_warning(sb, __FUNCTION__, - "will only finish group (%llu blocks, %u new)", + "will only finish group (%llu blocks, %llu new)", (unsigned long long)(o_blocks_count + add), add); /* See if the device is actually as big as what was requested */ @@ -975,7 +975,7 @@ int ext3_group_extend(struct super_block } lock_super(sb); - if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) { + if (o_blocks_count != EXT3_BLOCKS_COUNT(es)) { ext3_warning(sb, __FUNCTION__, "multiple resizers run on filesystem!"); err = -EBUSY; @@ -990,7 +990,7 @@ int ext3_group_extend(struct super_block ext3_journal_stop(handle); goto exit_put; } - es->s_blocks_count = cpu_to_le32(o_blocks_count + add); + EXT3_BLOCKS_COUNT_SET(es, o_blocks_count + add); ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); sb->s_dirt = 1; unlock_super(sb); @@ -1002,8 +1002,8 @@ int ext3_group_extend(struct super_block if ((err = ext3_journal_stop(handle))) goto exit_put; if (test_opt(sb, DEBUG)) - printk(KERN_DEBUG "EXT3-fs: extended group to %u blocks\n", - le32_to_cpu(es->s_blocks_count)); + printk(KERN_DEBUG "EXT3-fs: extended group to %llu blocks\n", + EXT3_BLOCKS_COUNT(es)); update_backups(sb, EXT3_SB(sb)->s_sbh->b_blocknr, (char *)es, sizeof(struct ext3_super_block)); exit_put: diff -puN fs/ext3/super.c~64bit-metadata fs/ext3/super.c --- linux-2.6.16/fs/ext3/super.c~64bit-metadata 2006-05-08 11:04:19.359320829 -0700 +++ linux-2.6.16-ming/fs/ext3/super.c 2006-05-08 11:04:19.382318166 -0700 @@ -1149,44 +1149,44 @@ static int ext3_check_descriptors (struc if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0) gdp = (struct ext3_group_desc *) sbi->s_group_desc[desc_block++]->b_data; - if (le32_to_cpu(gdp->bg_block_bitmap) < block || - le32_to_cpu(gdp->bg_block_bitmap) >= + if (EXT3_BLOCK_BITMAP(gdp, EXT3_GROUP_BASE(sbi->s_es, i)) < block || + EXT3_BLOCK_BITMAP(gdp, EXT3_GROUP_BASE(sbi->s_es, i)) >= block + EXT3_BLOCKS_PER_GROUP(sb)) { ext3_error (sb, "ext3_check_descriptors", "Block bitmap for group %d" " not in group (block %llu)!", i, (unsigned long long) - le32_to_cpu(gdp->bg_block_bitmap)); + EXT3_BLOCK_BITMAP(gdp, EXT3_GROUP_BASE(sbi->s_es, i))); return 0; } - if (le32_to_cpu(gdp->bg_inode_bitmap) < block || - le32_to_cpu(gdp->bg_inode_bitmap) >= + if (EXT3_INODE_BITMAP(gdp, EXT3_GROUP_BASE(sbi->s_es, i)) < block || + EXT3_INODE_BITMAP(gdp, EXT3_GROUP_BASE(sbi->s_es, i)) >= block + EXT3_BLOCKS_PER_GROUP(sb)) { ext3_error (sb, "ext3_check_descriptors", "Inode bitmap for group %d" " not in group (block %llu)!", i, (unsigned long long) - le32_to_cpu(gdp->bg_inode_bitmap)); + EXT3_INODE_BITMAP(gdp, EXT3_GROUP_BASE(sbi->s_es, i))); return 0; } - if (le32_to_cpu(gdp->bg_inode_table) < block || - le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >= + if (EXT3_INODE_TABLE(gdp, EXT3_GROUP_BASE(sbi->s_es, i)) < block || + EXT3_INODE_TABLE(gdp, EXT3_GROUP_BASE(sbi->s_es, i)) + sbi->s_itb_per_group >= block + EXT3_BLOCKS_PER_GROUP(sb)) { ext3_error (sb, "ext3_check_descriptors", "Inode table for group %d" " not in group (block %llu)!", i, (unsigned long long) - le32_to_cpu(gdp->bg_inode_table)); + EXT3_INODE_TABLE(gdp, EXT3_GROUP_BASE(sbi->s_es, i))); return 0; } block += EXT3_BLOCKS_PER_GROUP(sb); gdp++; } - sbi->s_es->s_free_blocks_count=cpu_to_le32(ext3_count_free_blocks(sb)); + EXT3_FREE_BLOCKS_COUNT_SET(sbi->s_es, ext3_count_free_blocks(sb)); sbi->s_es->s_free_inodes_count=cpu_to_le32(ext3_count_free_inodes(sb)); return 1; } @@ -1364,6 +1364,7 @@ static int ext3_fill_super (struct super int i; int needs_recovery; __le32 features; + __u64 blocks_count; sbi = kmalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) @@ -1577,10 +1578,11 @@ static int ext3_fill_super (struct super if (EXT3_BLOCKS_PER_GROUP(sb) == 0) goto cantfind_ext3; - sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) - - le32_to_cpu(es->s_first_data_block) + - EXT3_BLOCKS_PER_GROUP(sb) - 1) / - EXT3_BLOCKS_PER_GROUP(sb); + blocks_count = (EXT3_BLOCKS_COUNT(es) - + le32_to_cpu(es->s_first_data_block) + + EXT3_BLOCKS_PER_GROUP(sb) - 1); + do_div(blocks_count, EXT3_BLOCKS_PER_GROUP(sb)); + sbi->s_groups_count = blocks_count; db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) / EXT3_DESC_PER_BLOCK(sb); sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *), @@ -1749,6 +1751,11 @@ static int ext3_fill_super (struct super ext3_ext_init(sb); + if (EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT3_FEATURE_RO_COMPAT_64BIT)) { + set_opt (sbi->s_mount_opt, EXTENTS); + printk("EXT3-fs: 64bit meta-data enabled\n"); + } + lock_kernel(); return 0; @@ -1847,7 +1854,7 @@ static journal_t *ext3_get_dev_journal(s struct buffer_head * bh; journal_t *journal; int start; - int len; + sector_t len; int hblock, blocksize; sector_t sb_block; unsigned long offset; @@ -1898,7 +1905,7 @@ static journal_t *ext3_get_dev_journal(s goto out_bdev; } - len = le32_to_cpu(es->s_blocks_count); + len = EXT3_BLOCKS_COUNT(es); start = sb_block + 1; brelse(bh); /* we're done with the superblock */ @@ -2068,7 +2075,7 @@ static void ext3_commit_super (struct su if (!sbh) return; es->s_wtime = cpu_to_le32(get_seconds()); - es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb)); + EXT3_FREE_BLOCKS_COUNT_SET(es, ext3_count_free_blocks(sb)); es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb)); BUFFER_TRACE(sbh, "marking dirty"); mark_buffer_dirty(sbh); @@ -2261,7 +2268,7 @@ static int ext3_remount (struct super_bl ext3_init_journal_params(sb, sbi->s_journal); if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) || - n_blocks_count > le32_to_cpu(es->s_blocks_count)) { + n_blocks_count > EXT3_BLOCKS_COUNT(es)) { if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) { err = -EROFS; goto restore_opts; @@ -2380,10 +2387,10 @@ static int ext3_statfs (struct super_blo 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_blocks = EXT3_BLOCKS_COUNT(es) - overhead; buf->f_bfree = ext3_count_free_blocks (sb); - 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 = buf->f_bfree - EXT3_R_BLOCKS_COUNT(es); + if (buf->f_bfree < EXT3_R_BLOCKS_COUNT(es)) buf->f_bavail = 0; buf->f_files = le32_to_cpu(es->s_inodes_count); buf->f_ffree = ext3_count_free_inodes (sb); _