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
|
@ -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 {
|
||||||
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.
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
*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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
*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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
/* 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)
|
||||||
* 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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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;
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
* 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,
|
||||||
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,
|
||||||
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,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
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;
|
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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
* 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);
|
||||||
|
|
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
|
#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)
|
||||||
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,
|
||||||
/* 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,
|
||||||
|
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue