diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-06-10 05:01:45 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-14 08:33:31 -0400 |
commit | 47237687d73cbeae1dd7a133c3fc3d7239094568 (patch) | |
tree | 1d267d03246f0a16cbff3c8221ee69dd1521f835 | |
parent | a8277b9baa6268de386529a33061775bc716198b (diff) |
->atomic_open() prototype change - pass int * instead of bool *
... and let finish_open() report having opened the file via that sucker.
Next step: don't modify od->filp at all.
[AV: FILE_CREATE was already used by cifs; Miklos' fix folded]
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | Documentation/filesystems/Locking | 2 | ||||
-rw-r--r-- | Documentation/filesystems/vfs.txt | 2 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 6 | ||||
-rw-r--r-- | fs/9p/vfs_inode_dotl.c | 6 | ||||
-rw-r--r-- | fs/ceph/dir.c | 8 | ||||
-rw-r--r-- | fs/ceph/file.c | 5 | ||||
-rw-r--r-- | fs/ceph/super.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 2 | ||||
-rw-r--r-- | fs/cifs/dir.c | 12 | ||||
-rw-r--r-- | fs/fuse/dir.c | 10 | ||||
-rw-r--r-- | fs/namei.c | 33 | ||||
-rw-r--r-- | fs/nfs/dir.c | 11 | ||||
-rw-r--r-- | fs/open.c | 7 | ||||
-rw-r--r-- | include/linux/fs.h | 9 |
14 files changed, 63 insertions, 52 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 8157488c3463..af4e45bd6cfa 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -64,7 +64,7 @@ ata *); | |||
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 | struct file * (*atomic_open)(struct inode *, struct dentry *, |
66 | struct opendata *, unsigned open_flag, | 66 | struct opendata *, unsigned open_flag, |
67 | umode_t create_mode, bool *created); | 67 | umode_t create_mode, int *opened); |
68 | 68 | ||
69 | locking rules: | 69 | locking rules: |
70 | all may block | 70 | all may block |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index beb6e691f70a..d7121051afcd 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -366,7 +366,7 @@ struct inode_operations { | |||
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 | struct file * (*atomic_open)(struct inode *, struct dentry *, |
368 | struct opendata *, unsigned open_flag, | 368 | struct opendata *, unsigned open_flag, |
369 | umode_t create_mode, bool *created); | 369 | umode_t create_mode, int *opened); |
370 | }; | 370 | }; |
371 | 371 | ||
372 | Again, all methods are called without any locks being held, unless | 372 | Again, all methods are called without any locks being held, unless |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index e8c42ceb89ba..de626b3b342f 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -859,7 +859,7 @@ error: | |||
859 | static struct file * | 859 | static struct file * |
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 | bool *created) | 862 | int *opened) |
863 | { | 863 | { |
864 | int err; | 864 | int err; |
865 | u32 perm; | 865 | u32 perm; |
@@ -918,7 +918,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
918 | v9inode->writeback_fid = (void *) inode_fid; | 918 | v9inode->writeback_fid = (void *) inode_fid; |
919 | } | 919 | } |
920 | mutex_unlock(&v9inode->v_mutex); | 920 | mutex_unlock(&v9inode->v_mutex); |
921 | filp = finish_open(od, dentry, generic_file_open); | 921 | filp = finish_open(od, dentry, generic_file_open, opened); |
922 | if (IS_ERR(filp)) { | 922 | if (IS_ERR(filp)) { |
923 | err = PTR_ERR(filp); | 923 | err = PTR_ERR(filp); |
924 | goto error; | 924 | goto error; |
@@ -930,7 +930,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
930 | v9fs_cache_inode_set_cookie(dentry->d_inode, filp); | 930 | v9fs_cache_inode_set_cookie(dentry->d_inode, filp); |
931 | #endif | 931 | #endif |
932 | 932 | ||
933 | *created = true; | 933 | *opened |= FILE_CREATED; |
934 | out: | 934 | out: |
935 | dput(res); | 935 | dput(res); |
936 | return filp; | 936 | return filp; |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index a354fe2cb234..3db55471bc93 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
@@ -243,7 +243,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, | |||
243 | static struct file * | 243 | static struct file * |
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 | bool *created) | 246 | int *opened) |
247 | { | 247 | { |
248 | int err = 0; | 248 | int err = 0; |
249 | gid_t gid; | 249 | gid_t gid; |
@@ -357,7 +357,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | |||
357 | } | 357 | } |
358 | mutex_unlock(&v9inode->v_mutex); | 358 | mutex_unlock(&v9inode->v_mutex); |
359 | /* Since we are opening a file, assign the open fid to the file */ | 359 | /* Since we are opening a file, assign the open fid to the file */ |
360 | filp = finish_open(od, dentry, generic_file_open); | 360 | filp = finish_open(od, dentry, generic_file_open, opened); |
361 | if (IS_ERR(filp)) { | 361 | if (IS_ERR(filp)) { |
362 | err = PTR_ERR(filp); | 362 | err = PTR_ERR(filp); |
363 | goto err_clunk_old_fid; | 363 | goto err_clunk_old_fid; |
@@ -367,7 +367,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | |||
367 | if (v9ses->cache) | 367 | if (v9ses->cache) |
368 | v9fs_cache_inode_set_cookie(inode, filp); | 368 | v9fs_cache_inode_set_cookie(inode, filp); |
369 | #endif | 369 | #endif |
370 | *created = true; | 370 | *opened |= FILE_CREATED; |
371 | out: | 371 | out: |
372 | dput(res); | 372 | dput(res); |
373 | return filp; | 373 | return filp; |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 75df600ec9b4..81e5e908df9d 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -636,7 +636,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
636 | 636 | ||
637 | struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry, | 637 | struct file *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 | bool *created) | 639 | int *opened) |
640 | { | 640 | { |
641 | int err; | 641 | int err; |
642 | struct dentry *res = NULL; | 642 | struct dentry *res = NULL; |
@@ -650,7 +650,7 @@ struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry, | |||
650 | if (err < 0) | 650 | if (err < 0) |
651 | return ERR_PTR(err); | 651 | return ERR_PTR(err); |
652 | 652 | ||
653 | return ceph_lookup_open(dir, dentry, od, flags, mode); | 653 | return ceph_lookup_open(dir, dentry, od, flags, mode, opened); |
654 | } | 654 | } |
655 | 655 | ||
656 | if (d_unhashed(dentry)) { | 656 | if (d_unhashed(dentry)) { |
@@ -668,8 +668,8 @@ struct file *ceph_atomic_open(struct inode *dir, struct dentry *dentry, | |||
668 | return NULL; | 668 | return NULL; |
669 | } | 669 | } |
670 | 670 | ||
671 | *created = true; | 671 | *opened |= FILE_CREATED; |
672 | filp = ceph_lookup_open(dir, dentry, od, flags, mode); | 672 | filp = ceph_lookup_open(dir, dentry, od, flags, mode, opened); |
673 | dput(res); | 673 | dput(res); |
674 | 674 | ||
675 | return filp; | 675 | return filp; |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index e34dc22e75a9..4c304a90d046 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -214,7 +214,8 @@ out: | |||
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 | struct file *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 | { | 219 | { |
219 | 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); |
220 | struct ceph_mds_client *mdsc = fsc->mdsc; | 221 | struct ceph_mds_client *mdsc = fsc->mdsc; |
@@ -247,7 +248,7 @@ struct file *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | |||
247 | err = ceph_handle_notrace_create(dir, dentry); | 248 | err = ceph_handle_notrace_create(dir, dentry); |
248 | if (err) | 249 | if (err) |
249 | goto out; | 250 | goto out; |
250 | file = finish_open(od, req->r_dentry, ceph_open); | 251 | file = finish_open(od, req->r_dentry, ceph_open, opened); |
251 | if (IS_ERR(file)) | 252 | if (IS_ERR(file)) |
252 | err = PTR_ERR(file); | 253 | err = PTR_ERR(file); |
253 | out: | 254 | out: |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index e61e54673e56..f9a325108b49 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -808,7 +808,7 @@ 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 struct file *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); | 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 3a572bf5947f..92a7c3d8a031 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -48,7 +48,7 @@ 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 struct file *cifs_atomic_open(struct inode *, struct dentry *, |
50 | struct opendata *, unsigned, umode_t, | 50 | struct opendata *, unsigned, umode_t, |
51 | bool *); | 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 7a3dcd15d681..6cdf23fd70ee 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -160,7 +160,7 @@ check_name(struct dentry *direntry) | |||
160 | static int cifs_do_create(struct inode *inode, struct dentry *direntry, | 160 | static int cifs_do_create(struct inode *inode, struct dentry *direntry, |
161 | int xid, struct tcon_link *tlink, unsigned oflags, | 161 | int xid, struct tcon_link *tlink, unsigned oflags, |
162 | umode_t mode, __u32 *oplock, __u16 *fileHandle, | 162 | umode_t mode, __u32 *oplock, __u16 *fileHandle, |
163 | bool *created) | 163 | int *created) |
164 | { | 164 | { |
165 | int rc = -ENOENT; | 165 | int rc = -ENOENT; |
166 | int create_options = CREATE_NOT_DIR; | 166 | int create_options = CREATE_NOT_DIR; |
@@ -311,7 +311,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, | |||
311 | .device = 0, | 311 | .device = 0, |
312 | }; | 312 | }; |
313 | 313 | ||
314 | *created = true; | 314 | *created |= FILE_CREATED; |
315 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 315 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
316 | args.uid = (__u64) current_fsuid(); | 316 | args.uid = (__u64) current_fsuid(); |
317 | if (inode->i_mode & S_ISGID) | 317 | if (inode->i_mode & S_ISGID) |
@@ -379,7 +379,7 @@ out: | |||
379 | struct file * | 379 | struct file * |
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 | bool *created) | 382 | int *opened) |
383 | { | 383 | { |
384 | int rc; | 384 | int rc; |
385 | int xid; | 385 | int xid; |
@@ -426,14 +426,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, | |||
426 | tcon = tlink_tcon(tlink); | 426 | tcon = tlink_tcon(tlink); |
427 | 427 | ||
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, created); | 429 | &oplock, &fileHandle, opened); |
430 | 430 | ||
431 | if (rc) { | 431 | if (rc) { |
432 | filp = ERR_PTR(rc); | 432 | filp = ERR_PTR(rc); |
433 | goto out; | 433 | goto out; |
434 | } | 434 | } |
435 | 435 | ||
436 | filp = finish_open(od, direntry, generic_file_open); | 436 | filp = finish_open(od, direntry, generic_file_open, opened); |
437 | if (IS_ERR(filp)) { | 437 | if (IS_ERR(filp)) { |
438 | CIFSSMBClose(xid, tcon, fileHandle); | 438 | CIFSSMBClose(xid, tcon, fileHandle); |
439 | goto out; | 439 | goto out; |
@@ -469,7 +469,7 @@ int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
469 | struct tcon_link *tlink; | 469 | struct tcon_link *tlink; |
470 | __u16 fileHandle; | 470 | __u16 fileHandle; |
471 | __u32 oplock; | 471 | __u32 oplock; |
472 | bool created = true; | 472 | int created = FILE_CREATED; |
473 | 473 | ||
474 | cFYI(1, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p", | 474 | cFYI(1, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p", |
475 | inode, direntry->d_name.name, direntry); | 475 | inode, direntry->d_name.name, direntry); |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index e42442f1da16..345f78ee5c9d 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -371,7 +371,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
371 | */ | 371 | */ |
372 | static struct file *fuse_create_open(struct inode *dir, struct dentry *entry, | 372 | static struct file *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) | 374 | umode_t mode, int *opened) |
375 | { | 375 | { |
376 | int err; | 376 | int err; |
377 | struct inode *inode; | 377 | struct inode *inode; |
@@ -450,7 +450,7 @@ static struct file *fuse_create_open(struct inode *dir, struct dentry *entry, | |||
450 | d_instantiate(entry, inode); | 450 | d_instantiate(entry, inode); |
451 | fuse_change_entry_timeout(entry, &outentry); | 451 | fuse_change_entry_timeout(entry, &outentry); |
452 | fuse_invalidate_attr(dir); | 452 | fuse_invalidate_attr(dir); |
453 | file = finish_open(od, entry, generic_file_open); | 453 | file = finish_open(od, entry, generic_file_open, opened); |
454 | if (IS_ERR(file)) { | 454 | if (IS_ERR(file)) { |
455 | fuse_sync_release(ff, flags); | 455 | fuse_sync_release(ff, flags); |
456 | } else { | 456 | } else { |
@@ -472,7 +472,7 @@ out_err: | |||
472 | static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); | 472 | 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, | 473 | static struct file *fuse_atomic_open(struct inode *dir, struct dentry *entry, |
474 | struct opendata *od, unsigned flags, | 474 | struct opendata *od, unsigned flags, |
475 | umode_t mode, bool *created) | 475 | umode_t mode, int *opened) |
476 | { | 476 | { |
477 | int err; | 477 | int err; |
478 | struct fuse_conn *fc = get_fuse_conn(dir); | 478 | struct fuse_conn *fc = get_fuse_conn(dir); |
@@ -492,12 +492,12 @@ static struct file *fuse_atomic_open(struct inode *dir, struct dentry *entry, | |||
492 | goto no_open; | 492 | goto no_open; |
493 | 493 | ||
494 | /* Only creates */ | 494 | /* Only creates */ |
495 | *created = true; | 495 | *opened |= FILE_CREATED; |
496 | 496 | ||
497 | if (fc->no_create) | 497 | if (fc->no_create) |
498 | goto mknod; | 498 | goto mknod; |
499 | 499 | ||
500 | file = fuse_create_open(dir, entry, od, flags, mode); | 500 | file = fuse_create_open(dir, entry, od, flags, mode, opened); |
501 | if (PTR_ERR(file) == -ENOSYS) { | 501 | if (PTR_ERR(file) == -ENOSYS) { |
502 | fc->no_create = 1; | 502 | fc->no_create = 1; |
503 | goto mknod; | 503 | goto mknod; |
diff --git a/fs/namei.c b/fs/namei.c index 4bc4bc6a6938..7a33f074e5bd 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2197,7 +2197,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2197 | struct path *path, struct opendata *od, | 2197 | struct path *path, struct opendata *od, |
2198 | const struct open_flags *op, | 2198 | const struct open_flags *op, |
2199 | bool *want_write, bool need_lookup, | 2199 | bool *want_write, bool need_lookup, |
2200 | bool *created) | 2200 | int *opened) |
2201 | { | 2201 | { |
2202 | struct inode *dir = nd->path.dentry->d_inode; | 2202 | struct inode *dir = nd->path.dentry->d_inode; |
2203 | unsigned open_flag = open_to_namei_flags(op->open_flag); | 2203 | unsigned open_flag = open_to_namei_flags(op->open_flag); |
@@ -2222,7 +2222,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2222 | 2222 | ||
2223 | if (open_flag & O_EXCL) { | 2223 | if (open_flag & O_EXCL) { |
2224 | open_flag &= ~O_TRUNC; | 2224 | open_flag &= ~O_TRUNC; |
2225 | *created = true; | 2225 | *opened |= FILE_CREATED; |
2226 | } | 2226 | } |
2227 | 2227 | ||
2228 | /* | 2228 | /* |
@@ -2272,7 +2272,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
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 | filp = dir->i_op->atomic_open(dir, dentry, od, open_flag, mode, |
2275 | created); | 2275 | opened); |
2276 | if (IS_ERR(filp)) { | 2276 | if (IS_ERR(filp)) { |
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); |
@@ -2283,7 +2283,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
2283 | } | 2283 | } |
2284 | 2284 | ||
2285 | acc_mode = op->acc_mode; | 2285 | acc_mode = op->acc_mode; |
2286 | if (*created) { | 2286 | if (*opened & FILE_CREATED) { |
2287 | fsnotify_create(dir, dentry); | 2287 | fsnotify_create(dir, dentry); |
2288 | acc_mode = MAY_OPEN; | 2288 | acc_mode = MAY_OPEN; |
2289 | } | 2289 | } |
@@ -2353,7 +2353,7 @@ looked_up: | |||
2353 | static struct file *lookup_open(struct nameidata *nd, struct path *path, | 2353 | static struct file *lookup_open(struct nameidata *nd, struct path *path, |
2354 | struct opendata *od, | 2354 | struct opendata *od, |
2355 | const struct open_flags *op, | 2355 | const struct open_flags *op, |
2356 | bool *want_write, bool *created) | 2356 | bool *want_write, int *opened) |
2357 | { | 2357 | { |
2358 | struct dentry *dir = nd->path.dentry; | 2358 | struct dentry *dir = nd->path.dentry; |
2359 | struct inode *dir_inode = dir->d_inode; | 2359 | struct inode *dir_inode = dir->d_inode; |
@@ -2361,7 +2361,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path, | |||
2361 | int error; | 2361 | int error; |
2362 | bool need_lookup; | 2362 | bool need_lookup; |
2363 | 2363 | ||
2364 | *created = false; | 2364 | *opened &= ~FILE_CREATED; |
2365 | dentry = lookup_dcache(&nd->last, dir, nd, &need_lookup); | 2365 | dentry = lookup_dcache(&nd->last, dir, nd, &need_lookup); |
2366 | if (IS_ERR(dentry)) | 2366 | if (IS_ERR(dentry)) |
2367 | return ERR_CAST(dentry); | 2367 | return ERR_CAST(dentry); |
@@ -2372,7 +2372,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path, | |||
2372 | 2372 | ||
2373 | if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) { | 2373 | if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) { |
2374 | return atomic_open(nd, dentry, path, od, op, want_write, | 2374 | return atomic_open(nd, dentry, path, od, op, want_write, |
2375 | need_lookup, created); | 2375 | need_lookup, opened); |
2376 | } | 2376 | } |
2377 | 2377 | ||
2378 | if (need_lookup) { | 2378 | if (need_lookup) { |
@@ -2399,7 +2399,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path, | |||
2399 | if (error) | 2399 | if (error) |
2400 | goto out_dput; | 2400 | goto out_dput; |
2401 | *want_write = true; | 2401 | *want_write = true; |
2402 | *created = true; | 2402 | *opened |= FILE_CREATED; |
2403 | error = security_path_mknod(&nd->path, dentry, mode, 0); | 2403 | error = security_path_mknod(&nd->path, dentry, mode, 0); |
2404 | if (error) | 2404 | if (error) |
2405 | goto out_dput; | 2405 | goto out_dput; |
@@ -2422,7 +2422,7 @@ out_dput: | |||
2422 | */ | 2422 | */ |
2423 | static struct file *do_last(struct nameidata *nd, struct path *path, | 2423 | static struct file *do_last(struct nameidata *nd, struct path *path, |
2424 | struct opendata *od, const struct open_flags *op, | 2424 | struct opendata *od, const struct open_flags *op, |
2425 | const char *pathname) | 2425 | int *opened, const char *pathname) |
2426 | { | 2426 | { |
2427 | struct dentry *dir = nd->path.dentry; | 2427 | struct dentry *dir = nd->path.dentry; |
2428 | int open_flag = op->open_flag; | 2428 | int open_flag = op->open_flag; |
@@ -2431,7 +2431,6 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2431 | int acc_mode = op->acc_mode; | 2431 | int acc_mode = op->acc_mode; |
2432 | struct file *filp; | 2432 | struct file *filp; |
2433 | struct inode *inode; | 2433 | struct inode *inode; |
2434 | bool created; | ||
2435 | bool symlink_ok = false; | 2434 | bool symlink_ok = false; |
2436 | struct path save_parent = { .dentry = NULL, .mnt = NULL }; | 2435 | struct path save_parent = { .dentry = NULL, .mnt = NULL }; |
2437 | bool retried = false; | 2436 | bool retried = false; |
@@ -2499,21 +2498,22 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2499 | 2498 | ||
2500 | retry_lookup: | 2499 | retry_lookup: |
2501 | mutex_lock(&dir->d_inode->i_mutex); | 2500 | mutex_lock(&dir->d_inode->i_mutex); |
2502 | filp = lookup_open(nd, path, od, op, &want_write, &created); | 2501 | filp = lookup_open(nd, path, od, op, &want_write, opened); |
2503 | mutex_unlock(&dir->d_inode->i_mutex); | 2502 | mutex_unlock(&dir->d_inode->i_mutex); |
2504 | 2503 | ||
2505 | if (filp) { | 2504 | if (filp) { |
2506 | if (IS_ERR(filp)) | 2505 | if (IS_ERR(filp)) |
2507 | goto out; | 2506 | goto out; |
2508 | 2507 | ||
2509 | if (created || !S_ISREG(filp->f_path.dentry->d_inode->i_mode)) | 2508 | if ((*opened & FILE_CREATED) || |
2509 | !S_ISREG(filp->f_path.dentry->d_inode->i_mode)) | ||
2510 | will_truncate = false; | 2510 | will_truncate = false; |
2511 | 2511 | ||
2512 | audit_inode(pathname, filp->f_path.dentry); | 2512 | audit_inode(pathname, filp->f_path.dentry); |
2513 | goto opened; | 2513 | goto opened; |
2514 | } | 2514 | } |
2515 | 2515 | ||
2516 | if (created) { | 2516 | if (*opened & FILE_CREATED) { |
2517 | /* Don't check for write permission, don't truncate */ | 2517 | /* Don't check for write permission, don't truncate */ |
2518 | open_flag &= ~O_TRUNC; | 2518 | open_flag &= ~O_TRUNC; |
2519 | will_truncate = false; | 2519 | will_truncate = false; |
@@ -2606,7 +2606,7 @@ finish_open_created: | |||
2606 | if (error) | 2606 | if (error) |
2607 | goto exit; | 2607 | goto exit; |
2608 | od->mnt = nd->path.mnt; | 2608 | od->mnt = nd->path.mnt; |
2609 | filp = finish_open(od, nd->path.dentry, NULL); | 2609 | filp = finish_open(od, nd->path.dentry, NULL, opened); |
2610 | if (IS_ERR(filp)) { | 2610 | if (IS_ERR(filp)) { |
2611 | if (filp == ERR_PTR(-EOPENSTALE)) | 2611 | if (filp == ERR_PTR(-EOPENSTALE)) |
2612 | goto stale_open; | 2612 | goto stale_open; |
@@ -2667,6 +2667,7 @@ static struct file *path_openat(int dfd, const char *pathname, | |||
2667 | struct opendata od; | 2667 | struct opendata od; |
2668 | struct file *res; | 2668 | struct file *res; |
2669 | struct path path; | 2669 | struct path path; |
2670 | int opened = 0; | ||
2670 | int error; | 2671 | int error; |
2671 | 2672 | ||
2672 | od.filp = get_empty_filp(); | 2673 | od.filp = get_empty_filp(); |
@@ -2684,7 +2685,7 @@ static struct file *path_openat(int dfd, const char *pathname, | |||
2684 | if (unlikely(error)) | 2685 | if (unlikely(error)) |
2685 | goto out_filp; | 2686 | goto out_filp; |
2686 | 2687 | ||
2687 | res = do_last(nd, &path, &od, op, pathname); | 2688 | res = do_last(nd, &path, &od, op, &opened, pathname); |
2688 | while (unlikely(!res)) { /* trailing symlink */ | 2689 | while (unlikely(!res)) { /* trailing symlink */ |
2689 | struct path link = path; | 2690 | struct path link = path; |
2690 | void *cookie; | 2691 | void *cookie; |
@@ -2699,7 +2700,7 @@ static struct file *path_openat(int dfd, const char *pathname, | |||
2699 | error = follow_link(&link, nd, &cookie); | 2700 | error = follow_link(&link, nd, &cookie); |
2700 | if (unlikely(error)) | 2701 | if (unlikely(error)) |
2701 | goto out_filp; | 2702 | goto out_filp; |
2702 | res = do_last(nd, &path, &od, op, pathname); | 2703 | res = do_last(nd, &path, &od, op, &opened, pathname); |
2703 | put_link(nd, &link, cookie); | 2704 | put_link(nd, &link, cookie); |
2704 | } | 2705 | } |
2705 | out: | 2706 | out: |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e6d55dc93ffd..6deb2549ead5 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -113,7 +113,7 @@ const struct inode_operations nfs3_dir_inode_operations = { | |||
113 | 113 | ||
114 | static struct file *nfs_atomic_open(struct inode *, struct dentry *, | 114 | static struct file *nfs_atomic_open(struct inode *, struct dentry *, |
115 | struct opendata *, unsigned, umode_t, | 115 | struct opendata *, unsigned, umode_t, |
116 | bool *); | 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, |
@@ -1389,7 +1389,8 @@ static int do_open(struct inode *inode, struct file *filp) | |||
1389 | 1389 | ||
1390 | static struct file *nfs_finish_open(struct nfs_open_context *ctx, | 1390 | static struct file *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 | { | 1394 | { |
1394 | struct file *filp; | 1395 | struct file *filp; |
1395 | int err; | 1396 | int err; |
@@ -1408,7 +1409,7 @@ static struct file *nfs_finish_open(struct nfs_open_context *ctx, | |||
1408 | } | 1409 | } |
1409 | } | 1410 | } |
1410 | 1411 | ||
1411 | filp = finish_open(od, dentry, do_open); | 1412 | filp = finish_open(od, dentry, do_open, opened); |
1412 | if (!IS_ERR(filp)) | 1413 | if (!IS_ERR(filp)) |
1413 | nfs_file_set_open_context(filp, ctx); | 1414 | nfs_file_set_open_context(filp, ctx); |
1414 | 1415 | ||
@@ -1419,7 +1420,7 @@ out: | |||
1419 | 1420 | ||
1420 | static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, | 1421 | static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, |
1421 | struct opendata *od, unsigned open_flags, | 1422 | struct opendata *od, unsigned open_flags, |
1422 | umode_t mode, bool *created) | 1423 | umode_t mode, int *opened) |
1423 | { | 1424 | { |
1424 | struct nfs_open_context *ctx; | 1425 | struct nfs_open_context *ctx; |
1425 | struct dentry *res; | 1426 | struct dentry *res; |
@@ -1497,7 +1498,7 @@ static struct file *nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1497 | nfs_unblock_sillyrename(dentry->d_parent); | 1498 | nfs_unblock_sillyrename(dentry->d_parent); |
1498 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1499 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1499 | 1500 | ||
1500 | filp = nfs_finish_open(ctx, dentry, od, open_flags); | 1501 | filp = nfs_finish_open(ctx, dentry, od, open_flags, opened); |
1501 | 1502 | ||
1502 | dput(res); | 1503 | dput(res); |
1503 | return filp; | 1504 | return filp; |
@@ -782,7 +782,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
782 | * filesystem callback is substituted. | 782 | * filesystem callback is substituted. |
783 | */ | 783 | */ |
784 | struct file *finish_open(struct opendata *od, struct dentry *dentry, | 784 | struct file *finish_open(struct opendata *od, struct dentry *dentry, |
785 | int (*open)(struct inode *, struct file *)) | 785 | int (*open)(struct inode *, struct file *), |
786 | int *opened) | ||
786 | { | 787 | { |
787 | struct file *res; | 788 | struct file *res; |
788 | 789 | ||
@@ -790,8 +791,10 @@ struct file *finish_open(struct opendata *od, struct dentry *dentry, | |||
790 | dget(dentry); | 791 | dget(dentry); |
791 | 792 | ||
792 | res = do_dentry_open(dentry, od->mnt, od->filp, open, current_cred()); | 793 | res = do_dentry_open(dentry, od->mnt, od->filp, open, current_cred()); |
793 | if (!IS_ERR(res)) | 794 | if (!IS_ERR(res)) { |
795 | *opened |= FILE_OPENED; | ||
794 | od->filp = NULL; | 796 | od->filp = NULL; |
797 | } | ||
795 | 798 | ||
796 | return res; | 799 | return res; |
797 | } | 800 | } |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 0314635cf833..a7618cf28d0e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1696,7 +1696,7 @@ struct inode_operations { | |||
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 | struct file * (*atomic_open)(struct inode *, struct dentry *, |
1698 | struct opendata *, unsigned open_flag, | 1698 | struct opendata *, unsigned open_flag, |
1699 | umode_t create_mode, bool *created); | 1699 | umode_t create_mode, int *opened); |
1700 | } ____cacheline_aligned; | 1700 | } ____cacheline_aligned; |
1701 | 1701 | ||
1702 | struct seq_file; | 1702 | struct seq_file; |
@@ -2065,8 +2065,13 @@ extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, | |||
2065 | const struct cred *); | 2065 | const struct cred *); |
2066 | extern int filp_close(struct file *, fl_owner_t id); | 2066 | extern int filp_close(struct file *, fl_owner_t id); |
2067 | extern char * getname(const char __user *); | 2067 | extern char * getname(const char __user *); |
2068 | enum { | ||
2069 | FILE_CREATED = 1, | ||
2070 | FILE_OPENED = 2 | ||
2071 | }; | ||
2068 | extern struct file *finish_open(struct opendata *od, struct dentry *dentry, | 2072 | extern struct file *finish_open(struct opendata *od, struct dentry *dentry, |
2069 | int (*open)(struct inode *, struct file *)); | 2073 | int (*open)(struct inode *, struct file *), |
2074 | int *opened); | ||
2070 | extern void finish_no_open(struct opendata *od, struct dentry *dentry); | 2075 | extern void finish_no_open(struct opendata *od, struct dentry *dentry); |
2071 | 2076 | ||
2072 | /* fs/ioctl.c */ | 2077 | /* fs/ioctl.c */ |