f2fs: fix to avoid potential race on sbi->unusable_block_count access/update
authorChao Yu <yuchao0@huawei.com>
Sun, 5 May 2019 03:40:46 +0000 (11:40 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Thu, 9 May 2019 04:23:13 +0000 (21:23 -0700)
Use sbi.stat_lock to protect sbi->unusable_block_count accesss/udpate, in
order to avoid potential race on it.

Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/checkpoint.c
fs/f2fs/segment.c
fs/f2fs/super.c

index 805a33088e82dd4161b65285674d7bbe43a4bb28..ed70b68b2b382c6886645dcb5ce301b573e7f5f0 100644 (file)
@@ -1536,7 +1536,11 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        clear_sbi_flag(sbi, SBI_IS_DIRTY);
        clear_sbi_flag(sbi, SBI_NEED_CP);
        clear_sbi_flag(sbi, SBI_QUOTA_SKIP_FLUSH);
+
+       spin_lock(&sbi->stat_lock);
        sbi->unusable_block_count = 0;
+       spin_unlock(&sbi->stat_lock);
+
        __set_cp_next_pack(sbi);
 
        /*
index 8388d2abacb5d5616cbd7b2f53e75188fa2a46a6..8dee063c833fa8fb2c6fedc91859c7600226fe8c 100644 (file)
@@ -2169,8 +2169,11 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
                         * before, we must track that to know how much space we
                         * really have.
                         */
-                       if (f2fs_test_bit(offset, se->ckpt_valid_map))
+                       if (f2fs_test_bit(offset, se->ckpt_valid_map)) {
+                               spin_lock(&sbi->stat_lock);
                                sbi->unusable_block_count++;
+                               spin_unlock(&sbi->stat_lock);
+                       }
                }
 
                if (f2fs_test_and_clear_bit(offset, se->discard_map))
index fe075aa12893b7a37b3118d0d5f5354a36c5d4ea..7ddf0d3cbecea2b4036541a7c1dc9699e9e872df 100644 (file)
@@ -1226,10 +1226,13 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_blocks = total_count - start_count;
        buf->f_bfree = user_block_count - valid_user_blocks(sbi) -
                                                sbi->current_reserved_blocks;
+
+       spin_lock(&sbi->stat_lock);
        if (unlikely(buf->f_bfree <= sbi->unusable_block_count))
                buf->f_bfree = 0;
        else
                buf->f_bfree -= sbi->unusable_block_count;
+       spin_unlock(&sbi->stat_lock);
 
        if (buf->f_bfree > F2FS_OPTION(sbi).root_reserved_blocks)
                buf->f_bavail = buf->f_bfree -
@@ -1508,7 +1511,10 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
        if (err)
                goto out_unlock;
 
+       spin_lock(&sbi->stat_lock);
        sbi->unusable_block_count = 0;
+       spin_unlock(&sbi->stat_lock);
+
 out_unlock:
        mutex_unlock(&sbi->gc_mutex);
 restore_flag: