diff options
author | Chao Yu <yuchao0@huawei.com> | 2021-01-12 09:55:09 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-03-07 12:18:59 +0100 |
commit | 7bfc5a344ad0afd4b0601a1ee0e7d037d6c92569 (patch) | |
tree | 94a65cec2f7c6ef35ab52e54f2ca447be007620e /fs/f2fs | |
parent | 7416ec5526b5af5e495f224299ba291ce09407f2 (diff) | |
download | linux-stable-7bfc5a344ad0afd4b0601a1ee0e7d037d6c92569.tar.gz linux-stable-7bfc5a344ad0afd4b0601a1ee0e7d037d6c92569.tar.bz2 linux-stable-7bfc5a344ad0afd4b0601a1ee0e7d037d6c92569.zip |
f2fs: fix to set/clear I_LINKABLE under i_lock
[ Upstream commit 46085f37fc9e12d5c3539fb768b5ad7951e72acf ]
fsstress + fault injection test case reports a warning message as
below:
WARNING: CPU: 13 PID: 6226 at fs/inode.c:361 inc_nlink+0x32/0x40
Call Trace:
f2fs_init_inode_metadata+0x25c/0x4a0 [f2fs]
f2fs_add_inline_entry+0x153/0x3b0 [f2fs]
f2fs_add_dentry+0x75/0x80 [f2fs]
f2fs_do_add_link+0x108/0x160 [f2fs]
f2fs_rename2+0x6ab/0x14f0 [f2fs]
vfs_rename+0x70c/0x940
do_renameat2+0x4d8/0x4f0
__x64_sys_renameat2+0x4b/0x60
do_syscall_64+0x33/0x80
entry_SYSCALL_64_after_hwframe+0x44/0xa9
Following race case can cause this:
Thread A Kworker
- f2fs_rename
- f2fs_create_whiteout
- __f2fs_tmpfile
- f2fs_i_links_write
- f2fs_mark_inode_dirty_sync
- mark_inode_dirty_sync
- writeback_single_inode
- __writeback_single_inode
- spin_lock(&inode->i_lock)
- inode->i_state |= I_LINKABLE
- inode->i_state &= ~dirty
- spin_unlock(&inode->i_lock)
- f2fs_add_link
- f2fs_do_add_link
- f2fs_add_dentry
- f2fs_add_inline_entry
- f2fs_init_inode_metadata
- f2fs_i_links_write
- inc_nlink
- WARN_ON(!(inode->i_state & I_LINKABLE))
Fix to add i_lock to avoid i_state update race condition.
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/namei.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 8617e742d087..e20a0f9e6845 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -772,7 +772,11 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry, if (whiteout) { f2fs_i_links_write(inode, false); + + spin_lock(&inode->i_lock); inode->i_state |= I_LINKABLE; + spin_unlock(&inode->i_lock); + *whiteout = inode; } else { d_tmpfile(dentry, inode); @@ -966,7 +970,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, err = f2fs_add_link(old_dentry, whiteout); if (err) goto put_out_dir; + + spin_lock(&whiteout->i_lock); whiteout->i_state &= ~I_LINKABLE; + spin_unlock(&whiteout->i_lock); + iput(whiteout); } |