diff mbox series

[f2fs-dev] f2fs: Prevent s_writer rw_sem count mismatch in f2fs_evict_inode

Message ID 20240322041639.23144-1-youngjin.gil@samsung.com (mailing list archive)
State Accepted
Commit 3127f1010c9b27d925e83081d413ea7fc361abb0
Headers show
Series [f2fs-dev] f2fs: Prevent s_writer rw_sem count mismatch in f2fs_evict_inode | expand

Commit Message

Yeongjin Gil March 22, 2024, 4:16 a.m. UTC
If f2fs_evict_inode is called between freeze_super and thaw_super, the
s_writer rwsem count may become negative, resulting in hang.

CPU1                       CPU2

f2fs_resize_fs()           f2fs_evict_inode()
  f2fs_freeze
    set SBI_IS_FREEZING
                             skip sb_start_intwrite
  f2fs_unfreeze
    clear SBI_IS_FREEZING
                             sb_end_intwrite

To solve this problem, the call to sb_end_write is determined by whether
sb_start_intwrite is called, rather than the current freezing status.

Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
Reviewed-by: Sunmin Jeong <s_min.jeong@samsung.com>
Signed-off-by: Yeongjin Gil <youngjin.gil@samsung.com>
---
 fs/f2fs/inode.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Comments

Chao Yu March 23, 2024, 2:11 a.m. UTC | #1
On 2024/3/22 12:16, Yeongjin Gil wrote:
> If f2fs_evict_inode is called between freeze_super and thaw_super, the
> s_writer rwsem count may become negative, resulting in hang.
> 
> CPU1 CPU2
> 
> f2fs_resize_fs()           f2fs_evict_inode()
>    f2fs_freeze
>      set SBI_IS_FREEZING
>                               skip sb_start_intwrite
>    f2fs_unfreeze
>      clear SBI_IS_FREEZING
>                               sb_end_intwrite
> 
> To solve this problem, the call to sb_end_write is determined by whether
> sb_start_intwrite is called, rather than the current freezing status.
> 
> Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
> Reviewed-by: Sunmin Jeong <s_min.jeong@samsung.com>
> Signed-off-by: Yeongjin Gil <youngjin.gil@samsung.com>

Reviewed-by: Chao Yu <chao@kernel.org>

Thanks,
patchwork-bot+f2fs@kernel.org April 14, 2024, 3:32 p.m. UTC | #2
Hello:

This patch was applied to jaegeuk/f2fs.git (dev)
by Jaegeuk Kim <jaegeuk@kernel.org>:

On Fri, 22 Mar 2024 13:16:39 +0900 you wrote:
> If f2fs_evict_inode is called between freeze_super and thaw_super, the
> s_writer rwsem count may become negative, resulting in hang.
> 
> CPU1                       CPU2
> 
> f2fs_resize_fs()           f2fs_evict_inode()
>   f2fs_freeze
>     set SBI_IS_FREEZING
>                              skip sb_start_intwrite
>   f2fs_unfreeze
>     clear SBI_IS_FREEZING
>                              sb_end_intwrite
> 
> [...]

Here is the summary with links:
  - [f2fs-dev] f2fs: Prevent s_writer rw_sem count mismatch in f2fs_evict_inode
    https://git.kernel.org/jaegeuk/f2fs/c/3127f1010c9b

You are awesome, thank you!
diff mbox series

Patch

diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index c26effdce9aa..12b1fef31f43 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -804,6 +804,7 @@  void f2fs_evict_inode(struct inode *inode)
 	struct f2fs_inode_info *fi = F2FS_I(inode);
 	nid_t xnid = fi->i_xattr_nid;
 	int err = 0;
+	bool freeze_protected = false;
 
 	f2fs_abort_atomic_write(inode, true);
 
@@ -843,8 +844,10 @@  void f2fs_evict_inode(struct inode *inode)
 	f2fs_remove_ino_entry(sbi, inode->i_ino, UPDATE_INO);
 	f2fs_remove_ino_entry(sbi, inode->i_ino, FLUSH_INO);
 
-	if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING))
+	if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING)) {
 		sb_start_intwrite(inode->i_sb);
+		freeze_protected = true;
+	}
 	set_inode_flag(inode, FI_NO_ALLOC);
 	i_size_write(inode, 0);
 retry:
@@ -887,7 +890,7 @@  void f2fs_evict_inode(struct inode *inode)
 		if (dquot_initialize_needed(inode))
 			set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR);
 	}
-	if (!is_sbi_flag_set(sbi, SBI_IS_FREEZING))
+	if (freeze_protected)
 		sb_end_intwrite(inode->i_sb);
 no_delete:
 	dquot_drop(inode);