Skip to content

Commit

Permalink
[PATCH] ext4: 64bit metadata
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Laurent Vivier authored and Linus Torvalds committed Oct 11, 2006
1 parent a1ddeb7 commit bd81d8e
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 97 deletions.
50 changes: 25 additions & 25 deletions fs/ext4/balloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -460,12 +461,11 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
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",
Expand Down Expand Up @@ -552,8 +552,8 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb,
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 {
Expand Down Expand Up @@ -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))) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1561,12 +1561,12 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,

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",
Expand Down Expand Up @@ -1604,11 +1604,11 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
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;
}

Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions fs/ext4/ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down
52 changes: 28 additions & 24 deletions fs/ext4/resize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -286,6 +286,7 @@ static int setup_new_group_blocks(struct super_block *sb,
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
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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));

Expand All @@ -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));
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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:
Expand Down
Loading

0 comments on commit bd81d8e

Please sign in to comment.