Merge tag 'metag-for-v4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan...
[linux-2.6-block.git] / fs / fuse / file.c
index e1afdd7abf90114fffd61da6bcfcc77916afb950..5ef05b5c4cff86e9353a0594f0faadc1ab8612f5 100644 (file)
@@ -1145,13 +1145,11 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
        struct file *file = iocb->ki_filp;
        struct address_space *mapping = file->f_mapping;
-       size_t count = iov_iter_count(from);
        ssize_t written = 0;
        ssize_t written_buffered = 0;
        struct inode *inode = mapping->host;
        ssize_t err;
        loff_t endbyte = 0;
-       loff_t pos = iocb->ki_pos;
 
        if (get_fuse_conn(inode)->writeback_cache) {
                /* Update size (EOF optimization) and mode (SUID clearing) */
@@ -1167,14 +1165,10 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        /* We can write back this queue in page reclaim */
        current->backing_dev_info = inode_to_bdi(inode);
 
-       err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
-       if (err)
-               goto out;
-
-       if (count == 0)
+       err = generic_write_checks(iocb, from);
+       if (err <= 0)
                goto out;
 
-       iov_iter_truncate(from, count);
        err = file_remove_suid(file);
        if (err)
                goto out;
@@ -1183,7 +1177,8 @@ 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))
                        goto out;
@@ -1209,9 +1204,9 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
                written += written_buffered;
                iocb->ki_pos = pos + written_buffered;
        } else {
-               written = fuse_perform_write(file, mapping, from, pos);
+               written = fuse_perform_write(file, mapping, from, iocb->ki_pos);
                if (written >= 0)
-                       iocb->ki_pos = pos + written;
+                       iocb->ki_pos += written;
        }
 out:
        current->backing_dev_info = NULL;
@@ -1412,7 +1407,6 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
        struct fuse_io_priv io = { .async = 0, .file = file };
-       size_t count = iov_iter_count(from);
        ssize_t res;
 
        if (is_bad_inode(inode))
@@ -1420,11 +1414,9 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
 
        /* Don't allow parallel writes to the same file */
        mutex_lock(&inode->i_mutex);
-       res = generic_write_checks(file, &iocb->ki_pos, &count, 0);
-       if (!res) {
-               iov_iter_truncate(from, count);
+       res = generic_write_checks(iocb, from);
+       if (res > 0)
                res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE);
-       }
        fuse_invalidate_attr(inode);
        if (res > 0)
                fuse_write_update_size(inode, iocb->ki_pos);
@@ -2782,8 +2774,7 @@ static inline loff_t fuse_round_up(loff_t off)
 }
 
 static ssize_t
-fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
-                       loff_t offset)
+fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
 {
        DECLARE_COMPLETION_ONSTACK(wait);
        ssize_t ret = 0;
@@ -2800,15 +2791,15 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
        inode = file->f_mapping->host;
        i_size = i_size_read(inode);
 
-       if ((rw == READ) && (offset > i_size))
+       if ((iov_iter_rw(iter) == READ) && (offset > i_size))
                return 0;
 
        /* optimization for short read */
-       if (async_dio && rw != WRITE && offset + count > i_size) {
+       if (async_dio && iov_iter_rw(iter) != WRITE && offset + count > i_size) {
                if (offset >= i_size)
                        return 0;
-               count = min_t(loff_t, count, fuse_round_up(i_size - offset));
-               iov_iter_truncate(iter, count);
+               iov_iter_truncate(iter, fuse_round_up(i_size - offset));
+               count = iov_iter_count(iter);
        }
 
        io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
@@ -2819,7 +2810,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
        io->bytes = -1;
        io->size = 0;
        io->offset = offset;
-       io->write = (rw == WRITE);
+       io->write = (iov_iter_rw(iter) == WRITE);
        io->err = 0;
        io->file = file;
        /*
@@ -2834,19 +2825,15 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
         * to wait on real async I/O requests, so we must submit this request
         * synchronously.
         */
-       if (!is_sync_kiocb(iocb) && (offset + count > i_size) && rw == WRITE)
+       if (!is_sync_kiocb(iocb) && (offset + count > i_size) &&
+           iov_iter_rw(iter) == WRITE)
                io->async = false;
 
        if (io->async && is_sync_kiocb(iocb))
                io->done = &wait;
 
-       if (rw == WRITE) {
-               ret = generic_write_checks(file, &pos, &count, 0);
-               if (!ret) {
-                       iov_iter_truncate(iter, count);
-                       ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE);
-               }
-
+       if (iov_iter_rw(iter) == WRITE) {
+               ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE);
                fuse_invalidate_attr(inode);
        } else {
                ret = __fuse_direct_read(io, iter, &pos);
@@ -2865,7 +2852,7 @@ fuse_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter,
 
        kfree(io);
 
-       if (rw == WRITE) {
+       if (iov_iter_rw(iter) == WRITE) {
                if (ret > 0)
                        fuse_write_update_size(inode, pos);
                else if (ret < 0 && offset + count > i_size)