Merge tag 'pull-finish_no_open' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull finish_no_open updates from Al Viro:
 "finish_no_open calling conventions change to simplify callers"

* tag 'pull-finish_no_open' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  slightly simplify nfs_atomic_open()
  simplify gfs2_atomic_open()
  simplify fuse_atomic_open()
  simplify nfs_atomic_open_v23()
  simplify vboxsf_dir_atomic_open()
  simplify cifs_atomic_open()
  9p: simplify v9fs_vfs_atomic_open_dotl()
  9p: simplify v9fs_vfs_atomic_open()
  allow finish_no_open(file, ERR_PTR(-E...))
This commit is contained in:
Linus Torvalds
2025-10-03 10:59:31 -07:00
8 changed files with 54 additions and 103 deletions

View File

@@ -768,22 +768,18 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
struct v9fs_inode __maybe_unused *v9inode; struct v9fs_inode __maybe_unused *v9inode;
struct v9fs_session_info *v9ses; struct v9fs_session_info *v9ses;
struct p9_fid *fid; struct p9_fid *fid;
struct dentry *res = NULL;
struct inode *inode; struct inode *inode;
int p9_omode; int p9_omode;
if (d_in_lookup(dentry)) { if (d_in_lookup(dentry)) {
res = v9fs_vfs_lookup(dir, dentry, 0); struct dentry *res = v9fs_vfs_lookup(dir, dentry, 0);
if (IS_ERR(res)) if (res || d_really_is_positive(dentry))
return PTR_ERR(res); return finish_no_open(file, res);
if (res)
dentry = res;
} }
/* Only creates */ /* Only creates */
if (!(flags & O_CREAT) || d_really_is_positive(dentry)) if (!(flags & O_CREAT))
return finish_no_open(file, res); return finish_no_open(file, NULL);
v9ses = v9fs_inode2v9ses(dir); v9ses = v9fs_inode2v9ses(dir);
perm = unixmode2p9mode(v9ses, mode); perm = unixmode2p9mode(v9ses, mode);
@@ -795,17 +791,17 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
"write-only file with writeback enabled, creating w/ O_RDWR\n"); "write-only file with writeback enabled, creating w/ O_RDWR\n");
} }
fid = v9fs_create(v9ses, dir, dentry, NULL, perm, p9_omode); fid = v9fs_create(v9ses, dir, dentry, NULL, perm, p9_omode);
if (IS_ERR(fid)) { if (IS_ERR(fid))
err = PTR_ERR(fid); return PTR_ERR(fid);
goto error;
}
v9fs_invalidate_inode_attr(dir); v9fs_invalidate_inode_attr(dir);
inode = d_inode(dentry); inode = d_inode(dentry);
v9inode = V9FS_I(inode); v9inode = V9FS_I(inode);
err = finish_open(file, dentry, generic_file_open); err = finish_open(file, dentry, generic_file_open);
if (err) if (unlikely(err)) {
goto error; p9_fid_put(fid);
return err;
}
file->private_data = fid; file->private_data = fid;
#ifdef CONFIG_9P_FSCACHE #ifdef CONFIG_9P_FSCACHE
@@ -818,13 +814,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
v9fs_open_fid_add(inode, &fid); v9fs_open_fid_add(inode, &fid);
file->f_mode |= FMODE_CREATED; file->f_mode |= FMODE_CREATED;
out: return 0;
dput(res);
return err;
error:
p9_fid_put(fid);
goto out;
} }
/** /**

View File

@@ -238,20 +238,16 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
struct p9_fid *dfid = NULL, *ofid = NULL; struct p9_fid *dfid = NULL, *ofid = NULL;
struct v9fs_session_info *v9ses; struct v9fs_session_info *v9ses;
struct posix_acl *pacl = NULL, *dacl = NULL; struct posix_acl *pacl = NULL, *dacl = NULL;
struct dentry *res = NULL;
if (d_in_lookup(dentry)) { if (d_in_lookup(dentry)) {
res = v9fs_vfs_lookup(dir, dentry, 0); struct dentry *res = v9fs_vfs_lookup(dir, dentry, 0);
if (IS_ERR(res)) if (res || d_really_is_positive(dentry))
return PTR_ERR(res); return finish_no_open(file, res);
if (res)
dentry = res;
} }
/* Only creates */ /* Only creates */
if (!(flags & O_CREAT) || d_really_is_positive(dentry)) if (!(flags & O_CREAT))
return finish_no_open(file, res); return finish_no_open(file, NULL);
v9ses = v9fs_inode2v9ses(dir); v9ses = v9fs_inode2v9ses(dir);
@@ -337,7 +333,6 @@ out:
p9_fid_put(ofid); p9_fid_put(ofid);
p9_fid_put(fid); p9_fid_put(fid);
v9fs_put_acl(dacl, pacl); v9fs_put_acl(dacl, pacl);
dput(res);
return err; return err;
} }

