diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-06-08 13:22:02 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-07-12 10:04:18 -0400 |
commit | 73a09dd94377e4b186b300bd5461920710c7c3d5 (patch) | |
tree | bb66705e5b7215057e416b4f6cb9670561b6b395 | |
parent | aad888f828fec1e7160b67f122172e7ab7f82e03 (diff) |
introduce FMODE_CREATED and switch to it
Parallel to FILE_CREATED, goes into ->f_mode instead of *opened.
NFS is a bit of a wart here - it doesn't have file at the point
where FILE_CREATED used to be set, so we need to propagate it
there (for now). IMA is another one (here and everywhere)...
Note that this needs do_dentry_open() to leave old bits in ->f_mode
alone - we want it to preserve FMODE_CREATED if it had been already
set (no other bit can be there).
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/9p/vfs_inode.c | 2 | ||||
-rw-r--r-- | fs/9p/vfs_inode_dotl.c | 2 | ||||
-rw-r--r-- | fs/ceph/file.c | 2 | ||||
-rw-r--r-- | fs/cifs/dir.c | 2 | ||||
-rw-r--r-- | fs/fuse/dir.c | 2 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 2 | ||||
-rw-r--r-- | fs/namei.c | 15 | ||||
-rw-r--r-- | fs/nfs/dir.c | 5 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
-rw-r--r-- | include/linux/fs.h | 1 |
10 files changed, 20 insertions, 15 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 42e102e2e74a..566929792480 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -925,7 +925,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
925 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) | 925 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) |
926 | v9fs_cache_inode_set_cookie(d_inode(dentry), file); | 926 | v9fs_cache_inode_set_cookie(d_inode(dentry), file); |
927 | 927 | ||
928 | *opened |= FILE_CREATED; | 928 | file->f_mode |= FMODE_CREATED; |
929 | out: | 929 | out: |
930 | dput(res); | 930 | dput(res); |
931 | return err; | 931 | return err; |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 7f6ae21a27b3..ee65db5c7eb0 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
@@ -358,7 +358,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | |||
358 | file->private_data = ofid; | 358 | file->private_data = ofid; |
359 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) | 359 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) |
360 | v9fs_cache_inode_set_cookie(inode, file); | 360 | v9fs_cache_inode_set_cookie(inode, file); |
361 | *opened |= FILE_CREATED; | 361 | file->f_mode |= FMODE_CREATED; |
362 | out: | 362 | out: |
363 | v9fs_put_acl(dacl, pacl); | 363 | v9fs_put_acl(dacl, pacl); |
364 | dput(res); | 364 | dput(res); |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index ad0bed99b1d5..38a63fff7903 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -507,7 +507,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, | |||
507 | dout("atomic_open finish_open on dn %p\n", dn); | 507 | dout("atomic_open finish_open on dn %p\n", dn); |
508 | if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) { | 508 | if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) { |
509 | ceph_init_inode_acls(d_inode(dentry), &acls); | 509 | ceph_init_inode_acls(d_inode(dentry), &acls); |
510 | *opened |= FILE_CREATED; | 510 | file->f_mode |= FMODE_CREATED; |
511 | } | 511 | } |
512 | err = finish_open(file, dentry, ceph_open, opened); | 512 | err = finish_open(file, dentry, ceph_open, opened); |
513 | } | 513 | } |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index ddae52bd1993..21d7e393900e 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -539,7 +539,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, | |||
539 | } | 539 | } |
540 | 540 | ||
541 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | 541 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) |
542 | *opened |= FILE_CREATED; | 542 | file->f_mode |= FMODE_CREATED; |
543 | 543 | ||
544 | rc = finish_open(file, direntry, generic_file_open, opened); | 544 | rc = finish_open(file, direntry, generic_file_open, opened); |
545 | if (rc) { | 545 | if (rc) { |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 56231b31f806..d4bdcf51e6cb 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -508,7 +508,7 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry, | |||
508 | goto no_open; | 508 | goto no_open; |
509 | 509 | ||
510 | /* Only creates */ | 510 | /* Only creates */ |
511 | *opened |= FILE_CREATED; | 511 | file->f_mode |= FMODE_CREATED; |
512 | 512 | ||
513 | if (fc->no_create) | 513 | if (fc->no_create) |
514 | goto mknod; | 514 | goto mknod; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 67c588edf8d8..4aba00a6004b 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -767,7 +767,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, | |||
767 | mark_inode_dirty(inode); | 767 | mark_inode_dirty(inode); |
768 | d_instantiate(dentry, inode); | 768 | d_instantiate(dentry, inode); |
769 | if (file) { | 769 | if (file) { |
770 | *opened |= FILE_CREATED; | 770 | file->f_mode |= FMODE_CREATED; |
771 | error = finish_open(file, dentry, gfs2_open_common, opened); | 771 | error = finish_open(file, dentry, gfs2_open_common, opened); |
772 | } | 772 | } |
773 | gfs2_glock_dq_uninit(ghs); | 773 | gfs2_glock_dq_uninit(ghs); |
diff --git a/fs/namei.c b/fs/namei.c index 8a1ae074c1c1..4bd7cc0d7522 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -3061,7 +3061,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
3061 | * permission here. | 3061 | * permission here. |
3062 | */ | 3062 | */ |
3063 | int acc_mode = op->acc_mode; | 3063 | int acc_mode = op->acc_mode; |
3064 | if (*opened & FILE_CREATED) { | 3064 | if (file->f_mode & FMODE_CREATED) { |
3065 | WARN_ON(!(open_flag & O_CREAT)); | 3065 | WARN_ON(!(open_flag & O_CREAT)); |
3066 | fsnotify_create(dir, dentry); | 3066 | fsnotify_create(dir, dentry); |
3067 | acc_mode = 0; | 3067 | acc_mode = 0; |
@@ -3077,7 +3077,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry, | |||
3077 | dput(dentry); | 3077 | dput(dentry); |
3078 | dentry = file->f_path.dentry; | 3078 | dentry = file->f_path.dentry; |
3079 | } | 3079 | } |
3080 | if (*opened & FILE_CREATED) | 3080 | if (file->f_mode & FMODE_CREATED) |
3081 | fsnotify_create(dir, dentry); | 3081 | fsnotify_create(dir, dentry); |
3082 | if (unlikely(d_is_negative(dentry))) { | 3082 | if (unlikely(d_is_negative(dentry))) { |
3083 | error = -ENOENT; | 3083 | error = -ENOENT; |
@@ -3126,7 +3126,7 @@ static int lookup_open(struct nameidata *nd, struct path *path, | |||
3126 | if (unlikely(IS_DEADDIR(dir_inode))) | 3126 | if (unlikely(IS_DEADDIR(dir_inode))) |
3127 | return -ENOENT; | 3127 | return -ENOENT; |
3128 | 3128 | ||
3129 | *opened &= ~FILE_CREATED; | 3129 | file->f_mode &= ~FMODE_CREATED; |
3130 | dentry = d_lookup(dir, &nd->last); | 3130 | dentry = d_lookup(dir, &nd->last); |
3131 | for (;;) { | 3131 | for (;;) { |
3132 | if (!dentry) { | 3132 | if (!dentry) { |
@@ -3211,7 +3211,7 @@ no_open: | |||
3211 | 3211 | ||
3212 | /* Negative dentry, just create the file */ | 3212 | /* Negative dentry, just create the file */ |
3213 | if (!dentry->d_inode && (open_flag & O_CREAT)) { | 3213 | if (!dentry->d_inode && (open_flag & O_CREAT)) { |
3214 | *opened |= FILE_CREATED; | 3214 | file->f_mode |= FMODE_CREATED; |
3215 | audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE); | 3215 | audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE); |
3216 | if (!dir_inode->i_op->create) { | 3216 | if (!dir_inode->i_op->create) { |
3217 | error = -EACCES; | 3217 | error = -EACCES; |
@@ -3318,7 +3318,7 @@ static int do_last(struct nameidata *nd, | |||
3318 | if (error) | 3318 | if (error) |
3319 | goto out; | 3319 | goto out; |
3320 | 3320 | ||
3321 | if ((*opened & FILE_CREATED) || | 3321 | if ((file->f_mode & FMODE_CREATED) || |
3322 | !S_ISREG(file_inode(file)->i_mode)) | 3322 | !S_ISREG(file_inode(file)->i_mode)) |
3323 | will_truncate = false; | 3323 | will_truncate = false; |
3324 | 3324 | ||
@@ -3326,7 +3326,7 @@ static int do_last(struct nameidata *nd, | |||
3326 | goto opened; | 3326 | goto opened; |
3327 | } | 3327 | } |
3328 | 3328 | ||
3329 | if (*opened & FILE_CREATED) { | 3329 | if (file->f_mode & FMODE_CREATED) { |
3330 | /* Don't check for write permission, don't truncate */ | 3330 | /* Don't check for write permission, don't truncate */ |
3331 | open_flag &= ~O_TRUNC; | 3331 | open_flag &= ~O_TRUNC; |
3332 | will_truncate = false; | 3332 | will_truncate = false; |
@@ -3400,7 +3400,8 @@ finish_open_created: | |||
3400 | if (error) | 3400 | if (error) |
3401 | goto out; | 3401 | goto out; |
3402 | opened: | 3402 | opened: |
3403 | error = ima_file_check(file, op->acc_mode, *opened); | 3403 | error = ima_file_check(file, op->acc_mode, |
3404 | file->f_mode & FMODE_CREATED ? FILE_CREATED : 0); | ||
3404 | if (!error && will_truncate) | 3405 | if (!error && will_truncate) |
3405 | error = handle_truncate(file); | 3406 | error = handle_truncate(file); |
3406 | out: | 3407 | out: |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 7a9c14426855..0ac50983fc4e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1461,6 +1461,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1461 | struct inode *inode; | 1461 | struct inode *inode; |
1462 | unsigned int lookup_flags = 0; | 1462 | unsigned int lookup_flags = 0; |
1463 | bool switched = false; | 1463 | bool switched = false; |
1464 | int created = 0; | ||
1464 | int err; | 1465 | int err; |
1465 | 1466 | ||
1466 | /* Expect a negative dentry */ | 1467 | /* Expect a negative dentry */ |
@@ -1521,7 +1522,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1521 | goto out; | 1522 | goto out; |
1522 | 1523 | ||
1523 | trace_nfs_atomic_open_enter(dir, ctx, open_flags); | 1524 | trace_nfs_atomic_open_enter(dir, ctx, open_flags); |
1524 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, opened); | 1525 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr, &created); |
1526 | if (created) | ||
1527 | file->f_mode |= FMODE_CREATED; | ||
1525 | if (IS_ERR(inode)) { | 1528 | if (IS_ERR(inode)) { |
1526 | err = PTR_ERR(inode); | 1529 | err = PTR_ERR(inode); |
1527 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); | 1530 | trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ed45090e4df6..2c4df0ffbca1 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2951,7 +2951,7 @@ static int _nfs4_do_open(struct inode *dir, | |||
2951 | } | 2951 | } |
2952 | } | 2952 | } |
2953 | if (opened && opendata->file_created) | 2953 | if (opened && opendata->file_created) |
2954 | *opened |= FILE_CREATED; | 2954 | *opened = 1; |
2955 | 2955 | ||
2956 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) { | 2956 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) { |
2957 | *ctx_th = opendata->f_attr.mdsthreshold; | 2957 | *ctx_th = opendata->f_attr.mdsthreshold; |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 05f34726e29c..ca668c7e48a7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -149,6 +149,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, | |||
149 | #define FMODE_CAN_WRITE ((__force fmode_t)0x40000) | 149 | #define FMODE_CAN_WRITE ((__force fmode_t)0x40000) |
150 | 150 | ||
151 | #define FMODE_OPENED ((__force fmode_t)0x80000) | 151 | #define FMODE_OPENED ((__force fmode_t)0x80000) |
152 | #define FMODE_CREATED ((__force fmode_t)0x100000) | ||
152 | 153 | ||
153 | /* File was opened by fanotify and shouldn't generate fanotify events */ | 154 | /* File was opened by fanotify and shouldn't generate fanotify events */ |
154 | #define FMODE_NONOTIFY ((__force fmode_t)0x4000000) | 155 | #define FMODE_NONOTIFY ((__force fmode_t)0x4000000) |