Implement ext2fs_allocate_group_table2() which marks blocks also in fs->block_map unconditionally and which always updates allocation statistics. Signed-off-by: Jan Kara <jack@xxxxxxxx> --- lib/ext2fs/alloc_tables.c | 97 ++++++++++++++++++++++++++++++++++------------- lib/ext2fs/ext2fs.h | 7 ++++ 2 files changed, 78 insertions(+), 26 deletions(-) diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c index 3e1952fa63e8..7b1f9da22fb8 100644 --- a/lib/ext2fs/alloc_tables.c +++ b/lib/ext2fs/alloc_tables.c @@ -81,19 +81,62 @@ static blk64_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk64_t start_blk, return first_free; } -errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, - ext2fs_block_bitmap bmap) +static void update_block_bitmap_stats(ext2_filsys fs, blk64_t blk, int len, + unsigned long flags, int flex_bg) +{ + if (flags & EXT2FS_ALLOC_TABLE_UPDATE_STATS) { + ext2fs_block_alloc_stats_range(fs, blk, len, +1); + if (!(flags & EXT2FS_ALLOC_TABLE_SET_BLOCK_BITMAP)) + ext2fs_unmark_block_bitmap_range2(fs->block_map, blk, + len); + } else if (flags & EXT2FS_ALLOC_TABLE_SET_BLOCK_BITMAP) { + dgrp_t g, end; + + ext2fs_mark_block_bitmap_range2(fs->block_map, blk, len); + /* For fs without FLEX_BG, bitmaps can stay uninitialized */ + if (!flex_bg) + return; + /* + * It's an overkill to assume more than two groups can be + * touched but the code is easy to understand this way. + */ + end = ext2fs_group_of_blk2(fs, blk + len - 1); + for (g = ext2fs_group_of_blk2(fs, blk); g <= end; g++) { + if (ext2fs_bg_flags_test(fs, g, EXT2_BG_BLOCK_UNINIT)) { + ext2fs_bg_flags_clear(fs, g, + EXT2_BG_BLOCK_UNINIT); + ext2fs_group_desc_csum_set(fs, g); + } + } + } +} + +/* + * Allocate group metadata (bitmaps, inode table) if not present. If + * reserve_bmap is set, we use that as a bitmap of blocks free for allocation + * (and update used blocks there as well as in fs->block_map). + */ +errcode_t ext2fs_allocate_group_table2(ext2_filsys fs, dgrp_t group, + ext2fs_block_bitmap reserve_bmap, + unsigned long flags) { errcode_t retval; blk64_t group_blk, start_blk, last_blk, new_blk; dgrp_t last_grp = 0; int rem_grps = 0, flexbg_size = 0, table_offset = 0; + ext2fs_block_bitmap bmap; group_blk = ext2fs_group_first_block2(fs, group); last_blk = ext2fs_group_last_block2(fs, group); - if (!bmap) + if (reserve_bmap == fs->block_map) + reserve_bmap = NULL; + + if (!reserve_bmap) { bmap = fs->block_map; + flags |= EXT2FS_ALLOC_TABLE_SET_BLOCK_BITMAP; + } else + bmap = reserve_bmap; if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT4_FEATURE_INCOMPAT_FLEX_BG) && @@ -153,15 +196,10 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, last_blk, 1, bmap, &new_blk); if (retval) return retval; - ext2fs_mark_block_bitmap2(bmap, new_blk); ext2fs_block_bitmap_loc_set(fs, group, new_blk); - if (flexbg_size) { - dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk); - ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1); - ext2fs_free_blocks_count_add(fs->super, -1); - ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT); - ext2fs_group_desc_csum_set(fs, gr); - } + update_block_bitmap_stats(fs, new_blk, 1, flags, flexbg_size); + if (reserve_bmap) + ext2fs_mark_block_bitmap2(bmap, new_blk); } if (flexbg_size) { @@ -186,15 +224,10 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, last_blk, 1, bmap, &new_blk); if (retval) return retval; - ext2fs_mark_block_bitmap2(bmap, new_blk); ext2fs_inode_bitmap_loc_set(fs, group, new_blk); - if (flexbg_size) { - dgrp_t gr = ext2fs_group_of_blk2(fs, new_blk); - ext2fs_bg_free_blocks_count_set(fs, gr, ext2fs_bg_free_blocks_count(fs, gr) - 1); - ext2fs_free_blocks_count_add(fs->super, -1); - ext2fs_bg_flags_clear(fs, gr, EXT2_BG_BLOCK_UNINIT); - ext2fs_group_desc_csum_set(fs, gr); - } + update_block_bitmap_stats(fs, new_blk, 1, flags, flexbg_size); + if (reserve_bmap) + ext2fs_mark_block_bitmap2(bmap, new_blk); } /* @@ -223,18 +256,30 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, bmap, &new_blk); if (retval) return retval; - if (flexbg_size) - ext2fs_block_alloc_stats_range(fs, new_blk, - fs->inode_blocks_per_group, +1); - else - ext2fs_mark_block_bitmap_range2(fs->block_map, - new_blk, fs->inode_blocks_per_group); ext2fs_inode_table_loc_set(fs, group, new_blk); + update_block_bitmap_stats(fs, new_blk, + fs->inode_blocks_per_group, flags, + flexbg_size); + if (reserve_bmap) + ext2fs_mark_block_bitmap_range2(bmap, + new_blk, fs->inode_blocks_per_group); } ext2fs_group_desc_csum_set(fs, group); return 0; } +errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, + ext2fs_block_bitmap bmap) +{ + unsigned long flags = 0; + + if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, + EXT4_FEATURE_INCOMPAT_FLEX_BG)) + flags |= EXT2FS_ALLOC_TABLE_UPDATE_STATS; + + return ext2fs_allocate_group_table2(fs, group, bmap, flags); +} + errcode_t ext2fs_allocate_tables(ext2_filsys fs) { errcode_t retval; @@ -248,7 +293,7 @@ errcode_t ext2fs_allocate_tables(ext2_filsys fs) for (i = 0; i < fs->group_desc_count; i++) { if (fs->progress_ops && fs->progress_ops->update) (fs->progress_ops->update)(fs, &progress, i); - retval = ext2fs_allocate_group_table(fs, i, fs->block_map); + retval = ext2fs_allocate_group_table(fs, i, 0); if (retval) return retval; } diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 13cbe567b19c..3eda8d1f4ad3 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -713,6 +713,13 @@ void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk, extern errcode_t ext2fs_allocate_tables(ext2_filsys fs); extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, ext2fs_block_bitmap bmap); +/* Update allocation statistics */ +#define EXT2FS_ALLOC_TABLE_UPDATE_STATS 0x0001 +/* Set fs->block_map in addition to provided bmap */ +#define EXT2FS_ALLOC_TABLE_SET_BLOCK_BITMAP 0x0002 +extern errcode_t ext2fs_allocate_group_table2(ext2_filsys fs, dgrp_t group, + ext2fs_block_bitmap bmap, + unsigned long flags); /* badblocks.c */ extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html