]> git.ipfire.org Git - thirdparty/linux.git/blobdiff - fs/iomap.c
Merge branch 'work.iov_iter' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[thirdparty/linux.git] / fs / iomap.c
index b9f74803e56c08ce9655c96c5c32260e0e925efd..47d29ccffaef4d0f1aeb48c174dc3898344cd9b1 100644 (file)
@@ -856,6 +856,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
        struct bio *bio;
        bool need_zeroout = false;
        int nr_pages, ret;
+       size_t copied = 0;
 
        if ((pos | length | align) & ((1 << blkbits) - 1))
                return -EINVAL;
@@ -867,7 +868,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
                /*FALLTHRU*/
        case IOMAP_UNWRITTEN:
                if (!(dio->flags & IOMAP_DIO_WRITE)) {
-                       iov_iter_zero(length, dio->submit.iter);
+                       length = iov_iter_zero(length, dio->submit.iter);
                        dio->size += length;
                        return length;
                }
@@ -904,8 +905,11 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
        }
 
        do {
-               if (dio->error)
+               size_t n;
+               if (dio->error) {
+                       iov_iter_revert(dio->submit.iter, copied);
                        return 0;
+               }
 
                bio = bio_alloc(GFP_KERNEL, nr_pages);
                bio_set_dev(bio, iomap->bdev);
@@ -918,20 +922,24 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
                ret = bio_iov_iter_get_pages(bio, &iter);
                if (unlikely(ret)) {
                        bio_put(bio);
-                       return ret;
+                       return copied ? copied : ret;
                }
 
+               n = bio->bi_iter.bi_size;
                if (dio->flags & IOMAP_DIO_WRITE) {
                        bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_SYNC | REQ_IDLE);
-                       task_io_account_write(bio->bi_iter.bi_size);
+                       task_io_account_write(n);
                } else {
                        bio_set_op_attrs(bio, REQ_OP_READ, 0);
                        if (dio->flags & IOMAP_DIO_DIRTY)
                                bio_set_pages_dirty(bio);
                }
 
-               dio->size += bio->bi_iter.bi_size;
-               pos += bio->bi_iter.bi_size;
+               iov_iter_advance(dio->submit.iter, n);
+
+               dio->size += n;
+               pos += n;
+               copied += n;
 
                nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
 
@@ -947,9 +955,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
                if (pad)
                        iomap_dio_zero(dio, iomap, pos, fs_block_size - pad);
        }
-
-       iov_iter_advance(dio->submit.iter, length);
-       return length;
+       return copied;
 }
 
 ssize_t