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 (*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 @@ error: | ||||||
| 	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 @@ err_clunk_old_fid: | ||||||
| 	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 @@ out: | ||||||
|  * 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 @@ out: | ||||||
| 	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 @@ out: | ||||||
| 	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 @@ out_put_request: | ||||||
| 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Al Viro
				Al Viro