mirror O_APPEND and O_DIRECT into iocb->ki_flags
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 9 Apr 2015 17:52:01 +0000 (13:52 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 12 Apr 2015 02:30:22 +0000 (22:30 -0400)
... avoiding write_iter/fcntl races.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/aio.c
fs/btrfs/file.c
fs/ceph/file.c
fs/ext4/file.c
fs/fuse/file.c
fs/gfs2/file.c
fs/nfs/file.c
fs/ocfs2/file.c
fs/xfs/xfs_file.c
include/linux/fs.h
mm/filemap.c

index 5785c4b58fea5ffdeae17d43b6b00df2572dc638..e976185c8e5b3a8dbad29af7ff17fca08e50088f 100644 (file)
--- 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,
        }
        req->common.ki_pos = iocb->aio_offset;
        req->common.ki_complete = aio_complete;
-       req->common.ki_flags = 0;
+       req->common.ki_flags = iocb_flags(req->common.ki_filp);
 
        if (iocb->aio_flags & IOCB_FLAG_RESFD) {
                /*
index c64d11c41eeb5524d281bc93dcae259412e59159..faa7d390841b9a245a95ffb4944d515c3c486cbf 100644 (file)
@@ -1794,7 +1794,7 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
        if (sync)
                atomic_inc(&BTRFS_I(inode)->sync_writers);
 
-       if (file->f_flags & O_DIRECT) {
+       if (iocb->ki_flags & IOCB_DIRECT) {
                num_written = __btrfs_direct_write(iocb, from, pos);
        } else {
                num_written = __btrfs_buffered_write(file, from, pos);
index 3f0b9339d823447621181eafb87e980f6d210b78..b9b8eb225f66ead124f4a1484cfc5b76dbb8d2fb 100644 (file)
@@ -457,7 +457,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *i,
        if (ret < 0)
                return ret;
 
-       if (file->f_flags & O_DIRECT) {
+       if (iocb->ki_flags & IOCB_DIRECT) {
                while (iov_iter_count(i)) {
                        size_t start;
                        ssize_t n;
@@ -828,7 +828,7 @@ again:
                return ret;
 
        if ((got & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)) == 0 ||
-           (iocb->ki_filp->f_flags & O_DIRECT) ||
+           (iocb->ki_flags & IOCB_DIRECT) ||
            (fi->flags & CEPH_F_SYNC)) {
 
                dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n",
@@ -995,12 +995,12 @@ retry_snap:
             inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
 
        if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
-           (file->f_flags & O_DIRECT) || (fi->flags & CEPH_F_SYNC)) {
+           (iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC)) {
                struct iov_iter data;
                mutex_unlock(&inode->i_mutex);
                /* we might need to revert back to that point */
                data = *from;
-               if (file->f_flags & O_DIRECT)
+               if (iocb->ki_flags & IOCB_DIRECT)
                        written = ceph_sync_direct_write(iocb, &data, pos);
                else
                        written = ceph_sync_write(iocb, &data, pos);
index c10785f10d1d95bd76342cff13e13fb471684a4f..53bbc0b1995f5a02545494fa131461e6b7240ac2 100644 (file)
@@ -95,7 +95,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct inode *inode = file_inode(iocb->ki_filp);
        struct mutex *aio_mutex = NULL;
        struct blk_plug plug;
-       int o_direct = io_is_direct(file);
+       int o_direct = iocb->ki_flags & IOCB_DIRECT;
        int overwrite = 0;
        ssize_t ret;
 
@@ -106,7 +106,7 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (o_direct &&
            ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) &&
            !is_sync_kiocb(iocb) &&
-           (file->f_flags & O_APPEND ||
+           (iocb->ki_flags & IOCB_APPEND ||
             ext4_unaligned_aio(inode, from, iocb->ki_pos))) {
                aio_mutex = ext4_aio_mutex(inode);
                mutex_lock(aio_mutex);
index b86c8e08399a8a5dc52a797c1ec6c944dfcc04e9..5ef05b5c4cff86e9353a0594f0faadc1ab8612f5 100644 (file)
@@ -1177,7 +1177,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (err)
                goto out;
 
-       if (file->f_flags & O_DIRECT) {
+       if (iocb->ki_flags & IOCB_DIRECT) {
                loff_t pos = iocb->ki_pos;
                written = generic_file_direct_write(iocb, from, pos);
                if (written < 0 || !iov_iter_count(from))
index 614bb42cb7e1b765ce982ad61c0c51780e93247b..08329afa13396b78f236cb7c59984428f9c31986 100644 (file)
@@ -709,7 +709,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 
        gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from));
 
-       if (file->f_flags & O_APPEND) {
+       if (iocb->ki_flags & IOCB_APPEND) {
                struct gfs2_holder gh;
 
                ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
index f6a3adedf0270b7edabb23511746a14bbe6d000c..14364dc001f7cb19ac69b464b0b974ef06a8af54 100644 (file)
@@ -170,7 +170,7 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
        struct inode *inode = file_inode(iocb->ki_filp);
        ssize_t result;
 
-       if (iocb->ki_filp->f_flags & O_DIRECT)
+       if (iocb->ki_flags & IOCB_DIRECT)
                return nfs_file_direct_read(iocb, to, iocb->ki_pos);
 
        dprintk("NFS: read(%pD2, %zu@%lu)\n",
@@ -680,7 +680,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
        if (result)
                return result;
 
-       if (file->f_flags & O_DIRECT)
+       if (iocb->ki_flags & IOCB_DIRECT)
                return nfs_file_direct_write(iocb, from, pos);
 
        dprintk("NFS: write(%pD2, %zu@%Ld)\n",
@@ -692,7 +692,7 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
        /*
         * O_APPEND implies that we must revalidate the file length.
         */
-       if (file->f_flags & O_APPEND) {
+       if (iocb->ki_flags & IOCB_APPEND) {
                result = nfs_revalidate_file_size(inode, file);
                if (result)
                        goto out;
index b93919f50f0ff73440b189c142728221358ff4a2..cd37f6cd4d5163fa6fe6f899889ffed403c9bc1f 100644 (file)
@@ -2274,8 +2274,8 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb,
        if (count == 0)
                return 0;
 
-       appending = file->f_flags & O_APPEND ? 1 : 0;
-       direct_io = file->f_flags & O_DIRECT ? 1 : 0;
+       appending = iocb->ki_flags & IOCB_APPEND ? 1 : 0;
+       direct_io = iocb->ki_flags & IOCB_DIRECT ? 1 : 0;
 
        mutex_lock(&inode->i_mutex);
 
@@ -2429,7 +2429,7 @@ relock:
 
 out_dio:
        /* buffered aio wouldn't have proper lock coverage today */
-       BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
+       BUG_ON(ret == -EIOCBQUEUED && !(iocb->ki_flags & IOCB_DIRECT));
 
        if (unlikely(written <= 0))
                goto no_sync;
@@ -2546,7 +2546,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
         * buffered reads protect themselves in ->readpage().  O_DIRECT reads
         * need locks to protect pending reads from racing with truncate.
         */
-       if (filp->f_flags & O_DIRECT) {
+       if (iocb->ki_flags & IOCB_DIRECT) {
                have_alloc_sem = 1;
                ocfs2_iocb_set_sem_locked(iocb);
 
@@ -2580,7 +2580,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb,
        trace_generic_file_aio_read_ret(ret);
 
        /* buffered aio wouldn't have proper lock coverage today */
-       BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT));
+       BUG_ON(ret == -EIOCBQUEUED && !(iocb->ki_flags & IOCB_DIRECT));
 
        /* see ocfs2_file_write_iter */
        if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) {
index 28d157807b42a18d02e71d38f2d8c2e969570dd0..1f12ad0a8585b3d0f0788cfe5b88b6ab662a1547 100644 (file)
@@ -279,7 +279,7 @@ xfs_file_read_iter(
 
        XFS_STATS_INC(xs_read_calls);
 
-       if (unlikely(file->f_flags & O_DIRECT))
+       if (unlikely(iocb->ki_flags & IOCB_DIRECT))
                ioflags |= XFS_IO_ISDIRECT;
        if (file->f_mode & FMODE_NOCMTIME)
                ioflags |= XFS_IO_INVIS;
@@ -804,7 +804,7 @@ xfs_file_write_iter(
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
                return -EIO;
 
-       if (unlikely(file->f_flags & O_DIRECT))
+       if (unlikely(iocb->ki_flags & IOCB_DIRECT))
                ret = xfs_file_dio_aio_write(iocb, from);
        else
                ret = xfs_file_buffered_aio_write(iocb, from);
index b4aa400ac723243f420ebd4c099a0f624478bd07..b1d7db28c13c90b80e2e02954e753f31cb5b0f27 100644 (file)
@@ -315,6 +315,8 @@ struct address_space;
 struct writeback_control;
 
 #define IOCB_EVENTFD           (1 << 0)
+#define IOCB_APPEND            (1 << 1)
+#define IOCB_DIRECT            (1 << 2)
 
 struct kiocb {
        struct file             *ki_filp;
@@ -329,10 +331,13 @@ static inline bool is_sync_kiocb(struct kiocb *kiocb)
        return kiocb->ki_complete == NULL;
 }
 
+static inline int iocb_flags(struct file *file);
+
 static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
 {
        *kiocb = (struct kiocb) {
                .ki_filp = filp,
+               .ki_flags = iocb_flags(filp),
        };
 }
 
@@ -2779,6 +2784,16 @@ static inline bool io_is_direct(struct file *filp)
        return (filp->f_flags & O_DIRECT) || IS_DAX(file_inode(filp));
 }
 
+static inline int iocb_flags(struct file *file)
+{
+       int res = 0;
+       if (file->f_flags & O_APPEND)
+               res |= IOCB_APPEND;
+       if (io_is_direct(file))
+               res |= IOCB_DIRECT;
+       return res;
+}
+
 static inline ino_t parent_ino(struct dentry *dentry)
 {
        ino_t res;
index 243997a26e7cebbc52bbc4347555bc50f374a193..405de370e657196b18db64bd0f3b6a34526ab498 100644 (file)
@@ -1694,7 +1694,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
        loff_t *ppos = &iocb->ki_pos;
        loff_t pos = *ppos;
 
-       if (io_is_direct(file)) {
+       if (iocb->ki_flags & IOCB_DIRECT) {
                struct address_space *mapping = file->f_mapping;
                struct inode *inode = mapping->host;
                size_t count = iov_iter_count(iter);
@@ -2271,7 +2271,7 @@ inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from)
                return 0;
 
        /* FIXME: this is for backwards compatibility with 2.4 */
-       if (file->f_flags & O_APPEND)
+       if (iocb->ki_flags & IOCB_APPEND)
                iocb->ki_pos = i_size_read(inode);
 
        pos = iocb->ki_pos;
@@ -2545,7 +2545,7 @@ ssize_t __generic_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (err)
                goto out;
 
-       if (io_is_direct(file)) {
+       if (iocb->ki_flags & IOCB_DIRECT) {
                loff_t pos, endbyte;
 
                written = generic_file_direct_write(iocb, from, iocb->ki_pos);