aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-04-09 13:52:01 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-04-11 22:30:22 -0400
commit2ba48ce513c4e545318d22b138861d5876edf906 (patch)
tree0e2a5130ead5c71f0b079b1acd620fba98f99256
parent3309dd04cbcd2cdad168485af5cf3576b5051e49 (diff)
mirror O_APPEND and O_DIRECT into iocb->ki_flags
... avoiding write_iter/fcntl races. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/aio.c2
-rw-r--r--fs/btrfs/file.c2
-rw-r--r--fs/ceph/file.c8
-rw-r--r--fs/ext4/file.c4
-rw-r--r--fs/fuse/file.c2
-rw-r--r--fs/gfs2/file.c2
-rw-r--r--fs/nfs/file.c6
-rw-r--r--fs/ocfs2/file.c10
-rw-r--r--fs/xfs/xfs_file.c4
-rw-r--r--include/linux/fs.h15
-rw-r--r--mm/filemap.c6
11 files changed, 38 insertions, 23 deletions
diff --git a/fs/aio.c b/fs/aio.c
index 5785c4b58fea..e976185c8e5b 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1502,7 +1502,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
1502 } 1502 }
1503 req->common.ki_pos = iocb->aio_offset; 1503 req->common.ki_pos = iocb->aio_offset;
1504 req->common.ki_complete = aio_complete; 1504 req->common.ki_complete = aio_complete;
1505 req->common.ki_flags = 0; 1505 req->common.ki_flags = iocb_flags(req->common.ki_filp);
1506 1506
1507 if (iocb->aio_flags & IOCB_FLAG_RESFD) { 1507 if (iocb->aio_flags & IOCB_FLAG_RESFD) {
1508 /* 1508 /*
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index c64d11c41eeb..faa7d390841b 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1794,7 +1794,7 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
1794 if (sync) 1794 if (sync)
1795 atomic_inc(&BTRFS_I(inode)->sync_writers); 1795 atomic_inc(&BTRFS_I(inode)->sync_writers);
1796 1796
1797 if (file->f_flags & O_DIRECT) { 1797 if (iocb->ki_flags & IOCB_DIRECT) {
1798 num_written = __btrfs_direct_write(iocb, from, pos); 1798 num_written = __btrfs_direct_write(iocb, from, pos);
1799 } else { 1799 } else {
1800 num_written = __btrfs_buffered_write(file, from, pos); 1800 num_written = __btrfs_buffered_write(file, from, pos);
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 3f0b9339d823..b9b8eb225f66 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -457,7 +457,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
457 if (ret < 0) 457 if (ret < 0)
458 return ret; 458 return ret;
459 459
460 if (file->f_flags & O_DIRECT) { 460 if (iocb->ki_flags & IOCB_DIRECT) {
461 while (iov_iter_count(i)) { 461 while (iov_iter_count(i)) {
462 size_t start; 462 size_t start;
463 ssize_t n; 463 ssize_t n;
@@ -828,7 +828,7 @@ again:
828 return ret; 828 return ret;
829 829
830 if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 || 830 if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
831 (iocb->ki_filp->f_flags & O_DIRECT) || 831 (iocb->ki_flags & IOCB_DIRECT) ||
832 (fi->flags & CEPH_F_SYNC)) { 832 (fi->flags & CEPH_F_SYNC)) {
833 833
834 dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n", 834 dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n",
@@ -995,12 +995,12 @@ retry_snap:
995 inode, ceph_vinop(inode), pos, count, ceph_cap_string(got)); 995 inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
996 996
997 if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 || 997 if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
998 (file->f_flags & O_DIRECT) || (fi->flags & CEPH_F_SYNC)) { 998 (iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC)) {
999 struct iov_iter data; 999 struct iov_iter data;
1000 mutex_unlock(&inode->i_mutex); 1000 mutex_unlock(&inode->i_mutex);
1001 /* we might need to revert back to that point */ 1001 /* we might need to revert back to that point */
1002 data = *from; 1002 data = *from;
1003 if (file->f_flags & O_DIRECT) 1003 if (iocb->ki_flags & IOCB_DIRECT)
1004 written = ceph_sync_direct_write(iocb, &data, pos); 1004 written = ceph_sync_direct_write(iocb, &data, pos);
1005 else 1005 else
1006 written = ceph_sync_write(iocb, &data, pos); 1006 written = ceph_sync_write(iocb, &data, pos);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index c10785f10d1d..53bbc0b1995f 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -95,7 +95,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
95 struct inode *inode = file_inode(iocb->ki_filp); 95 struct inode *inode = file_inode(iocb->ki_filp);
96 struct mutex *aio_mutex = NULL; 96 struct mutex *aio_mutex = NULL;
97 struct blk_plug plug; 97 struct blk_plug plug;
98 int o_direct = io_is_direct(file); 98 int o_direct = iocb->ki_flags & IOCB_DIRECT;
99 int overwrite = 0; 99 int overwrite = 0;
100 ssize_t ret; 100 ssize_t ret;
101 101
@@ -106,7 +106,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
106 if (o_direct && 106 if (o_direct &&
107 ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && 107 ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
108 !is_sync_kiocb(iocb) && 108 !is_sync_kiocb(iocb) &&
109 (file->f_flags & O_APPEND || 109 (iocb->ki_flags & IOCB_APPEND ||
110 ext4_unaligned_aio(inode, from, iocb->ki_pos))) { 110 ext4_unaligned_aio(inode, from, iocb->ki_pos))) {
111 aio_mutex = ext4_aio_mutex(inode); 111 aio_mutex = ext4_aio_mutex(inode);
112 mutex_lock(aio_mutex); 112 mutex_lock(aio_mutex);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index b86c8e08399a..5ef05b5c4cff 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1177,7 +1177,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
1177 if (err) 1177 if (err)
1178 goto out; 1178 goto out;
1179 1179
1180 if (file->f_flags & O_DIRECT) { 1180 if (iocb->ki_flags & IOCB_DIRECT) {
1181 loff_t pos = iocb->ki_pos; 1181 loff_t pos = iocb->ki_pos;
1182 written = generic_file_direct_write(iocb, from, pos); 1182 written = generic_file_direct_write(iocb, from, pos);
1183 if (written < 0 || !iov_iter_count(from)) 1183 if (written < 0 || !iov_iter_count(from))
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 614bb42cb7e1..08329afa1339 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -709,7 +709,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
709 709
710 gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from)); 710 gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));
711 711
712 if (file->f_flags & O_APPEND) { 712 if (iocb->ki_flags & IOCB_APPEND) {
713 struct gfs2_holder gh; 713 struct gfs2_holder gh;
714 714
715 ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); 715 ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f6a3adedf027..14364dc001f7 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -170,7 +170,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
170 struct inode *inode = file_inode(iocb->ki_filp); 170 struct inode *inode = file_inode(iocb->ki_filp);
171 ssize_t result; 171 ssize_t result;
172 172
173 if (iocb->ki_filp->f_flags & O_DIRECT) 173 if (iocb->ki_flags & IOCB_DIRECT)
174 return nfs_file_direct_read(iocb, to, iocb->ki_pos); 174 return nfs_file_direct_read(iocb, to, iocb->ki_pos);
175 175
176 dprintk("NFS: read(%pD2, %zu@%lu)\n", 176 dprintk("NFS: read(%pD2, %zu@%lu)\n",
@@ -680,7 +680,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
680 if (result) 680 if (result)
681 return result; 681 return result;
682 682
683 if (file->f_flags & O_DIRECT) 683 if (iocb->ki_flags & IOCB_DIRECT)
684 return nfs_file_direct_write(iocb, from, pos); 684 return nfs_file_direct_write(iocb, from, pos);
685 685
686 dprintk("NFS: write(%pD2, %zu@%Ld)\n", 686 dprintk("NFS: write(%pD2, %zu@%Ld)\n",
@@ -692,7 +692,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
692 /* 692 /*
693 * O_APPEND implies that we must revalidate the file length. 693 * O_APPEND implies that we must revalidate the file length.
694 */ 694 */
695 if (file->f_flags & O_APPEND) { 695 if (iocb->ki_flags & IOCB_APPEND) {
696 result = nfs_revalidate_file_size(inode, file); 696 result = nfs_revalidate_file_size(inode, file);
697 if (result) 697 if (result)
698 goto out; 698 goto out;
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index b93919f50f0f..cd37f6cd4d51 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -2274,8 +2274,8 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
2274 if (count == 0) 2274 if (count == 0)
2275 return 0; 2275 return 0;
2276 2276
2277 appending = file->f_flags & O_APPEND ? 1 : 0; 2277 appending = iocb->ki_flags & IOCB_APPEND ? 1 : 0;
2278 direct_io = file->f_flags & O_DIRECT ? 1 : 0; 2278 direct_io = iocb->ki_flags & IOCB_DIRECT ? 1 : 0;
2279 2279
2280 mutex_lock(&inode->i_mutex); 2280 mutex_lock(&inode->i_mutex);
2281 2281
@@ -2429,7 +2429,7 @@ relock:
2429 2429
2430out_dio: 2430out_dio:
2431 /* buffered aio wouldn't have proper lock coverage today */ 2431 /* buffered aio wouldn't have proper lock coverage today */
2432 BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT)); 2432 BUG_ON(ret == -EIOCBQUEUED && !(iocb->ki_flags & IOCB_DIRECT));
2433 2433
2434 if (unlikely(written <= 0)) 2434 if (unlikely(written <= 0))
2435 goto no_sync; 2435 goto no_sync;
@@ -2546,7 +2546,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
2546 * buffered reads protect themselves in ->readpage(). O_DIRECT reads 2546 * buffered reads protect themselves in ->readpage(). O_DIRECT reads
2547 * need locks to protect pending reads from racing with truncate. 2547 * need locks to protect pending reads from racing with truncate.
2548 */ 2548 */
2549 if (filp->f_flags & O_DIRECT) { 2549 if (iocb->ki_flags & IOCB_DIRECT) {
2550 have_alloc_sem = 1; 2550 have_alloc_sem = 1;
2551 ocfs2_iocb_set_sem_locked(iocb); 2551 ocfs2_iocb_set_sem_locked(iocb);
2552 2552
@@ -2580,7 +2580,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
2580 trace_generic_file_aio_read_ret(ret); 2580 trace_generic_file_aio_read_ret(ret);
2581 2581
2582 /* buffered aio wouldn't have proper lock coverage today */ 2582 /* buffered aio wouldn't have proper lock coverage today */
2583 BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT)); 2583 BUG_ON(ret == -EIOCBQUEUED && !(iocb->ki_flags & IOCB_DIRECT));
2584 2584
2585 /* see ocfs2_file_write_iter */ 2585 /* see ocfs2_file_write_iter */
2586 if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) { 2586 if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) {
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 28d157807b42..1f12ad0a8585 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -279,7 +279,7 @@ xfs_file_read_iter(
279 279
280 XFS_STATS_INC(xs_read_calls); 280 XFS_STATS_INC(xs_read_calls);
281 281
282 if (unlikely(file->f_flags & O_DIRECT)) 282 if (unlikely(iocb->ki_flags & IOCB_DIRECT))
283 ioflags |= XFS_IO_ISDIRECT; 283 ioflags |= XFS_IO_ISDIRECT;
284 if (file->f_mode & FMODE_NOCMTIME) 284 if (file->f_mode & FMODE_NOCMTIME)
285 ioflags |= XFS_IO_INVIS; 285 ioflags |= XFS_IO_INVIS;
@@ -804,7 +804,7 @@ xfs_file_write_iter(
804 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) 804 if (XFS_FORCED_SHUTDOWN(ip->i_mount))
805 return -EIO; 805 return -EIO;
806 806
807 if (unlikely(file->f_flags & O_DIRECT)) 807 if (unlikely(iocb->ki_flags & IOCB_DIRECT))
808 ret = xfs_file_dio_aio_write(iocb, from); 808 ret = xfs_file_dio_aio_write(iocb, from);
809 else 809 else
810 ret = xfs_file_buffered_aio_write(iocb, from); 810 ret = xfs_file_buffered_aio_write(iocb, from);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b4aa400ac723..b1d7db28c13c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -315,6 +315,8 @@ struct address_space;
315struct writeback_control; 315struct writeback_control;
316 316
317#define IOCB_EVENTFD (1 << 0) 317#define IOCB_EVENTFD (1 << 0)
318#define IOCB_APPEND (1 << 1)
319#define IOCB_DIRECT (1 << 2)
318 320
319struct kiocb { 321struct kiocb {
320 struct file *ki_filp; 322 struct file *ki_filp;
@@ -329,10 +331,13 @@ static inline bool is_sync_kiocb(struct kiocb *kiocb)
329 return kiocb->ki_complete == NULL; 331 return kiocb->ki_complete == NULL;
330} 332}
331 333
334static inline int iocb_flags(struct file *file);
335
332static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) 336static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
333{ 337{
334 *kiocb = (struct kiocb) { 338 *kiocb = (struct kiocb) {
335 .ki_filp = filp, 339 .ki_filp = filp,
340 .ki_flags = iocb_flags(filp),
336 }; 341 };
337} 342}
338 343
@@ -2779,6 +2784,16 @@ static inline bool io_is_direct(struct file *filp)
2779 return (filp->f_flags & O_DIRECT) || IS_DAX(file_inode(filp)); 2784 return (filp->f_flags & O_DIRECT) || IS_DAX(file_inode(filp));
2780} 2785}
2781 2786
2787static inline int iocb_flags(struct file *file)
2788{
2789 int res = 0;
2790 if (file->f_flags & O_APPEND)
2791 res |= IOCB_APPEND;
2792 if (io_is_direct(file))
2793 res |= IOCB_DIRECT;
2794 return res;
2795}
2796
2782static inline ino_t parent_ino(struct dentry *dentry) 2797static inline ino_t parent_ino(struct dentry *dentry)
2783{ 2798{
2784 ino_t res; 2799 ino_t res;
diff --git a/mm/filemap.c b/mm/filemap.c
index 243997a26e7c..405de370e657 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1694,7 +1694,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
1694 loff_t *ppos = &iocb->ki_pos; 1694 loff_t *ppos = &iocb->ki_pos;
1695 loff_t pos = *ppos; 1695 loff_t pos = *ppos;
1696 1696
1697 if (io_is_direct(file)) { 1697 if (iocb->ki_flags & IOCB_DIRECT) {
1698 struct address_space *mapping = file->f_mapping; 1698 struct address_space *mapping = file->f_mapping;
1699 struct inode *inode = mapping->host; 1699 struct inode *inode = mapping->host;
1700 size_t count = iov_iter_count(iter); 1700 size_t count = iov_iter_count(iter);
@@ -2271,7 +2271,7 @@ inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
2271 return 0; 2271 return 0;
2272 2272
2273 /* FIXME: this is for backwards compatibility with 2.4 */ 2273 /* FIXME: this is for backwards compatibility with 2.4 */
2274 if (file->f_flags & O_APPEND) 2274 if (iocb->ki_flags & IOCB_APPEND)
2275 iocb->ki_pos = i_size_read(inode); 2275 iocb->ki_pos = i_size_read(inode);
2276 2276
2277 pos = iocb->ki_pos; 2277 pos = iocb->ki_pos;
@@ -2545,7 +2545,7 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
2545 if (err) 2545 if (err)
2546 goto out; 2546 goto out;
2547 2547
2548 if (io_is_direct(file)) { 2548 if (iocb->ki_flags & IOCB_DIRECT) {
2549 loff_t pos, endbyte; 2549 loff_t pos, endbyte;
2550 2550
2551 written = generic_file_direct_write(iocb, from, iocb->ki_pos); 2551 written = generic_file_direct_write(iocb, from, iocb->ki_pos);