No functional changes, just move the main logic to a helper function to make the whole thing easier to follow. Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Christian Brauner <christian.brauner@xxxxxxxxxx> Suggested-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> Link: https://lore.kernel.org/io-uring/CAHk-=wh=cpt_tQCirzFZRPawRpbuFTZ2MxNpXiyUF+eBXF=+sw@xxxxxxxxxxxxxx/ Signed-off-by: Dmitry Kadashev <dkadashev@xxxxxxxxx> --- fs/namei.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 6253486718d5..703cce40d597 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4091,7 +4091,9 @@ EXPORT_SYMBOL(vfs_unlink); * writeout happening, and we don't want to prevent access to the directory * while waiting on the I/O. */ -int do_unlinkat(int dfd, struct filename *name) + +static int try_unlinkat(int dfd, struct filename *name, + unsigned int lookup_flags) { int error; struct dentry *dentry; @@ -4100,19 +4102,18 @@ int do_unlinkat(int dfd, struct filename *name) int type; struct inode *inode = NULL; struct inode *delegated_inode = NULL; - unsigned int lookup_flags = 0; -retry: + error = __filename_parentat(dfd, name, lookup_flags, &path, &last, &type); if (error) - goto exit1; + return error; error = -EISDIR; if (type != LAST_NORM) - goto exit2; + goto exit1; error = mnt_want_write(path.mnt); if (error) - goto exit2; + goto exit1; retry_deleg: inode_lock_nested(path.dentry->d_inode, I_MUTEX_PARENT); dentry = __lookup_hash(&last, path.dentry, lookup_flags); @@ -4129,11 +4130,11 @@ int do_unlinkat(int dfd, struct filename *name) ihold(inode); error = security_path_unlink(&path, dentry); if (error) - goto exit3; + goto exit2; mnt_userns = mnt_user_ns(path.mnt); error = vfs_unlink(mnt_userns, path.dentry->d_inode, dentry, &delegated_inode); -exit3: +exit2: dput(dentry); } inode_unlock(path.dentry->d_inode); @@ -4146,17 +4147,9 @@ int do_unlinkat(int dfd, struct filename *name) goto retry_deleg; } mnt_drop_write(path.mnt); -exit2: - path_put(&path); exit1: - if (unlikely(retry_estale(error, lookup_flags))) { - lookup_flags |= LOOKUP_REVAL; - inode = NULL; - goto retry; - } - putname(name); + path_put(&path); return error; - slashes: if (d_is_negative(dentry)) error = -ENOENT; @@ -4164,7 +4157,20 @@ int do_unlinkat(int dfd, struct filename *name) error = -EISDIR; else error = -ENOTDIR; - goto exit3; + goto exit2; +} + +int do_unlinkat(int dfd, struct filename *name) +{ + int error; + + error = try_unlinkat(dfd, name, 0); + if (unlikely(retry_estale(error, 0))) + error = try_unlinkat(dfd, name, LOOKUP_REVAL); + + putname(name); + return error; + } SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag) -- 2.30.2