BACKPORT: f2fs: fix race condition on setting FI_NO_EXTENT flag

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.

Bug: 264453689
Fixes: 5f281fab9b ("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>
(cherry picked from commit a597af3b5a967e810cc8155abaa49abf10d6c417)
Change-Id: If36c3556c9062d46509f704f0491a7e6ad652ae6
This commit is contained in:
Zhang Qilong
2022-09-05 12:59:17 +08:00
committed by Todd Kjos
parent 3112d6f502
commit f6b4d18df0

View File

@@ -803,9 +803,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;