|
@@ -848,6 +848,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
|
|
struct bio *bio;
|
|
struct bio *bio;
|
|
bool need_zeroout = false;
|
|
bool need_zeroout = false;
|
|
int nr_pages, ret;
|
|
int nr_pages, ret;
|
|
|
|
+ size_t copied = 0;
|
|
|
|
|
|
if ((pos | length | align) & ((1 << blkbits) - 1))
|
|
if ((pos | length | align) & ((1 << blkbits) - 1))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -859,7 +860,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
|
|
/*FALLTHRU*/
|
|
/*FALLTHRU*/
|
|
case IOMAP_UNWRITTEN:
|
|
case IOMAP_UNWRITTEN:
|
|
if (!(dio->flags & IOMAP_DIO_WRITE)) {
|
|
if (!(dio->flags & IOMAP_DIO_WRITE)) {
|
|
- iov_iter_zero(length, dio->submit.iter);
|
|
|
|
|
|
+ length = iov_iter_zero(length, dio->submit.iter);
|
|
dio->size += length;
|
|
dio->size += length;
|
|
return length;
|
|
return length;
|
|
}
|
|
}
|
|
@@ -896,8 +897,11 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
|
|
}
|
|
}
|
|
|
|
|
|
do {
|
|
do {
|
|
- if (dio->error)
|
|
|
|
|
|
+ size_t n;
|
|
|
|
+ if (dio->error) {
|
|
|
|
+ iov_iter_revert(dio->submit.iter, copied);
|
|
return 0;
|
|
return 0;
|
|
|
|
+ }
|
|
|
|
|
|
bio = bio_alloc(GFP_KERNEL, nr_pages);
|
|
bio = bio_alloc(GFP_KERNEL, nr_pages);
|
|
bio_set_dev(bio, iomap->bdev);
|
|
bio_set_dev(bio, iomap->bdev);
|
|
@@ -910,20 +914,24 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
|
|
ret = bio_iov_iter_get_pages(bio, &iter);
|
|
ret = bio_iov_iter_get_pages(bio, &iter);
|
|
if (unlikely(ret)) {
|
|
if (unlikely(ret)) {
|
|
bio_put(bio);
|
|
bio_put(bio);
|
|
- return ret;
|
|
|
|
|
|
+ return copied ? copied : ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ n = bio->bi_iter.bi_size;
|
|
if (dio->flags & IOMAP_DIO_WRITE) {
|
|
if (dio->flags & IOMAP_DIO_WRITE) {
|
|
bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_SYNC | REQ_IDLE);
|
|
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 {
|
|
} else {
|
|
bio_set_op_attrs(bio, REQ_OP_READ, 0);
|
|
bio_set_op_attrs(bio, REQ_OP_READ, 0);
|
|
if (dio->flags & IOMAP_DIO_DIRTY)
|
|
if (dio->flags & IOMAP_DIO_DIRTY)
|
|
bio_set_pages_dirty(bio);
|
|
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);
|
|
nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
|
|
|
|
|
|
@@ -939,9 +947,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
|
|
if (pad)
|
|
if (pad)
|
|
iomap_dio_zero(dio, iomap, pos, fs_block_size - pad);
|
|
iomap_dio_zero(dio, iomap, pos, fs_block_size - pad);
|
|
}
|
|
}
|
|
-
|
|
|
|
- iov_iter_advance(dio->submit.iter, length);
|
|
|
|
- return length;
|
|
|
|
|
|
+ return copied;
|
|
}
|
|
}
|
|
|
|
|
|
ssize_t
|
|
ssize_t
|