View File

@@ -739,22 +739,18 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
int err; int err;
struct mnt_idmap *idmap = file_mnt_idmap(file); struct mnt_idmap *idmap = file_mnt_idmap(file);
struct fuse_conn *fc = get_fuse_conn(dir); struct fuse_conn *fc = get_fuse_conn(dir);
struct dentry *res = NULL;
if (fuse_is_bad(dir)) if (fuse_is_bad(dir))
return -EIO; return -EIO;
if (d_in_lookup(entry)) { if (d_in_lookup(entry)) {
res = fuse_lookup(dir, entry, 0); struct dentry *res = fuse_lookup(dir, entry, 0);
if (IS_ERR(res)) if (res || d_really_is_positive(entry))
return PTR_ERR(res); return finish_no_open(file, res);
if (res)
entry = res;
} }
if (!(flags & O_CREAT) || d_really_is_positive(entry)) if (!(flags & O_CREAT))
goto no_open; return finish_no_open(file, NULL);
/* Only creates */ /* Only creates */
file->f_mode |= FMODE_CREATED; file->f_mode |= FMODE_CREATED;
@@ -768,16 +764,13 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
goto mknod; goto mknod;
} else if (err == -EEXIST) } else if (err == -EEXIST)
fuse_invalidate_entry(entry); fuse_invalidate_entry(entry);
out_dput:
dput(res);
return err; return err;
mknod: mknod:
err = fuse_mknod(idmap, dir, entry, mode, 0); err = fuse_mknod(idmap, dir, entry, mode, 0);
if (err) if (err)
goto out_dput; return err;
no_open: return finish_no_open(file, NULL);
return finish_no_open(file, res);
} }
/* /*

View File

@@ -1368,27 +1368,19 @@ static int gfs2_atomic_open(struct inode *dir, struct dentry *dentry,
struct file *file, unsigned flags, struct file *file, unsigned flags,
umode_t mode) umode_t mode)
{ {
struct dentry *d;
bool excl = !!(flags & O_EXCL); bool excl = !!(flags & O_EXCL);
if (!d_in_lookup(dentry)) if (d_in_lookup(dentry)) {
goto skip_lookup; struct dentry *d = __gfs2_lookup(dir, dentry, file);
if (file->f_mode & FMODE_OPENED) {
d = __gfs2_lookup(dir, dentry, file);
if (IS_ERR(d)) if (IS_ERR(d))
return PTR_ERR(d); return PTR_ERR(d);
if (d != NULL)
dentry = d;
if (d_really_is_positive(dentry)) {
if (!(file->f_mode & FMODE_OPENED))
return finish_no_open(file, d);
dput(d); dput(d);
return excl && (flags & O_CREAT) ? -EEXIST : 0; return excl && (flags & O_CREAT) ? -EEXIST : 0;
} }
if (d || d_really_is_positive(dentry))
BUG_ON(d != NULL); return finish_no_open(file, d);
}
skip_lookup:
if (!(flags & O_CREAT)) if (!(flags & O_CREAT))
return -ENOENT; return -ENOENT;

View File

@@ -2198,8 +2198,6 @@ no_open:
else else
dput(dentry); dput(dentry);
} }
if (IS_ERR(res))
return PTR_ERR(res);
return finish_no_open(file, res); return finish_no_open(file, res);
} }
EXPORT_SYMBOL_GPL(nfs_atomic_open); EXPORT_SYMBOL_GPL(nfs_atomic_open);
@@ -2260,7 +2258,7 @@ int nfs_atomic_open_v23(struct inode *dir, struct dentry *dentry,
struct file *file, unsigned int open_flags, struct file *file, unsigned int open_flags,
umode_t mode) umode_t mode)
{ {
struct dentry *res = NULL;
/* Same as look+open from lookup_open(), but with different O_TRUNC /* Same as look+open from lookup_open(), but with different O_TRUNC
* handling. * handling.
*/ */
@@ -2275,21 +2273,15 @@ int nfs_atomic_open_v23(struct inode *dir, struct dentry *dentry,
if (error) if (error)
return error; return error;
return finish_open(file, dentry, NULL); return finish_open(file, dentry, NULL);
} else if (d_in_lookup(dentry)) { }
if (d_in_lookup(dentry)) {
/* The only flags nfs_lookup considers are /* The only flags nfs_lookup considers are
* LOOKUP_EXCL and LOOKUP_RENAME_TARGET, and * LOOKUP_EXCL and LOOKUP_RENAME_TARGET, and
* we want those to be zero so the lookup isn't skipped. * we want those to be zero so the lookup isn't skipped.
*/ */
struct dentry *res = nfs_lookup(dir, dentry, 0); res = nfs_lookup(dir, dentry, 0);
}
d_lookup_done(dentry);
if (unlikely(res)) {
if (IS_ERR(res))
return PTR_ERR(res);
return finish_no_open(file, res); return finish_no_open(file, res);
}
}
return finish_no_open(file, NULL);
} }
EXPORT_SYMBOL_GPL(nfs_atomic_open_v23); EXPORT_SYMBOL_GPL(nfs_atomic_open_v23);

