From: NeilBrown Date: Tue, 14 Jul 2026 23:04:13 +0000 (+1000) Subject: VFS: move delegated_inode retry loop into lookup_open() X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=a5438415be54e8e3bed20ac7f631a1bf6aeebb71;p=thirdparty%2Flinux.git VFS: move delegated_inode retry loop into lookup_open() By moving this retry into lookup_open() we no longer need to pass around the delegated_inode pointer. Various variable assignments need to be moved out of the declaration block so that they can be repeated after the "goto retry". Reviewed-by: Jan Kara Reviewed-by: Jori Koolstra Signed-off-by: NeilBrown Link: https://patch.msgid.link/20260714230534.776886-3-neilb@ownmail.net Signed-off-by: Christian Brauner (Amutable) --- diff --git a/fs/namei.c b/fs/namei.c index 711c7745e747..1ca738401afa 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -4402,17 +4402,23 @@ static struct dentry *atomic_open(const struct path *path, struct dentry *dentry * An error code is returned on failure. */ static struct dentry *lookup_open(struct nameidata *nd, struct file *file, - const struct open_flags *op, - struct delegated_inode *delegated_inode) + const struct open_flags *op) { + struct delegated_inode delegated_inode = { }; struct mnt_idmap *idmap; struct dentry *dir = nd->path.dentry; struct inode *dir_inode = dir->d_inode; - int open_flag = op->open_flag; + int open_flag; struct dentry *dentry; - int error, create_error = 0; - umode_t mode = op->mode; - bool got_write = false; + int error, create_error; + umode_t mode; + bool got_write; + +retry: + open_flag = op->open_flag; + got_write = false; + mode = op->mode; + create_error = 0; if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) { got_write = !mnt_want_write(nd->path.mnt); @@ -4510,7 +4516,7 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file, /* Negative dentry, just create the file */ if (!dentry->d_inode && (open_flag & O_CREAT)) { /* but break the directory lease first! */ - error = try_break_deleg(dir_inode, LEASE_BREAK_DIR_CREATE, delegated_inode); + error = try_break_deleg(dir_inode, LEASE_BREAK_DIR_CREATE, &delegated_inode); if (error) goto out_dput; @@ -4545,6 +4551,15 @@ out: if (got_write) mnt_drop_write(nd->path.mnt); + if (is_delegated(&delegated_inode)) { + /* Must have come through out_dput: dentry is an ERR_PTR() */ + error = break_deleg_wait(&delegated_inode); + + if (!error) + goto retry; + dentry = ERR_PTR(error); + } + return dentry; out_dput: @@ -4592,7 +4607,6 @@ static struct dentry *lookup_fast_for_open(struct nameidata *nd, int open_flag) static const char *open_last_lookups(struct nameidata *nd, struct file *file, const struct open_flags *op) { - struct delegated_inode delegated_inode = { }; int open_flag = op->open_flag; struct dentry *dentry; const char *res; @@ -4622,19 +4636,10 @@ static const char *open_last_lookups(struct nameidata *nd, return ERR_PTR(-ECHILD); } } -retry: - dentry = lookup_open(nd, file, op, &delegated_inode); - - if (IS_ERR(dentry)) { - if (is_delegated(&delegated_inode)) { - int error = break_deleg_wait(&delegated_inode); - if (!error) - goto retry; - return ERR_PTR(error); - } + dentry = lookup_open(nd, file, op); + if (IS_ERR(dentry)) return ERR_CAST(dentry); - } if (file->f_mode & (FMODE_OPENED | FMODE_CREATED)) { dput(nd->path.dentry);