]> git.baikalelectronics.ru Git - kernel.git/commitdiff
f2fs: fix race condition on setting FI_NO_EXTENT flag
authorZhang Qilong <zhangqilong3@huawei.com>
Mon, 5 Sep 2022 04:59:17 +0000 (12:59 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Oct 2022 11:22:46 +0000 (13:22 +0200)
[ Upstream commit 19c47cf7b93156b6a6399ff0b31810c1f5b2a4b4 ]

The following scenarios exist.
process A:               process B:
->f2fs_drop_extent_tree  ->f2fs_update_extent_cache_range
                          ->f2fs_update_extent_tree_range
                           ->write_lock
 ->set_inode_flag
                           ->is_inode_flag_set
                           ->__free_extent_tree // Shouldn't
                                                // have been
                                                // cleaned up
                                                // here
  ->write_lock

In this case, the "FI_NO_EXTENT" flag is set between
f2fs_update_extent_tree_range and is_inode_flag_set
by other process. it leads to clearing the whole exten
tree which should not have happened. And we fix it by
move the setting it to the range of write_lock.

Fixes:4bb03bae32c93 ("f2fs: disable extent_cache for fcollapse/finsert inodes")
Signed-off-by: Zhang Qilong <zhangqilong3@huawei.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/f2fs/extent_cache.c

index e60078460ad17975a2bdb39c46614e263ebdb067..05b17a741ccc05a773b6ca231231c65709fab8fd 100644 (file)
@@ -729,9 +729,8 @@ void f2fs_drop_extent_tree(struct inode *inode)
        if (!f2fs_may_extent_tree(inode))
                return;
 
-       set_inode_flag(inode, FI_NO_EXTENT);
-
        write_lock(&et->lock);
+       set_inode_flag(inode, FI_NO_EXTENT);
        __free_extent_tree(sbi, et);
        if (et->largest.len) {
                et->largest.len = 0;