Skip to content

Commit f9e2d95

Browse files
Kemeng Shitytso
authored andcommitted
ext4: factor out codes to update block bitmap and group descriptor on disk from ext4_mb_mark_bb
There are several reasons to add a general function ext4_mb_mark_context to update block bitmap and group descriptor on disk: 1. pair behavior of alloc/free bits. For example, ext4_mb_new_blocks_simple will update free_clusters in struct flex_groups in ext4_mb_mark_bb while ext4_free_blocks_simple forgets this. 2. remove repeat code to read from disk, update and write back to disk. 3. reduce future unit test mocks to catch real IO to update structure on disk. Signed-off-by: Kemeng Shi <[email protected]> Reviewed-by: "Ritesh Harjani (IBM)" <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent d2f7cf4 commit f9e2d95

File tree

1 file changed

+77
-70
lines changed

1 file changed

+77
-70
lines changed

fs/ext4/mballoc.c

Lines changed: 77 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3943,6 +3943,80 @@ void ext4_exit_mballoc(void)
39433943
ext4_groupinfo_destroy_slabs();
39443944
}
39453945

3946+
static int
3947+
ext4_mb_mark_context(struct super_block *sb, bool state, ext4_group_t group,
3948+
ext4_grpblk_t blkoff, ext4_grpblk_t len)
3949+
{
3950+
struct ext4_sb_info *sbi = EXT4_SB(sb);
3951+
struct buffer_head *bitmap_bh = NULL;
3952+
struct ext4_group_desc *gdp;
3953+
struct buffer_head *gdp_bh;
3954+
int err;
3955+
unsigned int i, already, changed;
3956+
3957+
bitmap_bh = ext4_read_block_bitmap(sb, group);
3958+
if (IS_ERR(bitmap_bh))
3959+
return PTR_ERR(bitmap_bh);
3960+
3961+
err = -EIO;
3962+
gdp = ext4_get_group_desc(sb, group, &gdp_bh);
3963+
if (!gdp)
3964+
goto out_err;
3965+
3966+
ext4_lock_group(sb, group);
3967+
if (ext4_has_group_desc_csum(sb) &&
3968+
(gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
3969+
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
3970+
ext4_free_group_clusters_set(sb, gdp,
3971+
ext4_free_clusters_after_init(sb, group, gdp));
3972+
}
3973+
3974+
already = 0;
3975+
for (i = 0; i < len; i++)
3976+
if (mb_test_bit(blkoff + i, bitmap_bh->b_data) ==
3977+
state)
3978+
already++;
3979+
changed = len - already;
3980+
3981+
if (state) {
3982+
mb_set_bits(bitmap_bh->b_data, blkoff, len);
3983+
ext4_free_group_clusters_set(sb, gdp,
3984+
ext4_free_group_clusters(sb, gdp) - changed);
3985+
} else {
3986+
mb_clear_bits(bitmap_bh->b_data, blkoff, len);
3987+
ext4_free_group_clusters_set(sb, gdp,
3988+
ext4_free_group_clusters(sb, gdp) + changed);
3989+
}
3990+
3991+
ext4_block_bitmap_csum_set(sb, gdp, bitmap_bh);
3992+
ext4_group_desc_csum_set(sb, group, gdp);
3993+
ext4_unlock_group(sb, group);
3994+
3995+
if (sbi->s_log_groups_per_flex) {
3996+
ext4_group_t flex_group = ext4_flex_group(sbi, group);
3997+
struct flex_groups *fg = sbi_array_rcu_deref(sbi,
3998+
s_flex_groups, flex_group);
3999+
4000+
if (state)
4001+
atomic64_sub(changed, &fg->free_clusters);
4002+
else
4003+
atomic64_add(changed, &fg->free_clusters);
4004+
}
4005+
4006+
err = ext4_handle_dirty_metadata(NULL, NULL, bitmap_bh);
4007+
if (err)
4008+
goto out_err;
4009+
err = ext4_handle_dirty_metadata(NULL, NULL, gdp_bh);
4010+
if (err)
4011+
goto out_err;
4012+
4013+
sync_dirty_buffer(bitmap_bh);
4014+
sync_dirty_buffer(gdp_bh);
4015+
4016+
out_err:
4017+
brelse(bitmap_bh);
4018+
return err;
4019+
}
39464020

39474021
/*
39484022
* Check quota and mark chosen space (ac->ac_b_ex) non-free in bitmaps
@@ -4069,15 +4143,11 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
40694143
void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
40704144
int len, bool state)
40714145
{
4072-
struct buffer_head *bitmap_bh = NULL;
4073-
struct ext4_group_desc *gdp;
4074-
struct buffer_head *gdp_bh;
40754146
struct ext4_sb_info *sbi = EXT4_SB(sb);
40764147
ext4_group_t group;
40774148
ext4_grpblk_t blkoff;
4078-
int i, err = 0;
4079-
int already;
4080-
unsigned int clen, clen_changed, thisgrp_len;
4149+
int err = 0;
4150+
unsigned int clen, thisgrp_len;
40814151

40824152
while (len > 0) {
40834153
ext4_get_group_no_and_offset(sb, block, &group, &blkoff);
@@ -4098,80 +4168,17 @@ void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
40984168
ext4_error(sb, "Marking blocks in system zone - "
40994169
"Block = %llu, len = %u",
41004170
block, thisgrp_len);
4101-
bitmap_bh = NULL;
41024171
break;
41034172
}
41044173

4105-
bitmap_bh = ext4_read_block_bitmap(sb, group);
4106-
if (IS_ERR(bitmap_bh)) {
4107-
err = PTR_ERR(bitmap_bh);
4108-
bitmap_bh = NULL;
4109-
break;
4110-
}
4111-
4112-
err = -EIO;
4113-
gdp = ext4_get_group_desc(sb, group, &gdp_bh);
4114-
if (!gdp)
4115-
break;
4116-
4117-
ext4_lock_group(sb, group);
4118-
already = 0;
4119-
for (i = 0; i < clen; i++)
4120-
if (!mb_test_bit(blkoff + i, bitmap_bh->b_data) ==
4121-
!state)
4122-
already++;
4123-
4124-
clen_changed = clen - already;
4125-
if (state)
4126-
mb_set_bits(bitmap_bh->b_data, blkoff, clen);
4127-
else
4128-
mb_clear_bits(bitmap_bh->b_data, blkoff, clen);
4129-
if (ext4_has_group_desc_csum(sb) &&
4130-
(gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) {
4131-
gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
4132-
ext4_free_group_clusters_set(sb, gdp,
4133-
ext4_free_clusters_after_init(sb, group, gdp));
4134-
}
4135-
if (state)
4136-
clen = ext4_free_group_clusters(sb, gdp) - clen_changed;
4137-
else
4138-
clen = ext4_free_group_clusters(sb, gdp) + clen_changed;
4139-
4140-
ext4_free_group_clusters_set(sb, gdp, clen);
4141-
ext4_block_bitmap_csum_set(sb, gdp, bitmap_bh);
4142-
ext4_group_desc_csum_set(sb, group, gdp);
4143-
4144-
ext4_unlock_group(sb, group);
4145-
4146-
if (sbi->s_log_groups_per_flex) {
4147-
ext4_group_t flex_group = ext4_flex_group(sbi, group);
4148-
struct flex_groups *fg = sbi_array_rcu_deref(sbi,
4149-
s_flex_groups, flex_group);
4150-
4151-
if (state)
4152-
atomic64_sub(clen_changed, &fg->free_clusters);
4153-
else
4154-
atomic64_add(clen_changed, &fg->free_clusters);
4155-
4156-
}
4157-
4158-
err = ext4_handle_dirty_metadata(NULL, NULL, bitmap_bh);
4159-
if (err)
4160-
break;
4161-
sync_dirty_buffer(bitmap_bh);
4162-
err = ext4_handle_dirty_metadata(NULL, NULL, gdp_bh);
4163-
sync_dirty_buffer(gdp_bh);
4174+
err = ext4_mb_mark_context(sb, state, group, blkoff, clen);
41644175
if (err)
41654176
break;
41664177

41674178
block += thisgrp_len;
41684179
len -= thisgrp_len;
4169-
brelse(bitmap_bh);
41704180
BUG_ON(len < 0);
41714181
}
4172-
4173-
if (err)
4174-
brelse(bitmap_bh);
41754182
}
41764183

41774184
/*

0 commit comments

Comments
 (0)