[PATCH] ext4: 64bit metadata
authorLaurent Vivier <Laurent.Vivier@bull.net>
Wed, 11 Oct 2006 08:21:10 +0000 (01:21 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Wed, 11 Oct 2006 18:14:17 +0000 (11:14 -0700)
In-kernel super block changes to support >32 bit free blocks numbers.

Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
Signed-off-by: Alexandre Ratchov <alexandre.ratchov@bull.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/ext4/balloc.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/resize.c
fs/ext4/super.c
include/linux/ext4_fs.h

index aa33ff2..6887151 100644 (file)
@@ -99,12 +99,13 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
        desc = ext4_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, ext4_block_bitmap(desc));
        if (!bh)
                ext4_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 = "E3FSBLK,
+                           block_group,
+                           ext4_block_bitmap(desc));
 error_out:
        return bh;
 }
@@ -432,14 +433,14 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
        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 > ext4_blocks_count(es)) {
                ext4_error (sb, "ext4_free_blocks",
                            "Freeing blocks not in datazone - "
                            "block = "E3FSBLK", count = %lu", block, count);
                goto error_return;
        }
 
-       ext4_debug ("freeing block(s) %lu-%lu\n", block, block + count - 1);
+       ext4_debug ("freeing block(s) %llu-%llu\n", block, block + count - 1);
 
 do_more:
        overflow = 0;
@@ -460,12 +461,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),
-                     sbi->s_itb_per_group) ||
-           in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table),
-                     sbi->s_itb_per_group))
+       if (in_range(ext4_block_bitmap(desc), block, count) ||
+           in_range(ext4_inode_bitmap(desc), block, count) ||
+           in_range(block, ext4_inode_table(desc), sbi->s_itb_per_group) ||
+           in_range(block + count - 1, ext4_inode_table(desc),
+                    sbi->s_itb_per_group))
                ext4_error (sb, "ext4_free_blocks",
                            "Freeing blocks in system zones - "
                            "Block = "E3FSBLK", count = %lu",
@@ -552,8 +552,8 @@ do_more:
                                                bit + i, bitmap_bh->b_data)) {
                        jbd_unlock_bh_state(bitmap_bh);
                        ext4_error(sb, __FUNCTION__,
-                               "bit already cleared for block "E3FSBLK,
-                                block + i);
+                                  "bit already cleared for block "E3FSBLK,
+                                  (ext4_fsblk_t)(block + i));
                        jbd_lock_bh_state(bitmap_bh);
                        BUFFER_TRACE(bitmap_bh, "bit already cleared");
                } else {
@@ -1351,7 +1351,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
        ext4_fsblk_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 = ext4_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))) {
@@ -1462,7 +1462,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
         * 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 >= ext4_blocks_count(es))
                goal = le32_to_cpu(es->s_first_data_block);
        ext4_get_group_no_and_offset(sb, goal, &group_no, &grp_target_blk);
        goal_group = group_no;
@@ -1561,12 +1561,12 @@ allocated:
 
        ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no);
 
-       if (in_range(le32_to_cpu(gdp->bg_block_bitmap), ret_block, num) ||
-           in_range(le32_to_cpu(gdp->bg_inode_bitmap), ret_block, num) ||
-           in_range(ret_block, le32_to_cpu(gdp->bg_inode_table),
-                     EXT4_SB(sb)->s_itb_per_group) ||
-           in_range(ret_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
-                     EXT4_SB(sb)->s_itb_per_group))
+       if (in_range(ext4_block_bitmap(gdp), ret_block, num) ||
+           in_range(ext4_block_bitmap(gdp), ret_block, num) ||
+           in_range(ret_block, ext4_inode_table(gdp),
+                    EXT4_SB(sb)->s_itb_per_group) ||
+           in_range(ret_block + num - 1, ext4_inode_table(gdp),
+                    EXT4_SB(sb)->s_itb_per_group))
                ext4_error(sb, "ext4_new_block",
                            "Allocating block in system zone - "
                            "blocks from "E3FSBLK", length %lu",
@@ -1604,11 +1604,11 @@ allocated:
        jbd_unlock_bh_state(bitmap_bh);
 #endif
 
-       if (ret_block + num - 1 >= le32_to_cpu(es->s_blocks_count)) {
+       if (ret_block + num - 1 >= ext4_blocks_count(es)) {
                ext4_error(sb, "ext4_new_block",
-                           "block("E3FSBLK") >= blocks count(%d) - "
+                           "block("E3FSBLK") >= blocks count("E3FSBLK") - "
                            "block_group = %lu, es == %p ", ret_block,
-                       le32_to_cpu(es->s_blocks_count), group_no, es);
+                       ext4_blocks_count(es), group_no, es);
                goto out;
        }
 
@@ -1707,7 +1707,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb)
        brelse(bitmap_bh);
        printk("ext4_count_free_blocks: stored = "E3FSBLK
                ", computed = "E3FSBLK", "E3FSBLK"\n",
-              le32_to_cpu(es->s_free_blocks_count),
+              EXT4_FREE_BLOCKS_COUNT(es),
                desc_count, bitmap_count);
        return bitmap_count;
 #else
