summaryrefslogtreecommitdiff
path: root/fs/f2fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/f2fs/namei.c')
-rw-r--r--fs/f2fs/namei.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index af40282a6948..043d20516a21 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -552,30 +552,31 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
if (unlikely(f2fs_cp_error(sbi))) {
err = -EIO;
- goto fail;
+ goto out;
}
err = f2fs_dquot_initialize(dir);
if (err)
- goto fail;
+ goto out;
err = f2fs_dquot_initialize(inode);
if (err)
- goto fail;
+ goto out;
de = f2fs_find_entry(dir, &dentry->d_name, &folio);
if (!de) {
if (IS_ERR(folio))
err = PTR_ERR(folio);
- goto fail;
+ goto out;
}
if (unlikely(inode->i_nlink == 0)) {
- f2fs_warn(F2FS_I_SB(inode), "%s: inode (ino=%lx) has zero i_nlink",
+ f2fs_warn(sbi, "%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 (S_ISDIR(inode->i_mode) && unlikely(inode->i_nlink == 1)) {
+ f2fs_warn(sbi, "%s: directory inode (ino=%lx) has a single i_nlink",
+ __func__, inode->i_ino);
+ goto corrupted;
}
f2fs_balance_fs(sbi, true);
@@ -585,7 +586,7 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
if (err) {
f2fs_unlock_op(sbi);
f2fs_folio_put(folio, false);
- goto fail;
+ goto out;
}
f2fs_delete_entry(de, folio, dir, inode);
f2fs_unlock_op(sbi);
@@ -601,7 +602,13 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
if (IS_DIRSYNC(dir))
f2fs_sync_fs(sbi->sb, 1);
-fail:
+
+ goto out;
+corrupted:
+ err = -EFSCORRUPTED;
+ set_sbi_flag(sbi, SBI_NEED_FSCK);
+ f2fs_folio_put(folio, false);
+out:
trace_f2fs_unlink_exit(inode, err);
return err;
}
@@ -1053,9 +1060,11 @@ static int f2fs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
if (whiteout) {
set_inode_flag(whiteout, FI_INC_LINK);
err = f2fs_add_link(old_dentry, whiteout);
- if (err)
+ if (err) {
+ d_invalidate(old_dentry);
+ d_invalidate(new_dentry);
goto put_out_dir;
-
+ }
spin_lock(&whiteout->i_lock);
inode_state_clear(whiteout, I_LINKABLE);
spin_unlock(&whiteout->i_lock);
@@ -1247,11 +1256,11 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
return 0;
out_new_dir:
if (new_dir_entry) {
- f2fs_folio_put(new_dir_folio, 0);
+ f2fs_folio_put(new_dir_folio, false);
}
out_old_dir:
if (old_dir_entry) {
- f2fs_folio_put(old_dir_folio, 0);
+ f2fs_folio_put(old_dir_folio, false);
}
out_new:
f2fs_folio_put(new_folio, false);