View File

@@ -1059,18 +1059,20 @@ EXPORT_SYMBOL(finish_open);
* finish_no_open - finish ->atomic_open() without opening the file * finish_no_open - finish ->atomic_open() without opening the file
* *
* @file: file pointer * @file: file pointer
* @dentry: dentry or NULL (as returned from ->lookup()) * @dentry: dentry, ERR_PTR(-E...) or NULL (as returned from ->lookup())
* *
* This can be used to set the result of a successful lookup in ->atomic_open(). * This can be used to set the result of a lookup in ->atomic_open().
* *
* NB: unlike finish_open() this function does consume the dentry reference and * NB: unlike finish_open() this function does consume the dentry reference and
* the caller need not dput() it. * the caller need not dput() it.
* *
* Returns "0" which must be the return value of ->atomic_open() after having * Returns 0 or -E..., which must be the return value of ->atomic_open() after
* called this function. * having called this function.
*/ */
int finish_no_open(struct file *file, struct dentry *dentry) int finish_no_open(struct file *file, struct dentry *dentry)
{ {
if (IS_ERR(dentry))
return PTR_ERR(dentry);
file->f_path.dentry = dentry; file->f_path.dentry = dentry;
return 0; return 0;
} }

View File

@@ -484,8 +484,6 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
* in network traffic in the other paths. * in network traffic in the other paths.
*/ */
if (!(oflags & O_CREAT)) { if (!(oflags & O_CREAT)) {
struct dentry *res;
/* /*
* Check for hashed negative dentry. We have already revalidated * Check for hashed negative dentry. We have already revalidated
* the dentry and it is fine. No need to perform another lookup. * the dentry and it is fine. No need to perform another lookup.
@@ -493,11 +491,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
if (!d_in_lookup(direntry)) if (!d_in_lookup(direntry))
return -ENOENT; return -ENOENT;
res = cifs_lookup(inode, direntry, 0); return finish_no_open(file, cifs_lookup(inode, direntry, 0));
if (IS_ERR(res))
return PTR_ERR(res);
return finish_no_open(file, res);
} }
xid = get_xid(); xid = get_xid();

View File

@@ -315,46 +315,39 @@ static int vboxsf_dir_atomic_open(struct inode *parent, struct dentry *dentry,
{ {
struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
struct vboxsf_handle *sf_handle; struct vboxsf_handle *sf_handle;
struct dentry *res = NULL;
u64 handle; u64 handle;
int err; int err;
if (d_in_lookup(dentry)) { if (d_in_lookup(dentry)) {
res = vboxsf_dir_lookup(parent, dentry, 0); struct dentry *res = vboxsf_dir_lookup(parent, dentry, 0);
if (IS_ERR(res)) if (res || d_really_is_positive(dentry))
return PTR_ERR(res); return finish_no_open(file, res);
if (res)
dentry = res;
} }
/* Only creates */ /* Only creates */
if (!(flags & O_CREAT) || d_really_is_positive(dentry)) if (!(flags & O_CREAT))
return finish_no_open(file, res); return finish_no_open(file, NULL);
err = vboxsf_dir_create(parent, dentry, mode, false, flags & O_EXCL, &handle); err = vboxsf_dir_create(parent, dentry, mode, false, flags & O_EXCL, &handle);
if (err) if (err)
goto out; return err;
sf_handle = vboxsf_create_sf_handle(d_inode(dentry), handle, SHFL_CF_ACCESS_READWRITE); sf_handle = vboxsf_create_sf_handle(d_inode(dentry), handle, SHFL_CF_ACCESS_READWRITE);
if (IS_ERR(sf_handle)) { if (IS_ERR(sf_handle)) {
vboxsf_close(sbi->root, handle); vboxsf_close(sbi->root, handle);
err = PTR_ERR(sf_handle); return PTR_ERR(sf_handle);
goto out;
} }
err = finish_open(file, dentry, generic_file_open); err = finish_open(file, dentry, generic_file_open);
if (err) { if (err) {
/* This also closes the handle passed to vboxsf_create_sf_handle() */ /* This also closes the handle passed to vboxsf_create_sf_handle() */
vboxsf_release_sf_handle(d_inode(dentry), sf_handle); vboxsf_release_sf_handle(d_inode(dentry), sf_handle);
goto out; return err;
} }
file->private_data = sf_handle; file->private_data = sf_handle;
file->f_mode |= FMODE_CREATED; file->f_mode |= FMODE_CREATED;
out: return 0;
dput(res);
return err;
} }
static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry) static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry)