Commit d9585277 authored by Al Viro's avatar Al Viro

make ->atomic_open() return int

Change of calling conventions:
old		new
NULL		1
file		0
ERR_PTR(-ve)	-ve

Caller *knows* that struct file *; no need to return it.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3d8a00d2
...@@ -62,7 +62,7 @@ ata *); ...@@ -62,7 +62,7 @@ ata *);
int (*removexattr) (struct dentry *, const char *); int (*removexattr) (struct dentry *, const char *);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
void (*update_time)(struct inode *, struct timespec *, int); void (*update_time)(struct inode *, struct timespec *, int);
struct file * (*atomic_open)(struct inode *, struct dentry *, int (*atomic_open)(struct inode *, struct dentry *,
struct opendata *, unsigned open_flag, struct opendata *, unsigned open_flag,
umode_t create_mode, int *opened); umode_t create_mode, int *opened);
......
...@@ -364,7 +364,7 @@ struct inode_operations { ...@@ -364,7 +364,7 @@ struct inode_operations {
ssize_t (*listxattr) (struct dentry *, char *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *); int (*removexattr) (struct dentry *, const char *);
void (*update_time)(struct inode *, struct timespec *, int); void (*update_time)(struct inode *, struct timespec *, int);
struct file * (*atomic_open)(struct inode *, struct dentry *, int (*atomic_open)(struct inode *, struct dentry *,
struct opendata *, unsigned open_flag, struct opendata *, unsigned open_flag,
umode_t create_mode, int *opened); umode_t create_mode, int *opened);
}; };
...@@ -482,8 +482,8 @@ otherwise noted. ...@@ -482,8 +482,8 @@ otherwise noted.
atomic_open: called on the last component of an open. Using this optional atomic_open: called on the last component of an open. Using this optional
method the filesystem can look up, possibly create and open the file in method the filesystem can look up, possibly create and open the file in
one atomic operation. If it cannot perform this (e.g. the file type one atomic operation. If it cannot perform this (e.g. the file type
turned out to be wrong) it may signal this by returning NULL instead of turned out to be wrong) it may signal this by returning 1 instead of
an open struct file pointer. This method is only called if the last usual 0 or -ve . This method is only called if the last
component is negative or needs lookup. Cached positive dentries are component is negative or needs lookup. Cached positive dentries are
still handled by f_op->open(). still handled by f_op->open().
......
...@@ -856,7 +856,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -856,7 +856,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
return ERR_PTR(result); return ERR_PTR(result);
} }
static struct file * static int
v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
struct opendata *od, unsigned flags, umode_t mode, struct opendata *od, unsigned flags, umode_t mode,
int *opened) int *opened)
...@@ -872,7 +872,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -872,7 +872,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
if (d_unhashed(dentry)) { if (d_unhashed(dentry)) {
res = v9fs_vfs_lookup(dir, dentry, NULL); res = v9fs_vfs_lookup(dir, dentry, NULL);
if (IS_ERR(res)) if (IS_ERR(res))
return ERR_CAST(res); return PTR_ERR(res);
if (res) if (res)
dentry = res; dentry = res;
...@@ -881,7 +881,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -881,7 +881,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
/* Only creates */ /* Only creates */
if (!(flags & O_CREAT) || dentry->d_inode) { if (!(flags & O_CREAT) || dentry->d_inode) {
finish_no_open(od, res); finish_no_open(od, res);
return NULL; return 1;
} }
err = 0; err = 0;
...@@ -933,13 +933,11 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -933,13 +933,11 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
*opened |= FILE_CREATED; *opened |= FILE_CREATED;
out: out:
dput(res); dput(res);
return filp; return err;
error: error:
if (fid) if (fid)
p9_client_clunk(fid); p9_client_clunk(fid);
filp = ERR_PTR(err);
goto out; goto out;
} }
......
...@@ -240,7 +240,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, ...@@ -240,7 +240,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0);
} }
static struct file * static int
v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
struct opendata *od, unsigned flags, umode_t omode, struct opendata *od, unsigned flags, umode_t omode,
int *opened) int *opened)
...@@ -262,7 +262,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -262,7 +262,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
if (d_unhashed(dentry)) { if (d_unhashed(dentry)) {
res = v9fs_vfs_lookup(dir, dentry, NULL); res = v9fs_vfs_lookup(dir, dentry, NULL);
if (IS_ERR(res)) if (IS_ERR(res))
return ERR_CAST(res); return PTR_ERR(res);
if (res) if (res)
dentry = res; dentry = res;
...@@ -271,7 +271,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -271,7 +271,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
/* Only creates */ /* Only creates */
if (!(flags & O_CREAT) || dentry->d_inode) { if (!(flags & O_CREAT) || dentry->d_inode) {
finish_no_open(od, res); finish_no_open(od, res);
return NULL; return 1;
} }
v9ses = v9fs_inode2v9ses(dir); v9ses = v9fs_inode2v9ses(dir);
...@@ -284,7 +284,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -284,7 +284,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
if (IS_ERR(dfid)) { if (IS_ERR(dfid)) {
err = PTR_ERR(dfid); err = PTR_ERR(dfid);
p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
goto err_return; goto out;
} }
/* clone a fid to use for creation */ /* clone a fid to use for creation */
...@@ -292,7 +292,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -292,7 +292,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
if (IS_ERR(ofid)) { if (IS_ERR(ofid)) {
err = PTR_ERR(ofid); err = PTR_ERR(ofid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
goto err_return; goto out;
} }
gid = v9fs_get_fsgid_for_create(dir); gid = v9fs_get_fsgid_for_create(dir);
...@@ -370,7 +370,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -370,7 +370,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
*opened |= FILE_CREATED; *opened |= FILE_CREATED;
out: out:
dput(res); dput(res);
return filp; return err;
error: error:
if (fid) if (fid)
...@@ -379,8 +379,6 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -379,8 +379,6 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
if (ofid) if (ofid)
p9_client_clunk(ofid); p9_client_clunk(ofid);
v9fs_set_create_acl(NULL, &dacl, &pacl); v9fs_set_create_acl(NULL, &dacl, &pacl);
err_return:
filp = ERR_PTR(err);
goto out; goto out;
} }
......
...@@ -634,21 +634,20 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, ...@@ -634,21 +634,20 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
return dentry; return dentry;
} }
struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry, int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
struct opendata *od, unsigned flags, umode_t mode, struct opendata *od, unsigned flags, umode_t mode,
int *opened) int *opened)
{ {
int err; int err;
struct dentry *res = NULL; struct dentry *res = NULL;
struct file *filp;
if (!(flags & O_CREAT)) { if (!(flags & O_CREAT)) {
if (dentry->d_name.len > NAME_MAX) if (dentry->d_name.len > NAME_MAX)
return ERR_PTR(-ENAMETOOLONG); return -ENAMETOOLONG;
err = ceph_init_dentry(dentry); err = ceph_init_dentry(dentry);
if (err < 0) if (err < 0)
return ERR_PTR(err); return err;
return ceph_lookup_open(dir, dentry, od, flags, mode, opened); return ceph_lookup_open(dir, dentry, od, flags, mode, opened);
} }
...@@ -656,7 +655,7 @@ struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -656,7 +655,7 @@ struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry,
if (d_unhashed(dentry)) { if (d_unhashed(dentry)) {
res = ceph_lookup(dir, dentry, NULL); res = ceph_lookup(dir, dentry, NULL);
if (IS_ERR(res)) if (IS_ERR(res))
return ERR_CAST(res); return PTR_ERR(res);
if (res) if (res)
dentry = res; dentry = res;
...@@ -665,14 +664,14 @@ struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -665,14 +664,14 @@ struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry,
/* We don't deal with positive dentries here */ /* We don't deal with positive dentries here */
if (dentry->d_inode) { if (dentry->d_inode) {
finish_no_open(od, res); finish_no_open(od, res);
return NULL; return 1;
} }
*opened |= FILE_CREATED; *opened |= FILE_CREATED;
filp = ceph_lookup_open(dir, dentry, od, flags, mode, opened); err = ceph_lookup_open(dir, dentry, od, flags, mode, opened);
dput(res); dput(res);
return filp; return err;
} }
/* /*
......
...@@ -213,9 +213,9 @@ int ceph_open(struct inode *inode, struct file *file) ...@@ -213,9 +213,9 @@ int ceph_open(struct inode *inode, struct file *file)
* may_open() fails, the struct *file gets cleaned up (i.e. * may_open() fails, the struct *file gets cleaned up (i.e.
* ceph_release gets called). So fear not! * ceph_release gets called). So fear not!
*/ */
struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry, int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
struct opendata *od, unsigned flags, umode_t mode, struct opendata *od, unsigned flags, umode_t mode,
int *opened) int *opened)
{ {
struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_mds_client *mdsc = fsc->mdsc;
...@@ -230,7 +230,7 @@ struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry, ...@@ -230,7 +230,7 @@ struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
/* do the open */ /* do the open */
req = prepare_open_request(dir->i_sb, flags, mode); req = prepare_open_request(dir->i_sb, flags, mode);
if (IS_ERR(req)) if (IS_ERR(req))
return ERR_CAST(req); return PTR_ERR(req);
req->r_dentry = dget(dentry); req->r_dentry = dget(dentry);
req->r_num_caps = 2; req->r_num_caps = 2;
if (flags & O_CREAT) { if (flags & O_CREAT) {
...@@ -257,10 +257,10 @@ struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry, ...@@ -257,10 +257,10 @@ struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
dout("ceph_lookup_open result=%p\n", ret); dout("ceph_lookup_open result=%p\n", ret);
if (IS_ERR(ret)) if (IS_ERR(ret))
return ERR_CAST(ret); return PTR_ERR(ret);
dput(ret); dput(ret);
return err ? ERR_PTR(err) : file; return err;
} }
int ceph_release(struct inode *inode, struct file *file) int ceph_release(struct inode *inode, struct file *file)
......
...@@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages, ...@@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages,
loff_t off, size_t len); loff_t off, size_t len);
extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
extern int ceph_open(struct inode *inode, struct file *file); extern int ceph_open(struct inode *inode, struct file *file);
extern struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry, extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
struct opendata *od, unsigned flags, struct opendata *od, unsigned flags,
umode_t mode, int *opened); umode_t mode, int *opened);
extern int ceph_release(struct inode *inode, struct file *filp); extern int ceph_release(struct inode *inode, struct file *filp);
/* dir.c */ /* dir.c */
......
...@@ -46,9 +46,9 @@ extern const struct inode_operations cifs_dir_inode_ops; ...@@ -46,9 +46,9 @@ extern const struct inode_operations cifs_dir_inode_ops;
extern struct inode *cifs_root_iget(struct super_block *); extern struct inode *cifs_root_iget(struct super_block *);
extern int cifs_create(struct inode *, struct dentry *, umode_t, extern int cifs_create(struct inode *, struct dentry *, umode_t,
struct nameidata *); struct nameidata *);
extern struct file *cifs_atomic_open(struct inode *, struct dentry *, extern int cifs_atomic_open(struct inode *, struct dentry *,
struct opendata *, unsigned, umode_t, struct opendata *, unsigned, umode_t,
int *); int *);
extern struct dentry *cifs_lookup(struct inode *, struct dentry *, extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
struct nameidata *); struct nameidata *);
extern int cifs_unlink(struct inode *dir, struct dentry *dentry); extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
......
...@@ -376,7 +376,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, ...@@ -376,7 +376,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry,
return rc; return rc;
} }
struct file * int
cifs_atomic_open(struct inode *inode, struct dentry *direntry, cifs_atomic_open(struct inode *inode, struct dentry *direntry,
struct opendata *od, unsigned oflags, umode_t mode, struct opendata *od, unsigned oflags, umode_t mode,
int *opened) int *opened)
...@@ -403,15 +403,15 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, ...@@ -403,15 +403,15 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
if (!(oflags & O_CREAT)) { if (!(oflags & O_CREAT)) {
struct dentry *res = cifs_lookup(inode, direntry, NULL); struct dentry *res = cifs_lookup(inode, direntry, NULL);
if (IS_ERR(res)) if (IS_ERR(res))
return ERR_CAST(res); return PTR_ERR(res);
finish_no_open(od, res); finish_no_open(od, res);
return NULL; return 1;
} }
rc = check_name(direntry); rc = check_name(direntry);
if (rc) if (rc)
return ERR_PTR(rc); return rc;
xid = GetXid(); xid = GetXid();
...@@ -428,13 +428,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, ...@@ -428,13 +428,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
&oplock, &fileHandle, opened); &oplock, &fileHandle, opened);
if (rc) { if (rc)
filp = ERR_PTR(rc);
goto out; goto out;
}
filp = finish_open(od, direntry, generic_file_open, opened); filp = finish_open(od, direntry, generic_file_open, opened);
if (IS_ERR(filp)) { if (IS_ERR(filp)) {
rc = PTR_ERR(filp);
CIFSSMBClose(xid, tcon, fileHandle); CIFSSMBClose(xid, tcon, fileHandle);
goto out; goto out;
} }
...@@ -443,14 +442,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, ...@@ -443,14 +442,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
if (pfile_info == NULL) { if (pfile_info == NULL) {
CIFSSMBClose(xid, tcon, fileHandle); CIFSSMBClose(xid, tcon, fileHandle);
fput(filp); fput(filp);
filp = ERR_PTR(-ENOMEM); rc = -ENOMEM;
} }
out: out:
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
free_xid: free_xid:
FreeXid(xid); FreeXid(xid);
return filp; return rc;
} }
int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
......
...@@ -369,9 +369,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, ...@@ -369,9 +369,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
* If the filesystem doesn't support this, then fall back to separate * If the filesystem doesn't support this, then fall back to separate
* 'mknod' + 'open' requests. * 'mknod' + 'open' requests.
*/ */
static struct file *fuse_create_open(struct inode *dir, struct dentry *entry, static int fuse_create_open(struct inode *dir, struct dentry *entry,
struct opendata *od, unsigned flags, struct opendata *od, unsigned flags,
umode_t mode, int *opened) umode_t mode, int *opened)
{ {
int err; int err;
struct inode *inode; struct inode *inode;
...@@ -452,12 +452,14 @@ static struct file *fuse_create_open(struct inode *dir, struct dentry *entry, ...@@ -452,12 +452,14 @@ static struct file *fuse_create_open(struct inode *dir, struct dentry *entry,
fuse_invalidate_attr(dir); fuse_invalidate_attr(dir);
file = finish_open(od, entry, generic_file_open, opened); file = finish_open(od, entry, generic_file_open, opened);
if (IS_ERR(file)) { if (IS_ERR(file)) {
err = PTR_ERR(file);
fuse_sync_release(ff, flags); fuse_sync_release(ff, flags);
} else { } else {
file->private_data = fuse_file_get(ff); file->private_data = fuse_file_get(ff);
fuse_finish_open(inode, file); fuse_finish_open(inode, file);
err = 0;
} }
return file; return err;
out_free_ff: out_free_ff:
fuse_file_free(ff); fuse_file_free(ff);
...@@ -466,23 +468,22 @@ static struct file *fuse_create_open(struct inode *dir, struct dentry *entry, ...@@ -466,23 +468,22 @@ static struct file *fuse_create_open(struct inode *dir, struct dentry *entry,
out_put_forget_req: out_put_forget_req:
kfree(forget); kfree(forget);
out_err: out_err:
return ERR_PTR(err); return err;
} }
static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
static struct file *fuse_atomic_open(struct inode *dir, struct dentry *entry, static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
struct opendata *od, unsigned flags, struct opendata *od, unsigned flags,
umode_t mode, int *opened) umode_t mode, int *opened)
{ {
int err; int err;
struct fuse_conn *fc = get_fuse_conn(dir); struct fuse_conn *fc = get_fuse_conn(dir);
struct file *file;
struct dentry *res = NULL; struct dentry *res = NULL;
if (d_unhashed(entry)) { if (d_unhashed(entry)) {
res = fuse_lookup(dir, entry, NULL); res = fuse_lookup(dir, entry, NULL);
if (IS_ERR(res)) if (IS_ERR(res))
return ERR_CAST(res); return PTR_ERR(res);
if (res) if (res)
entry = res; entry = res;
...@@ -497,24 +498,22 @@ static struct file *fuse_atomic_open(struct inode *dir, struct dentry *entry, ...@@ -497,24 +498,22 @@ static struct file *fuse_atomic_open(struct inode *dir, struct dentry *entry,
if (fc->no_create) if (fc->no_create)
goto mknod; goto mknod;
file = fuse_create_open(dir, entry, od, flags, mode, opened); err = fuse_create_open(dir, entry, od, flags, mode, opened);
if (PTR_ERR(file) == -ENOSYS) { if (err == -ENOSYS) {
fc->no_create = 1; fc->no_create = 1;
goto mknod; goto mknod;
} }
out_dput: out_dput:
dput(res); dput(res);
return file; return err;
mknod: mknod:
err = fuse_mknod(dir, entry, mode, 0); err = fuse_mknod(dir, entry, mode, 0);
if (err) { if (err)
file = ERR_PTR(err);
goto out_dput; goto out_dput;
}
no_open: no_open:
finish_no_open(od, res); finish_no_open(od, res);
return NULL; return 1;
} }
/* /*
......
...@@ -2204,7 +2204,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2204,7 +2204,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
umode_t mode; umode_t mode;
int error; int error;
int acc_mode; int acc_mode;
struct file *filp; struct file *filp = NULL;
int create_error = 0; int create_error = 0;
struct dentry *const DENTRY_NOT_SET = (void *) -1UL; struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
...@@ -2271,14 +2271,15 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2271,14 +2271,15 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
od->dentry = DENTRY_NOT_SET; od->dentry = DENTRY_NOT_SET;
od->mnt = nd->path.mnt; od->mnt = nd->path.mnt;
filp = dir->i_op->atomic_open(dir, dentry, od, open_flag, mode, error = dir->i_op->atomic_open(dir, dentry, od, open_flag, mode,
opened); opened);
if (IS_ERR(filp)) { if (error < 0) {
if (WARN_ON(od->dentry != DENTRY_NOT_SET)) if (WARN_ON(od->dentry != DENTRY_NOT_SET))
dput(od->dentry); dput(od->dentry);
if (create_error && PTR_ERR(filp) == -ENOENT) if (create_error && error == -ENOENT)
filp = ERR_PTR(create_error); error = create_error;
filp = ERR_PTR(error);
goto out; goto out;
} }
...@@ -2288,7 +2289,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2288,7 +2289,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
acc_mode = MAY_OPEN; acc_mode = MAY_OPEN;
} }
if (!filp) { if (error) { /* returned 1, that is */
if (WARN_ON(od->dentry == DENTRY_NOT_SET)) { if (WARN_ON(od->dentry == DENTRY_NOT_SET)) {
filp = ERR_PTR(-EIO); filp = ERR_PTR(-EIO);
goto out; goto out;
...@@ -2304,6 +2305,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, ...@@ -2304,6 +2305,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
* We didn't have the inode before the open, so check open permission * We didn't have the inode before the open, so check open permission
* here. * here.
*/ */
filp = od->filp;
error = may_open(&filp->f_path, acc_mode, open_flag); error = may_open(&filp->f_path, acc_mode, open_flag);
if (error) { if (error) {
fput(filp); fput(filp);
......
...@@ -111,9 +111,9 @@ const struct inode_operations nfs3_dir_inode_operations = { ...@@ -111,9 +111,9 @@ const struct inode_operations nfs3_dir_inode_operations = {
#ifdef CONFIG_NFS_V4 #ifdef CONFIG_NFS_V4
static struct file *nfs_atomic_open(struct inode *, struct dentry *, static int nfs_atomic_open(struct inode *, struct dentry *,
struct opendata *, unsigned, umode_t, struct opendata *, unsigned, umode_t,
int *); int *);
const struct inode_operations nfs4_dir_inode_operations = { const struct inode_operations nfs4_dir_inode_operations = {
.create = nfs_create, .create = nfs_create,
.lookup = nfs_lookup, .lookup = nfs_lookup,
...@@ -1387,10 +1387,10 @@ static int do_open(struct inode *inode, struct file *filp) ...@@ -1387,10 +1387,10 @@ static int do_open(struct inode *inode, struct file *filp)
return 0; return 0;
} }
static struct file *nfs_finish_open(struct nfs_open_context *ctx, static int nfs_finish_open(struct nfs_open_context *ctx,
struct dentry *dentry, struct dentry *dentry,
struct opendata *od, unsigned open_flags, struct opendata *od, unsigned open_flags,
int *opened) int *opened)
{ {
struct file *filp; struct file *filp;
int err; int err;
...@@ -1403,30 +1403,31 @@ static struct file *nfs_finish_open(struct nfs_open_context *ctx, ...@@ -1403,30 +1403,31 @@ static struct file *nfs_finish_open(struct nfs_open_context *ctx,
/* If the open_intent is for execute, we have an extra check to make */ /* If the open_intent is for execute, we have an extra check to make */
if (ctx->mode & FMODE_EXEC) { if (ctx->mode & FMODE_EXEC) {
err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags); err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags);
if (err < 0) { if (err < 0)
filp = ERR_PTR(err);
goto out; goto out;
}
} }
filp = finish_open(od, dentry, do_open, opened); filp = finish_open(od, dentry, do_open, opened);
if (!IS_ERR(filp)) if (IS_ERR(filp)) {
nfs_file_set_open_context(filp, ctx); err = PTR_ERR(filp);
goto out;
}
nfs_file_set_open_context(filp, ctx);
err = 0;
out: out:
put_nfs_open_context(ctx); put_nfs_open_context(ctx);
return filp; return err;
} }
static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, static int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
struct opendata *od, unsigned open_flags, struct opendata *od, unsigned open_flags,
umode_t mode, int *opened) umode_t mode, int *opened)
{ {
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
struct dentry *res; struct dentry *res;
struct iattr attr = { .ia_valid = ATTR_OPEN }; struct iattr attr = { .ia_valid = ATTR_OPEN };
struct inode *inode; struct inode *inode;
struct file *filp;
int err; int err;
/* Expect a negative dentry */ /* Expect a negative dentry */
...@@ -1437,21 +1438,19 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -1437,21 +1438,19 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry,
/* NFS only supports OPEN on regular files */ /* NFS only supports OPEN on regular files */
if ((open_flags & O_DIRECTORY)) { if ((open_flags & O_DIRECTORY)) {
err = -ENOENT;
if (!d_unhashed(dentry)) { if (!d_unhashed(dentry)) {
/* /*
* Hashed negative dentry with O_DIRECTORY: dentry was * Hashed negative dentry with O_DIRECTORY: dentry was
* revalidated and is fine, no need to perform lookup * revalidated and is fine, no need to perform lookup
* again * again
*/ */
goto out_err; return -ENOENT;
} }
goto no_open; goto no_open;
} }
err = -ENAMETOOLONG;
if (dentry->d_name.len > NFS_SERVER(dir)->namelen) if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
goto out_err; return -ENAMETOOLONG;
if (open_flags & O_CREAT) { if (open_flags & O_CREAT) {
attr.ia_valid |= ATTR_MODE; attr.ia_valid |= ATTR_MODE;
...@@ -1465,7 +1464,7 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -1465,7 +1464,7 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry,
ctx = create_nfs_open_context(dentry, open_flags); ctx = create_nfs_open_context(dentry, open_flags);
err = PTR_ERR(ctx); err = PTR_ERR(ctx);
if (IS_ERR(ctx)) if (IS_ERR(ctx))
goto out_err; goto out;
nfs_block_sillyrename(dentry->d_parent); nfs_block_sillyrename(dentry->d_parent);
inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
...@@ -1489,7 +1488,7 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -1489,7 +1488,7 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry,
default: default:
break; break;
} }
goto out_err; goto out;
} }
res = d_add_unique(dentry, inode); res = d_add_unique(dentry, inode);
if (res != NULL) if (res != NULL)
...@@ -1498,22 +1497,20 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -1498,22 +1497,20 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry,
nfs_unblock_sillyrename(dentry->d_parent); nfs_unblock_sillyrename(dentry->d_parent);
nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
filp = nfs_finish_open(ctx, dentry, od, open_flags, opened); err = nfs_finish_open(ctx, dentry, od, open_flags, opened);
dput(res); dput(res);
return filp; out:
return err;
out_err:
return ERR_PTR(err);
no_open: no_open:
res = nfs_lookup(dir, dentry, NULL); res = nfs_lookup(dir, dentry, NULL);
err = PTR_ERR(res); err = PTR_ERR(res);
if (IS_ERR(res)) if (IS_ERR(res))
goto out_err; goto out;
finish_no_open(od, res); finish_no_open(od, res);
return NULL; return 1;
} }
static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
......
...@@ -1694,9 +1694,9 @@ struct inode_operations { ...@@ -1694,9 +1694,9 @@ struct inode_operations {
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
u64 len); u64 len);
int (*update_time)(struct inode *, struct timespec *, int); int (*update_time)(struct inode *, struct timespec *, int);
struct file * (*atomic_open)(struct inode *, struct dentry *, int (*atomic_open)(struct inode *, struct dentry *,
struct opendata *, unsigned open_flag, struct opendata *, unsigned open_flag,
umode_t create_mode, int *opened); umode_t create_mode, int *opened);
} ____cacheline_aligned; } ____cacheline_aligned;
struct seq_file; struct seq_file;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment