diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index b882771e4699..68b33e8089b0 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -502,12 +502,14 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, goto out; } - if (inode->i_nlink == 0) { + if (unlikely(inode->i_nlink == 0)) { f2fs_warn(F2FS_I_SB(inode), "%s: inode (ino=%lx) has zero i_nlink", __func__, inode->i_ino); - err = -EFSCORRUPTED; - set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); - goto out_iput; + goto corrupted; + } else if (unlikely(S_ISDIR(inode->i_mode) && inode->i_nlink == 1)) { + f2fs_warn(F2FS_I_SB(inode), "%s: directory inode (ino=%lx) has a single i_nlink", + __func__, inode->i_ino); + goto corrupted; } if (IS_ENCRYPTED(dir) && @@ -533,6 +535,9 @@ static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, trace_f2fs_lookup_end(dir, !IS_ERR_OR_NULL(new) ? new : dentry, ino, IS_ERR(new) ? PTR_ERR(new) : err); return new; +corrupted: + err = -EFSCORRUPTED; + set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); out_iput: iput(inode); out: @@ -572,10 +577,11 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) if (unlikely(inode->i_nlink == 0)) { f2fs_warn(F2FS_I_SB(inode), "%s: inode (ino=%lx) has zero i_nlink", __func__, inode->i_ino); - err = -EFSCORRUPTED; - set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); - f2fs_folio_put(folio, false); - goto fail; + goto corrupted; + } else if (unlikely(S_ISDIR(inode->i_mode) && inode->i_nlink == 1)) { + f2fs_warn(F2FS_I_SB(inode), "%s: directory inode (ino=%lx) has a single i_nlink", + __func__, inode->i_ino); + goto corrupted; } f2fs_balance_fs(sbi, true); @@ -601,6 +607,12 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry) if (IS_DIRSYNC(dir)) f2fs_sync_fs(sbi->sb, 1); + + goto fail; +corrupted: + err = -EFSCORRUPTED; + set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK); + f2fs_folio_put(folio, false); fail: trace_f2fs_unlink_exit(inode, err); return err;