diff options
author | Yeongjin Gil <youngjin.gil@samsung.com> | 2024-03-22 13:16:39 +0900 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2024-03-26 16:52:26 +0000 |
commit | 3127f1010c9b27d925e83081d413ea7fc361abb0 (patch) | |
tree | 98fff95dfbadc3412f971cab9ad0efa6af63a6fa /fs/f2fs | |
parent | ee745e4736fbf33079d0d0808e1343c2280fd59a (diff) |
f2fs: Prevent s_writer rw_sem count mismatch in f2fs_evict_inode
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>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/inode.c | 7 |
1 files changed, 5 insertions, 2 deletions
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 @@ retry: 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); |