diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index aec06fb4fd76..4047e446ca1d 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -55,7 +55,7 @@ bool f2fs_sanity_check_inline_data(struct inode *inode, struct folio *ifolio) return false; if (inode_has_blocks(inode, ifolio)) - return false; + return !f2fs_exist_data(inode); if (!support_inline_data(inode)) return true; @@ -221,7 +221,7 @@ int f2fs_convert_inline_inode(struct inode *inode) struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct dnode_of_data dn; struct f2fs_lock_context lc; - struct folio *ifolio, *folio; + struct folio *ifolio, *folio = NULL; int err = 0; if (f2fs_hw_is_readonly(sbi) || f2fs_readonly(sbi->sb)) @@ -234,10 +234,7 @@ int f2fs_convert_inline_inode(struct inode *inode) if (err) return err; - folio = f2fs_grab_cache_folio(inode->i_mapping, 0, false); - if (IS_ERR(folio)) - return PTR_ERR(folio); - +retry: f2fs_lock_op(sbi, &lc); ifolio = f2fs_get_inode_folio(sbi, inode->i_ino); @@ -248,6 +245,21 @@ int f2fs_convert_inline_inode(struct inode *inode) set_new_dnode(&dn, inode, ifolio, ifolio, 0); + /* + * Keep the folio #0 -> inode folio lock order while checking + * FI_DATA_EXIST under the inode folio lock. + */ + if (!folio && f2fs_has_inline_data(inode) && f2fs_exist_data(inode)) { + f2fs_put_dnode(&dn); + f2fs_unlock_op(sbi, &lc); + + folio = f2fs_grab_cache_folio(inode->i_mapping, 0, false); + if (IS_ERR(folio)) + return PTR_ERR(folio); + + goto retry; + } + if (f2fs_has_inline_data(inode)) err = f2fs_convert_inline_folio(&dn, folio);