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