index 94e1bb4..959b7fa 100644 (file)
@@ -60,12 +60,12 @@ read_inode_bitmap(struct super_block * sb, unsigned long block_group)
        if (!desc)
                goto error_out;
 
-       bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap));
+       bh = sb_bread(sb, ext4_inode_bitmap(desc));
        if (!bh)
                ext4_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, ext4_inode_bitmap(desc));
 error_out:
        return bh;
 }
@@ -304,7 +304,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
                goto fallback;
        }
 
-       blocks_per_dir = le32_to_cpu(es->s_blocks_count) - freeb;
+       blocks_per_dir = ext4_blocks_count(es) - freeb;
        sector_div(blocks_per_dir, ndirs);
 
        max_dirs = ndirs / ngroups + inodes_per_group / 16;
index 9db8cff..effc38a 100644 (file)
@@ -2438,8 +2438,8 @@ static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
         */
        offset = ((ino - 1) % EXT4_INODES_PER_GROUP(sb)) *
                EXT4_INODE_SIZE(sb);
-       block = le32_to_cpu(gdp[desc].bg_inode_table) +
-               (offset >> EXT4_BLOCK_SIZE_BITS(sb));
+       block = ext4_inode_table(gdp + desc) +
+                       (offset >> EXT4_BLOCK_SIZE_BITS(sb));
 
        iloc->block_group = block_group;
        iloc->offset = offset & (EXT4_BLOCK_SIZE(sb) - 1);
@@ -2506,7 +2506,7 @@ static int __ext4_get_inode_loc(struct inode *inode,
                                goto make_io;
 
                        bitmap_bh = sb_getblk(inode->i_sb,
-                                       le32_to_cpu(desc->bg_inode_bitmap));
+                               ext4_inode_bitmap(desc));
                        if (!bitmap_bh)
                                goto make_io;
 
