Commit f550ee9b authored by Jan Kara's avatar Jan Kara Committed by Darrick J. Wong

iomap: Do not create fake iter in iomap_dio_bio_actor()

iomap_dio_bio_actor() copies iter to a local variable and then limits it
to a file extent we have mapped. When IO is submitted,
iomap_dio_bio_actor() advances the original iter while the copied iter
is advanced inside bio_iov_iter_get_pages(). This logic is non-obvious
especially because both iters still point to same shared structures
(such as pipe info) so if iov_iter_advance() changes anything in the
shared structure, this scheme breaks. Let's just truncate and reexpand
the original iter as needed instead of playing games with copying iters
and keeping them in sync.
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 419e9c38
...@@ -201,12 +201,12 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, ...@@ -201,12 +201,12 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev)); unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev));
unsigned int fs_block_size = i_blocksize(inode), pad; unsigned int fs_block_size = i_blocksize(inode), pad;
unsigned int align = iov_iter_alignment(dio->submit.iter); unsigned int align = iov_iter_alignment(dio->submit.iter);
struct iov_iter iter;
struct bio *bio; struct bio *bio;
bool need_zeroout = false; bool need_zeroout = false;
bool use_fua = false; bool use_fua = false;
int nr_pages, ret = 0; int nr_pages, ret = 0;
size_t copied = 0; size_t copied = 0;
size_t orig_count;
if ((pos | length | align) & ((1 << blkbits) - 1)) if ((pos | length | align) & ((1 << blkbits) - 1))
return -EINVAL; return -EINVAL;
...@@ -236,15 +236,18 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, ...@@ -236,15 +236,18 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
} }
/* /*
* Operate on a partial iter trimmed to the extent we were called for. * Save the original count and trim the iter to just the extent we
* We'll update the iter in the dio once we're done with this extent. * are operating on right now. The iter will be re-expanded once
* we are done.
*/ */
iter = *dio->submit.iter; orig_count = iov_iter_count(dio->submit.iter);
iov_iter_truncate(&iter, length); iov_iter_truncate(dio->submit.iter, length);
nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES); nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES);
if (nr_pages <= 0) if (nr_pages <= 0) {
return nr_pages; ret = nr_pages;
goto out;
}
if (need_zeroout) { if (need_zeroout) {
/* zero out from the start of the block to the write offset */ /* zero out from the start of the block to the write offset */
...@@ -257,7 +260,8 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, ...@@ -257,7 +260,8 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
size_t n; size_t n;
if (dio->error) { if (dio->error) {
iov_iter_revert(dio->submit.iter, copied); iov_iter_revert(dio->submit.iter, copied);
return 0; copied = ret = 0;
goto out;
} }
bio = bio_alloc(GFP_KERNEL, nr_pages); bio = bio_alloc(GFP_KERNEL, nr_pages);
...@@ -268,7 +272,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, ...@@ -268,7 +272,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
bio->bi_private = dio; bio->bi_private = dio;
bio->bi_end_io = iomap_dio_bio_end_io; bio->bi_end_io = iomap_dio_bio_end_io;
ret = bio_iov_iter_get_pages(bio, &iter); ret = bio_iov_iter_get_pages(bio, dio->submit.iter);
if (unlikely(ret)) { if (unlikely(ret)) {
/* /*
* We have to stop part way through an IO. We must fall * We have to stop part way through an IO. We must fall
...@@ -294,13 +298,11 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, ...@@ -294,13 +298,11 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
bio_set_pages_dirty(bio); bio_set_pages_dirty(bio);
} }
iov_iter_advance(dio->submit.iter, n);
dio->size += n; dio->size += n;
pos += n; pos += n;
copied += n; copied += n;
nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES); nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES);
iomap_dio_submit_bio(dio, iomap, bio); iomap_dio_submit_bio(dio, iomap, bio);
} while (nr_pages); } while (nr_pages);
...@@ -318,6 +320,9 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, ...@@ -318,6 +320,9 @@ iomap_dio_bio_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);
} }
out:
/* Undo iter limitation to current extent */
iov_iter_reexpand(dio->submit.iter, orig_count - copied);
if (copied) if (copied)
return copied; return copied;
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment