diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-06-22 04:39:14 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-14 08:33:35 -0400 |
commit | d95852777bc8ba6b3ad3397d495c5f9dd8ca8383 (patch) | |
tree | 96e9d8b1d33c4f6f7b5ba5be0fa4fd8f77c7a67f | |
parent | 3d8a00d2099ebc6d5a6e95fadaf861709d9919a8 (diff) |
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>
-rw-r--r-- | Documentation/filesystems/Locking | 2 | ||||
-rw-r--r-- | Documentation/filesystems/vfs.txt | 6 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 10 | ||||
-rw-r--r-- | fs/9p/vfs_inode_dotl.c | 14 | ||||
-rw-r--r-- | fs/ceph/dir.c | 19 | ||||
-rw-r--r-- | fs/ceph/file.c | 12 | ||||
-rw-r--r-- | fs/ceph/super.h | 6 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 6 | ||||
-rw-r--r-- | fs/cifs/dir.c | 17 | ||||
-rw-r--r-- | fs/fuse/dir.c | 33 | ||||
-rw-r--r-- | fs/namei.c | 14 | ||||
-rw-r--r-- | fs/nfs/dir.c | 57 | ||||
-rw-r--r-- | include/linux/fs.h | 6 |
13 files changed, 97 insertions, 105 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index af4e45bd6cfa..46a24a6ed095 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -62,7 +62,7 @@ ata *); | |||
62 | int (*removexattr) (struct dentry *, const char *); | 62 | int (*removexattr) (struct dentry *, const char *); |
63 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); | 63 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); |
64 | void (*update_time)(struct inode *, struct timespec *, int); | 64 | void (*update_time)(struct inode *, struct timespec *, int); |
65 | struct file * (*atomic_open)(struct inode *, struct dentry *, | 65 | int (*atomic_open)(struct inode *, struct dentry *, |
66 | struct opendata *, unsigned open_flag, | 66 | struct opendata *, unsigned open_flag, |
67 | umode_t create_mode, int *opened); | 67 | umode_t create_mode, int *opened); |
68 | 68 | ||
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index d7121051afcd..d0d690bbc4c7 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -364,7 +364,7 @@ struct inode_operations { | |||
364 | ssize_t (*listxattr) (struct dentry *, char *, size_t); | 364 | ssize_t (*listxattr) (struct dentry *, char *, size_t); |
365 | int (*removexattr) (struct dentry *, const char *); | 365 | int (*removexattr) (struct dentry *, const char *); |
366 | void (*update_time)(struct inode *, struct timespec *, int); | 366 | void (*update_time)(struct inode *, struct timespec *, int); |
367 | struct file * (*atomic_open)(struct inode *, struct dentry *, | 367 | int (*atomic_open)(struct inode *, struct dentry *, |
368 | struct opendata *, unsigned open_flag, | 368 | struct opendata *, unsigned open_flag, |
369 | umode_t create_mode, int *opened); | 369 | umode_t create_mode, int *opened); |
370 | }; | 370 | }; |
@@ -482,8 +482,8 @@ otherwise noted. | |||
482 | atomic_open: called on the last component of an open. Using this optional | 482 | atomic_open: called on the last component of an open. Using this optional |
483 | method the filesystem can look up, possibly create and open the file in | 483 | method the filesystem can look up, possibly create and open the file in |
484 | one atomic operation. If it cannot perform this (e.g. the file type | 484 | one atomic operation. If it cannot perform this (e.g. the file type |
485 | turned out to be wrong) it may signal this by returning NULL instead of | 485 | turned out to be wrong) it may signal this by returning 1 instead of |
486 | an open struct file pointer. This method is only called if the last | 486 | usual 0 or -ve . This method is only called if the last |
487 | component is negative or needs lookup. Cached positive dentries are | 487 | component is negative or needs lookup. Cached positive dentries are |
488 | still handled by f_op->open(). | 488 | still handled by f_op->open(). |
489 | 489 | ||
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index de626b3b342f..62ce8daefa95 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -856,7 +856,7 @@ error: | |||
856 | return ERR_PTR(result); | 856 | return ERR_PTR(result); |
857 | } | 857 | } |
858 | 858 | ||
859 | static struct file * | 859 | static int |
860 | v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, | 860 | v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, |
861 | struct opendata *od, unsigned flags, umode_t mode, | 861 | struct opendata *od, unsigned flags, umode_t mode, |
862 | int *opened) | 862 | int *opened) |
@@ -872,7 +872,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
872 | if (d_unhashed(dentry)) { | 872 | if (d_unhashed(dentry)) { |
873 | res = v9fs_vfs_lookup(dir, dentry, NULL); | 873 | res = v9fs_vfs_lookup(dir, dentry, NULL); |
874 | if (IS_ERR(res)) | 874 | if (IS_ERR(res)) |
875 | return ERR_CAST(res); | 875 | return PTR_ERR(res); |
876 | 876 | ||
877 | if (res) | 877 | if (res) |
878 | dentry = res; | 878 | dentry = res; |
@@ -881,7 +881,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
881 | /* Only creates */ | 881 | /* Only creates */ |
882 | if (!(flags & O_CREAT) || dentry->d_inode) { | 882 | if (!(flags & O_CREAT) || dentry->d_inode) { |
883 | finish_no_open(od, res); | 883 | finish_no_open(od, res); |
884 | return NULL; | 884 | return 1; |
885 | } | 885 | } |
886 | 886 | ||
887 | err = 0; | 887 | err = 0; |
@@ -933,13 +933,11 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
933 | *opened |= FILE_CREATED; | 933 | *opened |= FILE_CREATED; |
934 | out: | 934 | out: |
935 | dput(res); | 935 | dput(res); |
936 | return filp; | 936 | return err; |
937 | 937 | ||
938 | error: | 938 | error: |
939 | if (fid) | 939 | if (fid) |
940 | p9_client_clunk(fid); | 940 | p9_client_clunk(fid); |
941 | |||
942 | filp = ERR_PTR(err); | ||
943 | goto out; | 941 | goto out; |
944 | } | 942 | } |
945 | 943 | ||
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 3db55471bc93..69f05109f75d 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
@@ -240,7 +240,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, | |||
240 | return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); | 240 | return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); |
241 | } | 241 | } |
242 | 242 | ||
243 | static struct file * | 243 | static int |
244 | v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | 244 | v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, |
245 | struct opendata *od, unsigned flags, umode_t omode, | 245 | struct opendata *od, unsigned flags, umode_t omode, |
246 | int *opened) | 246 | int *opened) |
@@ -262,7 +262,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | |||
262 | if (d_unhashed(dentry)) { | 262 | if (d_unhashed(dentry)) { |
263 | res = v9fs_vfs_lookup(dir, dentry, NULL); | 263 | res = v9fs_vfs_lookup(dir, dentry, NULL); |
264 | if (IS_ERR(res)) | 264 | if (IS_ERR(res)) |
265 | return ERR_CAST(res); | 265 | return PTR_ERR(res); |
266 | 266 | ||
267 | if (res) | 267 | if (res) |
268 | dentry = res; | 268 | dentry = res; |
@@ -271,7 +271,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | |||
271 | /* Only creates */ | 271 | /* Only creates */ |
272 | if (!(flags & O_CREAT) || dentry->d_inode) { | 272 | if (!(flags & O_CREAT) || dentry->d_inode) { |
273 | finish_no_open(od, res); | 273 | finish_no_open(od, res); |
274 | return NULL; | 274 | return 1; |
275 | } | 275 | } |
276 | 276 | ||
277 | v9ses = v9fs_inode2v9ses(dir); | 277 | v9ses = v9fs_inode2v9ses(dir); |
@@ -284,7 +284,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | |||
284 | if (IS_ERR(dfid)) { | 284 | if (IS_ERR(dfid)) { |
285 | err = PTR_ERR(dfid); | 285 | err = PTR_ERR(dfid); |
286 | p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); | 286 | p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); |
287 | goto err_return; | 287 | goto out; |
288 | } | 288 | } |
289 | 289 | ||
290 | /* clone a fid to use for creation */ | 290 | /* clone a fid to use for creation */ |
@@ -292,7 +292,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | |||
292 | if (IS_ERR(ofid)) { | 292 | if (IS_ERR(ofid)) { |
293 | err = PTR_ERR(ofid); | 293 | err = PTR_ERR(ofid); |
294 | p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | 294 | p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); |
295 | goto err_return; | 295 | goto out; |
296 | } | 296 | } |
297 | 297 | ||
298 | gid = v9fs_get_fsgid_for_create(dir); | 298 | gid = v9fs_get_fsgid_for_create(dir); |
@@ -370,7 +370,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | |||
370 | *opened |= FILE_CREATED; | 370 | *opened |= FILE_CREATED; |
371 | out: | 371 | out: |
372 | dput(res); | 372 | dput(res); |
373 | return filp; | 373 | return err; |
374 | 374 | ||
375 | error: | 375 | error: |
376 | if (fid) | 376 | if (fid) |
@@ -379,8 +379,6 @@ err_clunk_old_fid: | |||
379 | if (ofid) | 379 | if (ofid) |
380 | p9_client_clunk(ofid); | 380 | p9_client_clunk(ofid); |
381 | v9fs_set_create_acl(NULL, &dacl, &pacl); | 381 | v9fs_set_create_acl(NULL, &dacl, &pacl); |
382 | err_return: | ||
383 | filp = ERR_PTR(err); | ||
384 | goto out; | 382 | goto out; |
385 | } | 383 | } |
386 | 384 | ||
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 81e5e908df9d..d8bfabeeaa25 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -634,21 +634,20 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
634 | return dentry; | 634 | return dentry; |
635 | } | 635 | } |
636 | 636 | ||
637 | struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry, | 637 | int ceph_atomic_open(struct inode *dir, struct dentry *dentry, |
638 | struct opendata *od, unsigned flags, umode_t mode, | 638 | struct opendata *od, unsigned flags, umode_t mode, |
639 | int *opened) | 639 | int *opened) |
640 | { | 640 | { |
641 | int err; | 641 | int err; |
642 | struct dentry *res = NULL; | 642 | struct dentry *res = NULL; |
643 | struct file *filp; | ||
644 | 643 | ||
645 | if (!(flags & O_CREAT)) { | 644 | if (!(flags & O_CREAT)) { |
646 | if (dentry->d_name.len > NAME_MAX) | 645 | if (dentry->d_name.len > NAME_MAX) |
647 | return ERR_PTR(-ENAMETOOLONG); | 646 | return -ENAMETOOLONG; |
648 | 647 | ||
649 | err = ceph_init_dentry(dentry); | 648 | err = ceph_init_dentry(dentry); |
650 | if (err < 0) | 649 | if (err < 0) |
651 | return ERR_PTR(err); | 650 | return err; |
652 | 651 | ||
653 | return ceph_lookup_open(dir, dentry, od, flags, mode, opened); | 652 | return ceph_lookup_open(dir, dentry, od, flags, mode, opened); |
654 | } | 653 | } |
@@ -656,7 +655,7 @@ struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry, | |||
656 | if (d_unhashed(dentry)) { | 655 | if (d_unhashed(dentry)) { |
657 | res = ceph_lookup(dir, dentry, NULL); | 656 | res = ceph_lookup(dir, dentry, NULL); |
658 | if (IS_ERR(res)) | 657 | if (IS_ERR(res)) |
659 | return ERR_CAST(res); | 658 | return PTR_ERR(res); |
660 | 659 | ||
661 | if (res) | 660 | if (res) |
662 | dentry = res; | 661 | dentry = res; |
@@ -665,14 +664,14 @@ struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry, | |||
665 | /* We don't deal with positive dentries here */ | 664 | /* We don't deal with positive dentries here */ |
666 | if (dentry->d_inode) { | 665 | if (dentry->d_inode) { |
667 | finish_no_open(od, res); | 666 | finish_no_open(od, res); |
668 | return NULL; | 667 | return 1; |
669 | } | 668 | } |
670 | 669 | ||
671 | *opened |= FILE_CREATED; | 670 | *opened |= FILE_CREATED; |
672 | filp = ceph_lookup_open(dir, dentry, od, flags, mode, opened); | 671 | err = ceph_lookup_open(dir, dentry, od, flags, mode, opened); |
673 | dput(res); | 672 | dput(res); |
674 | 673 | ||
675 | return filp; | 674 | return err; |
676 | } | 675 | } |
677 | 676 | ||
678 | /* | 677 | /* |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 4c304a90d046..b8cc3ee5401e 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -213,9 +213,9 @@ out: | |||
213 | * may_open() fails, the struct *file gets cleaned up (i.e. | 213 | * may_open() fails, the struct *file gets cleaned up (i.e. |
214 | * ceph_release gets called). So fear not! | 214 | * ceph_release gets called). So fear not! |
215 | */ | 215 | */ |
216 | struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | 216 | int ceph_lookup_open(struct inode *dir, struct dentry *dentry, |
217 | struct opendata *od, unsigned flags, umode_t mode, | 217 | struct opendata *od, unsigned flags, umode_t mode, |
218 | int *opened) | 218 | int *opened) |
219 | { | 219 | { |
220 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); | 220 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
221 | struct ceph_mds_client *mdsc = fsc->mdsc; | 221 | struct ceph_mds_client *mdsc = fsc->mdsc; |
@@ -230,7 +230,7 @@ struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | |||
230 | /* do the open */ | 230 | /* do the open */ |
231 | req = prepare_open_request(dir->i_sb, flags, mode); | 231 | req = prepare_open_request(dir->i_sb, flags, mode); |
232 | if (IS_ERR(req)) | 232 | if (IS_ERR(req)) |
233 | return ERR_CAST(req); | 233 | return PTR_ERR(req); |
234 | req->r_dentry = dget(dentry); | 234 | req->r_dentry = dget(dentry); |
235 | req->r_num_caps = 2; | 235 | req->r_num_caps = 2; |
236 | if (flags & O_CREAT) { | 236 | if (flags & O_CREAT) { |
@@ -257,10 +257,10 @@ out: | |||
257 | dout("ceph_lookup_open result=%p\n", ret); | 257 | dout("ceph_lookup_open result=%p\n", ret); |
258 | 258 | ||
259 | if (IS_ERR(ret)) | 259 | if (IS_ERR(ret)) |
260 | return ERR_CAST(ret); | 260 | return PTR_ERR(ret); |
261 | 261 | ||
262 | dput(ret); | 262 | dput(ret); |
263 | return err ? ERR_PTR(err) : file; | 263 | return err; |
264 | } | 264 | } |
265 | 265 | ||
266 | int ceph_release(struct inode *inode, struct file *file) | 266 | int ceph_release(struct inode *inode, struct file *file) |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index f9a325108b49..f7e8e82ec47f 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages, | |||
806 | loff_t off, size_t len); | 806 | loff_t off, size_t len); |
807 | extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); | 807 | extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); |
808 | extern int ceph_open(struct inode *inode, struct file *file); | 808 | extern int ceph_open(struct inode *inode, struct file *file); |
809 | extern struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | 809 | extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry, |
810 | struct opendata *od, unsigned flags, | 810 | struct opendata *od, unsigned flags, |
811 | umode_t mode, int *opened); | 811 | umode_t mode, int *opened); |
812 | extern int ceph_release(struct inode *inode, struct file *filp); | 812 | extern int ceph_release(struct inode *inode, struct file *filp); |
813 | 813 | ||
814 | /* dir.c */ | 814 | /* dir.c */ |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 92a7c3d8a031..58d9aca46a40 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -46,9 +46,9 @@ extern const struct inode_operations cifs_dir_inode_ops; | |||
46 | extern struct inode *cifs_root_iget(struct super_block *); | 46 | extern struct inode *cifs_root_iget(struct super_block *); |
47 | extern int cifs_create(struct inode *, struct dentry *, umode_t, | 47 | extern int cifs_create(struct inode *, struct dentry *, umode_t, |
48 | struct nameidata *); | 48 | struct nameidata *); |
49 | extern struct file *cifs_atomic_open(struct inode *, struct dentry *, | 49 | extern int cifs_atomic_open(struct inode *, struct dentry *, |
50 | struct opendata *, unsigned, umode_t, | 50 | struct opendata *, unsigned, umode_t, |
51 | int *); | 51 | int *); |
52 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, | 52 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, |
53 | struct nameidata *); | 53 | struct nameidata *); |
54 | extern int cifs_unlink(struct inode *dir, struct dentry *dentry); | 54 | extern int cifs_unlink(struct inode *dir, struct dentry *dentry); |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 6cdf23fd70ee..8ca70b102b95 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -376,7 +376,7 @@ out: | |||
376 | return rc; | 376 | return rc; |
377 | } | 377 | } |
378 | 378 | ||
379 | struct file * | 379 | int |
380 | cifs_atomic_open(struct inode *inode, struct dentry *direntry, | 380 | cifs_atomic_open(struct inode *inode, struct dentry *direntry, |
381 | struct opendata *od, unsigned oflags, umode_t mode, | 381 | struct opendata *od, unsigned oflags, umode_t mode, |
382 | int *opened) | 382 | int *opened) |
@@ -403,15 +403,15 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, | |||
403 | if (!(oflags & O_CREAT)) { | 403 | if (!(oflags & O_CREAT)) { |
404 | struct dentry *res = cifs_lookup(inode, direntry, NULL); | 404 | struct dentry *res = cifs_lookup(inode, direntry, NULL); |
405 | if (IS_ERR(res)) | 405 | if (IS_ERR(res)) |
406 | return ERR_CAST(res); | 406 | return PTR_ERR(res); |
407 | 407 | ||
408 | finish_no_open(od, res); | 408 | finish_no_open(od, res); |
409 | return NULL; | 409 | return 1; |
410 | } | 410 | } |
411 | 411 | ||
412 | rc = check_name(direntry); | 412 | rc = check_name(direntry); |
413 | if (rc) | 413 | if (rc) |
414 | return ERR_PTR(rc); | 414 | return rc; |
415 | 415 | ||
416 | xid = GetXid(); | 416 | xid = GetXid(); |
417 | 417 | ||
@@ -428,13 +428,12 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, | |||
428 | rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, | 428 | rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, |
429 | &oplock, &fileHandle, opened); | 429 | &oplock, &fileHandle, opened); |
430 | 430 | ||
431 | if (rc) { | 431 | if (rc) |
432 | filp = ERR_PTR(rc); | ||
433 | goto out; | 432 | goto out; |
434 | } | ||
435 | 433 | ||
436 | filp = finish_open(od, direntry, generic_file_open, opened); | 434 | filp = finish_open(od, direntry, generic_file_open, opened); |
437 | if (IS_ERR(filp)) { | 435 | if (IS_ERR(filp)) { |
436 | rc = PTR_ERR(filp); | ||
438 | CIFSSMBClose(xid, tcon, fileHandle); | 437 | CIFSSMBClose(xid, tcon, fileHandle); |
439 | goto out; | 438 | goto out; |
440 | } | 439 | } |
@@ -443,14 +442,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, | |||
443 | if (pfile_info == NULL) { | 442 | if (pfile_info == NULL) { |
444 | CIFSSMBClose(xid, tcon, fileHandle); | 443 | CIFSSMBClose(xid, tcon, fileHandle); |
445 | fput(filp); | 444 | fput(filp); |
446 | filp = ERR_PTR(-ENOMEM); | 445 | rc = -ENOMEM; |
447 | } | 446 | } |
448 | 447 | ||
449 | out: | 448 | out: |
450 | cifs_put_tlink(tlink); | 449 | cifs_put_tlink(tlink); |
451 | free_xid: | 450 | free_xid: |
452 | FreeXid(xid); | 451 | FreeXid(xid); |
453 | return filp; | 452 | return rc; |
454 | } | 453 | } |
455 | 454 | ||
456 | int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | 455 | int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 345f78ee5c9d..8a9ca09e87d4 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -369,9 +369,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
369 | * If the filesystem doesn't support this, then fall back to separate | 369 | * If the filesystem doesn't support this, then fall back to separate |
370 | * 'mknod' + 'open' requests. | 370 | * 'mknod' + 'open' requests. |
371 | */ | 371 | */ |
372 | static struct file *fuse_create_open(struct inode *dir, struct dentry *entry, | 372 | static int fuse_create_open(struct inode *dir, struct dentry *entry, |
373 | struct opendata *od, unsigned flags, | 373 | struct opendata *od, unsigned flags, |
374 | umode_t mode, int *opened) | 374 | umode_t mode, int *opened) |
375 | { | 375 | { |
376 | int err; | 376 | int err; |
377 | struct inode *inode; | 377 | struct inode *inode; |
@@ -452,12 +452,14 @@ static struct file *fuse_create_open(struct inode *dir, struct dentry *entry, | |||
452 | fuse_invalidate_attr(dir); | 452 | fuse_invalidate_attr(dir); |
453 | file = finish_open(od, entry, generic_file_open, opened); | 453 | file = finish_open(od, entry, generic_file_open, opened); |
454 | if (IS_ERR(file)) { | 454 | if (IS_ERR(file)) { |
455 | err = PTR_ERR(file); | ||
455 | fuse_sync_release(ff, flags); | 456 | fuse_sync_release(ff, flags); |
456 | } else { | 457 | } else { |
457 | file->private_data = fuse_file_get(ff); | 458 | file->private_data = fuse_file_get(ff); |
458 | fuse_finish_open(inode, file); | 459 | fuse_finish_open(inode, file); |
460 | err = 0; | ||
459 | } | 461 | } |
460 | return file; | 462 | return err; |
461 | 463 | ||
462 | out_free_ff: | 464 | out_free_ff: |
463 | fuse_file_free(ff); | 465 | fuse_file_free(ff); |
@@ -466,23 +468,22 @@ out_put_request: | |||
466 | out_put_forget_req: | 468 | out_put_forget_req: |
467 | kfree(forget); | 469 | kfree(forget); |
468 | out_err: | 470 | out_err: |
469 | return ERR_PTR(err); | 471 | return err; |
470 | } | 472 | } |
471 | 473 | ||
472 | static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); | 474 | static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); |
473 | static struct file *fuse_atomic_open(struct inode *dir, struct dentry *entry, | 475 | static int fuse_atomic_open(struct inode *dir, struct dentry *entry, |
474 | struct opendata *od, unsigned flags, | 476 | struct opendata *od, unsigned flags, |
475 | umode_t mode, int *opened) | 477 | umode_t mode, int *opened) |
476 | { | 478 | { |
477 | int err; | 479 | int err; |
478 | struct fuse_conn *fc = get_fuse_conn(dir); | 480 | struct fuse_conn *fc = get_fuse_conn(dir); |
479 | struct file *file; | ||
480 | struct dentry *res = NULL; | 481 | struct dentry *res = NULL; |
481 | 482 | ||
482 | if (d_unhashed(entry)) { | 483 | if (d_unhashed(entry)) { |
483 | res = fuse_lookup(dir, entry, NULL); | 484 | res = fuse_lookup(dir, entry, NULL); |
484 | if (IS_ERR(res)) | 485 | if (IS_ERR(res)) |
485 | return ERR_CAST(res); | 486 | return PTR_ERR(res); |
486 | 487 | ||
487 | if (res) | 488 | if (res) |
488 | entry = res; | 489 | entry = res; |
@@ -497,24 +498,22 @@ static struct file *fuse_atomic_open(struct inode *dir, struct dentry *entry, | |||
497 | if (fc->no_create) | 498 | if (fc->no_create) |
498 | goto mknod; | 499 | goto mknod; |
499 | 500 | ||
500 | file = fuse_create_open(dir, entry, od, flags, mode, opened); | 501 | err = fuse_create_open(dir, entry, od, flags, mode, opened); |
501 | if (PTR_ERR(file) == -ENOSYS) { | 502 | if (err == -ENOSYS) { |
502 | fc->no_create = 1; | 503 | fc->no_create = 1; |
503 | goto mknod; | 504 | goto mknod; |
504 | } | 505 | } |
505 | out_dput: | 506 | out_dput: |
506 | dput(res); | 507 | dput(res); |
507 | return file; | 508 | return err; |
508 | 509 | ||
509 | mknod: | 510 | mknod: |
510 | err = fuse_mknod(dir, entry, mode, 0); | 511 | err = fuse_mknod(dir, entry, mode, 0); |
511 | if (err) { | 512 | if (err) |
512 | file = ERR_PTR(err); | ||
513 | goto out_dput; | 513 | goto out_dput; |
514 | } | ||
515 | no_open: | 514 | no_open: |
516 | finish_no_open(od, res); | 515 | finish_no_open(od, res); |
517 | return NULL; | 516 | return 1; |
518 | } | 517 | } |
519 | 518 | ||
520 | /* | 519 | /* |
diff --git a/fs/namei.c b/fs/namei.c index 18b9326d951f..f0dae0057ec9 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2204,7 +2204,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2204 | umode_t mode; | 2204 | umode_t mode; |
2205 | int error; | 2205 | int error; |
2206 | int acc_mode; | 2206 | int acc_mode; |
2207 | struct file *filp; | 2207 | struct file *filp = NULL; |
2208 | int create_error = 0; | 2208 | int create_error = 0; |
2209 | struct dentry *const DENTRY_NOT_SET = (void *) -1UL; | 2209 | struct dentry *const DENTRY_NOT_SET = (void *) -1UL; |
2210 | 2210 | ||
@@ -2271,14 +2271,15 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2271 | 2271 | ||
2272 | od->dentry = DENTRY_NOT_SET; | 2272 | od->dentry = DENTRY_NOT_SET; |
2273 | od->mnt = nd->path.mnt; | 2273 | od->mnt = nd->path.mnt; |
2274 | filp = dir->i_op->atomic_open(dir, dentry, od, open_flag, mode, | 2274 | error = dir->i_op->atomic_open(dir, dentry, od, open_flag, mode, |
2275 | opened); | 2275 | opened); |
2276 | if (IS_ERR(filp)) { | 2276 | if (error < 0) { |
2277 | if (WARN_ON(od->dentry != DENTRY_NOT_SET)) | 2277 | if (WARN_ON(od->dentry != DENTRY_NOT_SET)) |
2278 | dput(od->dentry); | 2278 | dput(od->dentry); |
2279 | 2279 | ||
2280 | if (create_error && PTR_ERR(filp) == -ENOENT) | 2280 | if (create_error && error == -ENOENT) |
2281 | filp = ERR_PTR(create_error); | 2281 | error = create_error; |
2282 | filp = ERR_PTR(error); | ||
2282 | goto out; | 2283 | goto out; |
2283 | } | 2284 | } |
2284 | 2285 | ||
@@ -2288,7 +2289,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2288 | acc_mode = MAY_OPEN; | 2289 | acc_mode = MAY_OPEN; |
2289 | } | 2290 | } |
2290 | 2291 | ||
2291 | if (!filp) { | 2292 | if (error) { /* returned 1, that is */ |
2292 | if (WARN_ON(od->dentry == DENTRY_NOT_SET)) { | 2293 | if (WARN_ON(od->dentry == DENTRY_NOT_SET)) { |
2293 | filp = ERR_PTR(-EIO); | 2294 | filp = ERR_PTR(-EIO); |
2294 | goto out; | 2295 | goto out; |
@@ -2304,6 +2305,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2304 | * We didn't have the inode before the open, so check open permission | 2305 | * We didn't have the inode before the open, so check open permission |
2305 | * here. | 2306 | * here. |
2306 | */ | 2307 | */ |
2308 | filp = od->filp; | ||
2307 | error = may_open(&filp->f_path, acc_mode, open_flag); | 2309 | error = may_open(&filp->f_path, acc_mode, open_flag); |
2308 | if (error) { | 2310 | if (error) { |
2309 | fput(filp); | 2311 | fput(filp); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 6deb2549ead5..b56f4b36ed41 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -111,9 +111,9 @@ const struct inode_operations nfs3_dir_inode_operations = { | |||
111 | 111 | ||
112 | #ifdef CONFIG_NFS_V4 | 112 | #ifdef CONFIG_NFS_V4 |
113 | 113 | ||
114 | static struct file *nfs_atomic_open(struct inode *, struct dentry *, | 114 | static int nfs_atomic_open(struct inode *, struct dentry *, |
115 | struct opendata *, unsigned, umode_t, | 115 | struct opendata *, unsigned, umode_t, |
116 | int *); | 116 | int *); |
117 | const struct inode_operations nfs4_dir_inode_operations = { | 117 | const struct inode_operations nfs4_dir_inode_operations = { |
118 | .create = nfs_create, | 118 | .create = nfs_create, |
119 | .lookup = nfs_lookup, | 119 | .lookup = nfs_lookup, |
@@ -1387,10 +1387,10 @@ static int do_open(struct inode *inode, struct file *filp) | |||
1387 | return 0; | 1387 | return 0; |
1388 | } | 1388 | } |
1389 | 1389 | ||
1390 | static struct file *nfs_finish_open(struct nfs_open_context *ctx, | 1390 | static int nfs_finish_open(struct nfs_open_context *ctx, |
1391 | struct dentry *dentry, | 1391 | struct dentry *dentry, |
1392 | struct opendata *od, unsigned open_flags, | 1392 | struct opendata *od, unsigned open_flags, |
1393 | int *opened) | 1393 | int *opened) |
1394 | { | 1394 | { |
1395 | struct file *filp; | 1395 | struct file *filp; |
1396 | int err; | 1396 | int err; |
@@ -1403,30 +1403,31 @@ static struct file *nfs_finish_open(struct nfs_open_context *ctx, | |||
1403 | /* If the open_intent is for execute, we have an extra check to make */ | 1403 | /* If the open_intent is for execute, we have an extra check to make */ |
1404 | if (ctx->mode & FMODE_EXEC) { | 1404 | if (ctx->mode & FMODE_EXEC) { |
1405 | err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags); | 1405 | err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags); |
1406 | if (err < 0) { | 1406 | if (err < 0) |
1407 | filp = ERR_PTR(err); | ||
1408 | goto out; | 1407 | goto out; |
1409 | } | ||
1410 | } | 1408 | } |
1411 | 1409 | ||
1412 | filp = finish_open(od, dentry, do_open, opened); | 1410 | filp = finish_open(od, dentry, do_open, opened); |
1413 | if (!IS_ERR(filp)) | 1411 | if (IS_ERR(filp)) { |
1414 | nfs_file_set_open_context(filp, ctx); | 1412 | err = PTR_ERR(filp); |
1413 | goto out; | ||
1414 | } | ||
1415 | nfs_file_set_open_context(filp, ctx); | ||
1416 | err = 0; | ||
1415 | 1417 | ||
1416 | out: | 1418 | out: |
1417 | put_nfs_open_context(ctx); | 1419 | put_nfs_open_context(ctx); |
1418 | return filp; | 1420 | return err; |
1419 | } | 1421 | } |
1420 | 1422 | ||
1421 | static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, | 1423 | static int nfs_atomic_open(struct inode *dir, struct dentry *dentry, |
1422 | struct opendata *od, unsigned open_flags, | 1424 | struct opendata *od, unsigned open_flags, |
1423 | umode_t mode, int *opened) | 1425 | umode_t mode, int *opened) |
1424 | { | 1426 | { |
1425 | struct nfs_open_context *ctx; | 1427 | struct nfs_open_context *ctx; |
1426 | struct dentry *res; | 1428 | struct dentry *res; |
1427 | struct iattr attr = { .ia_valid = ATTR_OPEN }; | 1429 | struct iattr attr = { .ia_valid = ATTR_OPEN }; |
1428 | struct inode *inode; | 1430 | struct inode *inode; |
1429 | struct file *filp; | ||
1430 | int err; | 1431 | int err; |
1431 | 1432 | ||
1432 | /* Expect a negative dentry */ | 1433 | /* Expect a negative dentry */ |
@@ -1437,21 +1438,19 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1437 | 1438 | ||
1438 | /* NFS only supports OPEN on regular files */ | 1439 | /* NFS only supports OPEN on regular files */ |
1439 | if ((open_flags & O_DIRECTORY)) { | 1440 | if ((open_flags & O_DIRECTORY)) { |
1440 | err = -ENOENT; | ||
1441 | if (!d_unhashed(dentry)) { | 1441 | if (!d_unhashed(dentry)) { |
1442 | /* | 1442 | /* |
1443 | * Hashed negative dentry with O_DIRECTORY: dentry was | 1443 | * Hashed negative dentry with O_DIRECTORY: dentry was |
1444 | * revalidated and is fine, no need to perform lookup | 1444 | * revalidated and is fine, no need to perform lookup |
1445 | * again | 1445 | * again |
1446 | */ | 1446 | */ |
1447 | goto out_err; | 1447 | return -ENOENT; |
1448 | } | 1448 | } |
1449 | goto no_open; | 1449 | goto no_open; |
1450 | } | 1450 | } |
1451 | 1451 | ||
1452 | err = -ENAMETOOLONG; | ||
1453 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) | 1452 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) |
1454 | goto out_err; | 1453 | return -ENAMETOOLONG; |
1455 | 1454 | ||
1456 | if (open_flags & O_CREAT) { | 1455 | if (open_flags & O_CREAT) { |
1457 | attr.ia_valid |= ATTR_MODE; | 1456 | attr.ia_valid |= ATTR_MODE; |
@@ -1465,7 +1464,7 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1465 | ctx = create_nfs_open_context(dentry, open_flags); | 1464 | ctx = create_nfs_open_context(dentry, open_flags); |
1466 | err = PTR_ERR(ctx); | 1465 | err = PTR_ERR(ctx); |
1467 | if (IS_ERR(ctx)) | 1466 | if (IS_ERR(ctx)) |
1468 | goto out_err; | 1467 | goto out; |
1469 | 1468 | ||
1470 | nfs_block_sillyrename(dentry->d_parent); | 1469 | nfs_block_sillyrename(dentry->d_parent); |
1471 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1470 | 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 | default: | 1488 | default: |
1490 | break; | 1489 | break; |
1491 | } | 1490 | } |
1492 | goto out_err; | 1491 | goto out; |
1493 | } | 1492 | } |
1494 | res = d_add_unique(dentry, inode); | 1493 | res = d_add_unique(dentry, inode); |
1495 | if (res != NULL) | 1494 | if (res != NULL) |
@@ -1498,22 +1497,20 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1498 | nfs_unblock_sillyrename(dentry->d_parent); | 1497 | nfs_unblock_sillyrename(dentry->d_parent); |
1499 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1498 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1500 | 1499 | ||
1501 | filp = nfs_finish_open(ctx, dentry, od, open_flags, opened); | 1500 | err = nfs_finish_open(ctx, dentry, od, open_flags, opened); |
1502 | 1501 | ||
1503 | dput(res); | 1502 | dput(res); |
1504 | return filp; | 1503 | out: |
1505 | 1504 | return err; | |
1506 | out_err: | ||
1507 | return ERR_PTR(err); | ||
1508 | 1505 | ||
1509 | no_open: | 1506 | no_open: |
1510 | res = nfs_lookup(dir, dentry, NULL); | 1507 | res = nfs_lookup(dir, dentry, NULL); |
1511 | err = PTR_ERR(res); | 1508 | err = PTR_ERR(res); |
1512 | if (IS_ERR(res)) | 1509 | if (IS_ERR(res)) |
1513 | goto out_err; | 1510 | goto out; |
1514 | 1511 | ||
1515 | finish_no_open(od, res); | 1512 | finish_no_open(od, res); |
1516 | return NULL; | 1513 | return 1; |
1517 | } | 1514 | } |
1518 | 1515 | ||
1519 | static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | 1516 | static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) |
diff --git a/include/linux/fs.h b/include/linux/fs.h index a7618cf28d0e..33bda922988a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1694,9 +1694,9 @@ struct inode_operations { | |||
1694 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, | 1694 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, |
1695 | u64 len); | 1695 | u64 len); |
1696 | int (*update_time)(struct inode *, struct timespec *, int); | 1696 | int (*update_time)(struct inode *, struct timespec *, int); |
1697 | struct file * (*atomic_open)(struct inode *, struct dentry *, | 1697 | int (*atomic_open)(struct inode *, struct dentry *, |
1698 | struct opendata *, unsigned open_flag, | 1698 | struct opendata *, unsigned open_flag, |
1699 | umode_t create_mode, int *opened); | 1699 | umode_t create_mode, int *opened); |
1700 | } ____cacheline_aligned; | 1700 | } ____cacheline_aligned; |
1701 | 1701 | ||
1702 | struct seq_file; | 1702 | struct seq_file; |