index c60bfed..3dbf91b 100644 (file)
@@ -27,7 +27,7 @@ static int verify_group_input(struct super_block *sb,
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_super_block *es = sbi->s_es;
-       ext4_fsblk_t start = le32_to_cpu(es->s_blocks_count);
+       ext4_fsblk_t start = ext4_blocks_count(es);
        ext4_fsblk_t end = start + input->blocks_count;
        unsigned group = input->group;
        ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
@@ -68,43 +68,43 @@ static int verify_group_input(struct super_block *sb,
                             end - 1);
        else if (outside(input->block_bitmap, start, end))
                ext4_warning(sb, __FUNCTION__,
-                            "Block bitmap not in group (block %u)",
+                            "Block bitmap not in group (block %llu)",
                             input->block_bitmap);
        else if (outside(input->inode_bitmap, start, end))
                ext4_warning(sb, __FUNCTION__,
-                            "Inode bitmap not in group (block %u)",
+                            "Inode bitmap not in group (block %llu)",
                             input->inode_bitmap);
        else if (outside(input->inode_table, start, end) ||
                 outside(itend - 1, start, end))
                ext4_warning(sb, __FUNCTION__,
-                            "Inode table not in group (blocks %u-"E3FSBLK")",
+                            "Inode table not in group (blocks %llu-%llu)",
                             input->inode_table, itend - 1);
        else if (input->inode_bitmap == input->block_bitmap)
                ext4_warning(sb, __FUNCTION__,
-                            "Block bitmap same as inode bitmap (%u)",
+                            "Block bitmap same as inode bitmap (%llu)",
                             input->block_bitmap);
        else if (inside(input->block_bitmap, input->inode_table, itend))
                ext4_warning(sb, __FUNCTION__,
-                            "Block bitmap (%u) in inode table (%u-"E3FSBLK")",
+                            "Block bitmap (%llu) in inode table (%llu-%llu)",
                             input->block_bitmap, input->inode_table, itend-1);
        else if (inside(input->inode_bitmap, input->inode_table, itend))
                ext4_warning(sb, __FUNCTION__,
-                            "Inode bitmap (%u) in inode table (%u-"E3FSBLK")",
+                            "Inode bitmap (%llu) in inode table (%llu-%llu)",
                             input->inode_bitmap, input->inode_table, itend-1);
        else if (inside(input->block_bitmap, start, metaend))
                ext4_warning(sb, __FUNCTION__,
-                            "Block bitmap (%u) in GDT table"
+                            "Block bitmap (%llu) in GDT table"
                             " ("E3FSBLK"-"E3FSBLK")",
                             input->block_bitmap, start, metaend - 1);
        else if (inside(input->inode_bitmap, start, metaend))
                ext4_warning(sb, __FUNCTION__,
-                            "Inode bitmap (%u) in GDT table"
+                            "Inode bitmap (%llu) in GDT table"
                             " ("E3FSBLK"-"E3FSBLK")",
                             input->inode_bitmap, start, metaend - 1);
        else if (inside(input->inode_table, start, metaend) ||
                 inside(itend - 1, start, metaend))
                ext4_warning(sb, __FUNCTION__,
-                            "Inode table (%u-"E3FSBLK") overlaps"
+                            "Inode table ("E3FSBLK"-"E3FSBLK") overlaps"
                             "GDT table ("E3FSBLK"-"E3FSBLK")",
                             input->inode_table, itend - 1, start, metaend - 1);
        else
@@ -286,6 +286,7 @@ exit_journal:
        return err;
 }
 
+
 /*
  * Iterate through the groups which hold BACKUP superblock/GDT copies in an
  * ext4 filesystem.  The counters should be initialized to 1, 5, and 7 before
@@ -340,12 +341,15 @@ static int verify_reserved_gdb(struct super_block *sb,
        int gdbackups = 0;
 
        while ((grp = ext4_list_backups(sb, &three, &five, &seven)) < end) {
-               if (le32_to_cpu(*p++) != grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){
+               if (le32_to_cpu(*p++) !=
+                   grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){
                        ext4_warning(sb, __FUNCTION__,
                                     "reserved GDT "E3FSBLK
                                     " missing grp %d ("E3FSBLK")",
                                     blk, grp,
-                                    grp * EXT4_BLOCKS_PER_GROUP(sb) + blk);
+                                    grp *
+                                    (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) +
+                                    blk);
                        return -EINVAL;
                }
                if (++gdbackups > EXT4_ADDR_PER_BLOCK(sb))
@@ -731,8 +735,8 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
                return -EPERM;
        }
 
-       if (le32_to_cpu(es->s_blocks_count) + input->blocks_count <
-           le32_to_cpu(es->s_blocks_count)) {
+       if (ext4_blocks_count(es) + input->blocks_count <
+           ext4_blocks_count(es)) {
                ext4_warning(sb, __FUNCTION__, "blocks_count overflow\n");
                return -EINVAL;
        }
@@ -830,9 +834,9 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
        /* Update group descriptor block for new group */
        gdp = (struct ext4_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);
+       ext4_block_bitmap_set(gdp, input->block_bitmap); /* LV FIXME */
+       ext4_inode_bitmap_set(gdp, input->inode_bitmap); /* LV FIXME */
+       ext4_inode_table_set(gdp, 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(EXT4_INODES_PER_GROUP(sb));
 
@@ -846,7 +850,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
         * 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) +
+       ext4_blocks_count_set(es, ext4_blocks_count(es) +
                input->blocks_count);
        es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) +
                EXT4_INODES_PER_GROUP(sb));
@@ -882,7 +886,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
 
        /* 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) +
+       ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) +
                input->reserved_blocks);
 
        /* Update the free space counts */
@@ -933,7 +937,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
        /* 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 = ext4_blocks_count(es);
        o_groups_count = EXT4_SB(sb)->s_groups_count;
 
        if (test_opt(sb, DEBUG))
@@ -1004,7 +1008,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
        }
 
        lock_super(sb);
-       if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
+       if (o_blocks_count != ext4_blocks_count(es)) {
                ext4_warning(sb, __FUNCTION__,
                             "multiple resizers run on filesystem!");
                unlock_super(sb);
@@ -1020,7 +1024,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
                ext4_journal_stop(handle);
                goto exit_put;
        }
-       es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
+       ext4_blocks_count_set(es, o_blocks_count + add);
        ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
        sb->s_dirt = 1;
        unlock_super(sb);
@@ -1032,8 +1036,8 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
        if ((err = ext4_journal_stop(handle)))
                goto exit_put;
        if (test_opt(sb, DEBUG))
-               printk(KERN_DEBUG "EXT4-fs: extended group to %u blocks\n",
-                      le32_to_cpu(es->s_blocks_count));
+               printk(KERN_DEBUG "EXT4-fs: extended group to %llu blocks\n",
+                      ext4_blocks_count(es));
        update_backups(sb, EXT4_SB(sb)->s_sbh->b_blocknr, (char *)es,
                       sizeof(struct ext4_super_block));
 exit_put:
index 1d12e4f..b91dffd 100644 (file)
@@ -62,6 +62,43 @@ static void ext4_unlockfs(struct super_block *sb);
 static void ext4_write_super (struct super_block * sb);
 static void ext4_write_super_lockfs(struct super_block *sb);
 
+
+ext4_fsblk_t ext4_block_bitmap(struct ext4_group_desc *bg)
+{
+       return le32_to_cpu(bg->bg_block_bitmap) |
+               ((ext4_fsblk_t)le16_to_cpu(bg->bg_block_bitmap_hi) << 32);
+}
+
+ext4_fsblk_t ext4_inode_bitmap(struct ext4_group_desc *bg)
+{
+       return le32_to_cpu(bg->bg_inode_bitmap) |
+               ((ext4_fsblk_t)le16_to_cpu(bg->bg_inode_bitmap_hi) << 32);
+}
+
+ext4_fsblk_t ext4_inode_table(struct ext4_group_desc *bg)
+{
+       return le32_to_cpu(bg->bg_inode_table) |
+               ((ext4_fsblk_t)le16_to_cpu(bg->bg_inode_table_hi) << 32);
+}
+
+void ext4_block_bitmap_set(struct ext4_group_desc *bg, ext4_fsblk_t blk)
+{
+       bg->bg_block_bitmap = cpu_to_le32((u32)blk);
+       bg->bg_block_bitmap_hi = cpu_to_le16(blk >> 32);
+}
+
+void ext4_inode_bitmap_set(struct ext4_group_desc *bg, ext4_fsblk_t blk)
+{
+       bg->bg_inode_bitmap  = cpu_to_le32((u32)blk);
+       bg->bg_inode_bitmap_hi = cpu_to_le16(blk >> 32);
+}
+
+void ext4_inode_table_set(struct ext4_group_desc *bg, ext4_fsblk_t blk)
+{
+       bg->bg_inode_table = cpu_to_le32((u32)blk);
+       bg->bg_inode_table_hi = cpu_to_le16(blk >> 32);
+}
+
 /*
  * Wrappers for jbd2_journal_start/end.
  *
@@ -1182,6 +1219,9 @@ static int ext4_check_descriptors (struct super_block * sb)
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
        ext4_fsblk_t last_block;
+       ext4_fsblk_t block_bitmap;
+       ext4_fsblk_t inode_bitmap;
+       ext4_fsblk_t inode_table;
        struct ext4_group_desc * gdp = NULL;
        int desc_block = 0;
        int i;
@@ -1191,7 +1231,7 @@ static int ext4_check_descriptors (struct super_block * sb)
        for (i = 0; i < sbi->s_groups_count; i++)
        {
                if (i == sbi->s_groups_count - 1)
-                       last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
+                       last_block = ext4_blocks_count(sbi->s_es) - 1;
                else
                        last_block = first_block +
                                (EXT4_BLOCKS_PER_GROUP(sb) - 1);
@@ -1199,42 +1239,39 @@ static int ext4_check_descriptors (struct super_block * sb)
                if ((i % EXT4_DESC_PER_BLOCK(sb)) == 0)
                        gdp = (struct ext4_group_desc *)
                                        sbi->s_group_desc[desc_block++]->b_data;
-               if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
-                   le32_to_cpu(gdp->bg_block_bitmap) > last_block)
+               block_bitmap = ext4_block_bitmap(gdp);
+               if (block_bitmap < first_block || block_bitmap > last_block)
                {
                        ext4_error (sb, "ext4_check_descriptors",
                                    "Block bitmap for group %d"
-                                   " not in group (block %lu)!",
-                                   i, (unsigned long)
-                                       le32_to_cpu(gdp->bg_block_bitmap));
+                                   " not in group (block "E3FSBLK")!",
+                                   i, block_bitmap);
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
-                   le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
+               inode_bitmap = ext4_inode_bitmap(gdp);
+               if (inode_bitmap < first_block || inode_bitmap > last_block)
                {
                        ext4_error (sb, "ext4_check_descriptors",
                                    "Inode bitmap for group %d"
-                                   " not in group (block %lu)!",
-                                   i, (unsigned long)
-                                       le32_to_cpu(gdp->bg_inode_bitmap));
+                                   " not in group (block "E3FSBLK")!",
+                                   i, inode_bitmap);
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
-                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >
-                   last_block)
+               inode_table = ext4_inode_table(gdp);
+               if (inode_table < first_block ||
+                   inode_table + sbi->s_itb_per_group > last_block)
                {
                        ext4_error (sb, "ext4_check_descriptors",
                                    "Inode table for group %d"
-                                   " not in group (block %lu)!",
-                                   i, (unsigned long)
-                                       le32_to_cpu(gdp->bg_inode_table));
+                                   " not in group (block "E3FSBLK")!",
+                                   i, inode_table);
                        return 0;
                }
                first_block += EXT4_BLOCKS_PER_GROUP(sb);
                gdp++;
        }
 
-       sbi->s_es->s_free_blocks_count=cpu_to_le32(ext4_count_free_blocks(sb));
+       ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
        sbi->s_es->s_free_inodes_count=cpu_to_le32(ext4_count_free_inodes(sb));
        return 1;
 }
@@ -1411,6 +1448,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
        int i;
        int needs_recovery;
        __le32 features;
+       __u64 blocks_count;
 
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
@@ -1620,7 +1658,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                goto failed_mount;
        }
 
-       if (le32_to_cpu(es->s_blocks_count) >
+       if (ext4_blocks_count(es) >
                    (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
                printk(KERN_ERR "EXT4-fs: filesystem on %s:"
                        " too large to mount safely\n", sb->s_id);
@@ -1632,9 +1670,11 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
 
        if (EXT4_BLOCKS_PER_GROUP(sb) == 0)
                goto cantfind_ext4;
-       sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
-                              le32_to_cpu(es->s_first_data_block) - 1)
-                                      / EXT4_BLOCKS_PER_GROUP(sb)) + 1;
+       blocks_count = (ext4_blocks_count(es) -
+                       le32_to_cpu(es->s_first_data_block) +
+                       EXT4_BLOCKS_PER_GROUP(sb) - 1);
+       do_div(blocks_count, EXT4_BLOCKS_PER_GROUP(sb));
+       sbi->s_groups_count = blocks_count;
        db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
                   EXT4_DESC_PER_BLOCK(sb);
        sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
@@ -1949,7 +1989,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
                goto out_bdev;
        }
 
-       len = le32_to_cpu(es->s_blocks_count);
+       len = ext4_blocks_count(es);
        start = sb_block + 1;
        brelse(bh);     /* we're done with the superblock */
 
@@ -2119,7 +2159,7 @@ static void ext4_commit_super (struct super_block * sb,
        if (!sbh)
                return;
        es->s_wtime = cpu_to_le32(get_seconds());
-       es->s_free_blocks_count = cpu_to_le32(ext4_count_free_blocks(sb));
+       ext4_free_blocks_count_set(es, ext4_count_free_blocks(sb));
        es->s_free_inodes_count = cpu_to_le32(ext4_count_free_inodes(sb));
        BUFFER_TRACE(sbh, "marking dirty");
        mark_buffer_dirty(sbh);
@@ -2312,7 +2352,7 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
        ext4_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 > ext4_blocks_count(es)) {
                if (sbi->s_mount_opt & EXT4_MOUNT_ABORT) {
                        err = -EROFS;
                        goto restore_opts;
@@ -2431,10 +2471,10 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
 
        buf->f_type = EXT4_SUPER_MAGIC;
        buf->f_bsize = sb->s_blocksize;
-       buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+       buf->f_blocks = ext4_blocks_count(es) - overhead;
        buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
-       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 - ext4_r_blocks_count(es);
+       if (buf->f_bfree < ext4_r_blocks_count(es))
                buf->f_bavail = 0;
        buf->f_files = le32_to_cpu(es->s_inodes_count);
        buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
index 63ed89f..8e5009e 100644 (file)
@@ -128,10 +128,17 @@ struct ext4_group_desc
        __le16  bg_free_blocks_count;   /* Free blocks count */
        __le16  bg_free_inodes_count;   /* Free inodes count */
        __le16  bg_used_dirs_count;     /* Directories count */
-       __u16   bg_pad;
-       __le32  bg_reserved[3];
+       __u16   bg_flags;
+       __le16  bg_block_bitmap_hi;     /* Blocks bitmap block MSB */
+       __le16  bg_inode_bitmap_hi;     /* Inodes bitmap block MSB */
+       __le16  bg_inode_table_hi;      /* Inodes table block MSB */
+       __u16   bg_reserved[3];
 };
 
+#ifdef __KERNEL__
+#include <linux/ext4_fs_i.h>
+#include <linux/ext4_fs_sb.h>
+#endif
 /*
  * Macro-instructions used to manage group descriptors
  */
@@ -194,9 +201,9 @@ struct ext4_group_desc
 /* Used to pass group descriptor data when online resize is done */
 struct ext4_new_group_input {
        __u32 group;            /* Group number for this data */
-       __u32 block_bitmap;     /* Absolute block number of block bitmap */
-       __u32 inode_bitmap;     /* Absolute block number of inode bitmap */
-       __u32 inode_table;      /* Absolute block number of inode table start */
+       __u64 block_bitmap;     /* Absolute block number of block bitmap */
+       __u64 inode_bitmap;     /* Absolute block number of inode bitmap */
+       __u64 inode_table;      /* Absolute block number of inode table start */
        __u32 blocks_count;     /* Total number of blocks in this group */
        __u16 reserved_blocks;  /* Number of reserved blocks in this group */
        __u16 unused;
@@ -205,9 +212,9 @@ struct ext4_new_group_input {
 /* The struct ext4_new_group_input in kernel space, with free_blocks_count */
 struct ext4_new_group_data {
        __u32 group;
-       __u32 block_bitmap;
-       __u32 inode_bitmap;
-       __u32 inode_table;
+       __u64 block_bitmap;
+       __u64 inode_bitmap;
+       __u64 inode_table;
        __u32 blocks_count;
        __u16 reserved_blocks;
        __u16 unused;
@@ -494,14 +501,18 @@ struct ext4_super_block {
        __u8    s_def_hash_version;     /* Default hash version to use */
        __u8    s_reserved_char_pad;
        __u16   s_reserved_word_pad;
-       __le32  s_default_mount_opts;
+/*100*/        __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 */
+       __le32  s_mkfs_time;            /* When the filesystem was created */
+       __le32  s_jnl_blocks[17];       /* Backup of the journal inode */
+       /* 64bit support valid if EXT4_FEATURE_COMPAT_64BIT */
+/*150*/        __le32  s_blocks_count_hi;      /* Blocks count */
+       __le32  s_r_blocks_count_hi;    /* Reserved blocks count */
+       __le32  s_free_blocks_count_hi; /* Free blocks count */
+       __u32   s_reserved[169];        /* Padding to the end of the block */
 };
 
 #ifdef __KERNEL__
-#include <linux/ext4_fs_i.h>
-#include <linux/ext4_fs_sb.h>
 static inline struct ext4_sb_info * EXT4_SB(struct super_block *sb)
 {
        return sb->s_fs_info;
@@ -588,12 +599,14 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino)
 #define EXT4_FEATURE_INCOMPAT_JOURNAL_DEV      0x0008 /* Journal device */
 #define EXT4_FEATURE_INCOMPAT_META_BG          0x0010
 #define EXT4_FEATURE_INCOMPAT_EXTENTS          0x0040 /* extents support */
+#define EXT4_FEATURE_INCOMPAT_64BIT            0x0080
 
 #define EXT4_FEATURE_COMPAT_SUPP       EXT2_FEATURE_COMPAT_EXT_ATTR
 #define EXT4_FEATURE_INCOMPAT_SUPP     (EXT4_FEATURE_INCOMPAT_FILETYPE| \
                                         EXT4_FEATURE_INCOMPAT_RECOVER| \
                                         EXT4_FEATURE_INCOMPAT_META_BG| \
-                                        EXT4_FEATURE_INCOMPAT_EXTENTS)
+                                        EXT4_FEATURE_INCOMPAT_EXTENTS| \
+                                        EXT4_FEATURE_INCOMPAT_64BIT)
 #define EXT4_FEATURE_RO_COMPAT_SUPP    (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                                         EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
                                         EXT4_FEATURE_RO_COMPAT_BTREE_DIR)
@@ -888,6 +901,53 @@ extern void ext4_abort (struct super_block *, const char *, const char *, ...)
 extern void ext4_warning (struct super_block *, const char *, const char *, ...)
        __attribute__ ((format (printf, 3, 4)));
 extern void ext4_update_dynamic_rev (struct super_block *sb);
+extern ext4_fsblk_t ext4_block_bitmap(struct ext4_group_desc *bg);
+extern ext4_fsblk_t ext4_inode_bitmap(struct ext4_group_desc *bg);
+extern ext4_fsblk_t ext4_inode_table(struct ext4_group_desc *bg);
+extern void ext4_block_bitmap_set(struct ext4_group_desc *bg, ext4_fsblk_t blk);
+extern void ext4_inode_bitmap_set(struct ext4_group_desc *bg, ext4_fsblk_t blk);
+extern void ext4_inode_table_set(struct ext4_group_desc *bg, ext4_fsblk_t blk);
+
+static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
+{
+       return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
+               le32_to_cpu(es->s_blocks_count);
+}
+
+static inline ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
+{
+       return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
+               le32_to_cpu(es->s_r_blocks_count);
+}
+
+static inline ext4_fsblk_t ext4_free_blocks_count(struct ext4_super_block *es)
+{
+       return ((ext4_fsblk_t)le32_to_cpu(es->s_free_blocks_count_hi) << 32) |
+               le32_to_cpu(es->s_free_blocks_count);
+}
+
+static inline void ext4_blocks_count_set(struct ext4_super_block *es,
+                                        ext4_fsblk_t blk)
+{
+       es->s_blocks_count = cpu_to_le32((u32)blk);
+       es->s_blocks_count_hi = cpu_to_le32(blk >> 32);
+}
+
+static inline void ext4_free_blocks_count_set(struct ext4_super_block *es,
+                                             ext4_fsblk_t blk)
+{
+       es->s_free_blocks_count = cpu_to_le32((u32)blk);
+       es->s_free_blocks_count_hi = cpu_to_le32(blk >> 32);
+}
+
+static inline void ext4_r_blocks_count_set(struct ext4_super_block *es,
+                                          ext4_fsblk_t blk)
+{
+       es->s_r_blocks_count = cpu_to_le32((u32)blk);
+       es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32);
+}
+
+
 
 #define ext4_std_error(sb, errno)                              \
 do {                                                           \