ext4: correct cluster len and clusters changed accounting in ext4_mb_mark_bb
authorRitesh Harjani <riteshh@linux.ibm.com>
Wed, 16 Feb 2022 07:02:43 +0000 (12:32 +0530)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 26 Feb 2022 02:34:56 +0000 (21:34 -0500)
ext4_mb_mark_bb() currently wrongly calculates cluster len (clen) and
flex_group->free_clusters. This patch fixes that.

Identified based on code review of ext4_mb_mark_bb() function.

Signed-off-by: Ritesh Harjani <riteshh@linux.ibm.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/a0b035d536bafa88110b74456853774b64c8ac40.1644992609.git.riteshh@linux.ibm.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/mballoc.c

index 67ac95c..b8ffbc0 100644 (file)
@@ -3899,10 +3899,11 @@ void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        ext4_group_t group;
        ext4_grpblk_t blkoff;
-       int i, clen, err;
+       int i, err;
        int already;
+       unsigned int clen, clen_changed;
 
-       clen = EXT4_B2C(sbi, len);
+       clen = EXT4_NUM_B2C(sbi, len);
 
        ext4_get_group_no_and_offset(sb, block, &group, &blkoff);
        bitmap_bh = ext4_read_block_bitmap(sb, group);
@@ -3923,6 +3924,7 @@ void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
                if (!mb_test_bit(blkoff + i, bitmap_bh->b_data) == !state)
                        already++;
 
+       clen_changed = clen - already;
        if (state)
                ext4_set_bits(bitmap_bh->b_data, blkoff, clen);
        else
@@ -3935,9 +3937,9 @@ void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
                                                group, gdp));
        }
        if (state)
-               clen = ext4_free_group_clusters(sb, gdp) - clen + already;
+               clen = ext4_free_group_clusters(sb, gdp) - clen_changed;
        else
-               clen = ext4_free_group_clusters(sb, gdp) + clen - already;
+               clen = ext4_free_group_clusters(sb, gdp) + clen_changed;
 
        ext4_free_group_clusters_set(sb, gdp, clen);
        ext4_block_bitmap_csum_set(sb, group, gdp, bitmap_bh);
@@ -3947,10 +3949,13 @@ void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
 
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi, group);
+               struct flex_groups *fg = sbi_array_rcu_deref(sbi,
+                                          s_flex_groups, flex_group);
 
-               atomic64_sub(len,
-                            &sbi_array_rcu_deref(sbi, s_flex_groups,
-                                                 flex_group)->free_clusters);
+               if (state)
+                       atomic64_sub(clen_changed, &fg->free_clusters);
+               else
+                       atomic64_add(clen_changed, &fg->free_clusters);
        }
 
        err = ext4_handle_dirty_metadata(NULL, NULL, bitmap_bh);