Skip to content

Commit f550ee9

Browse files
jankaradjwong
authored andcommitted
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: Jan Kara <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent 419e9c3 commit f550ee9

File tree

1 file changed

+18
-13
lines changed

1 file changed

+18
-13
lines changed

fs/iomap/direct-io.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,12 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
201201
unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev));
202202
unsigned int fs_block_size = i_blocksize(inode), pad;
203203
unsigned int align = iov_iter_alignment(dio->submit.iter);
204-
struct iov_iter iter;
205204
struct bio *bio;
206205
bool need_zeroout = false;
207206
bool use_fua = false;
208207
int nr_pages, ret = 0;
209208
size_t copied = 0;
209+
size_t orig_count;
210210

211211
if ((pos | length | align) & ((1 << blkbits) - 1))
212212
return -EINVAL;
@@ -236,15 +236,18 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
236236
}
237237

238238
/*
239-
* Operate on a partial iter trimmed to the extent we were called for.
240-
* We'll update the iter in the dio once we're done with this extent.
239+
* Save the original count and trim the iter to just the extent we
240+
* are operating on right now. The iter will be re-expanded once
241+
* we are done.
241242
*/
242-
iter = *dio->submit.iter;
243-
iov_iter_truncate(&iter, length);
243+
orig_count = iov_iter_count(dio->submit.iter);
244+
iov_iter_truncate(dio->submit.iter, length);
244245

245-
nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
246-
if (nr_pages <= 0)
247-
return nr_pages;
246+
nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES);
247+
if (nr_pages <= 0) {
248+
ret = nr_pages;
249+
goto out;
250+
}
248251

249252
if (need_zeroout) {
250253
/* 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,
257260
size_t n;
258261
if (dio->error) {
259262
iov_iter_revert(dio->submit.iter, copied);
260-
return 0;
263+
copied = ret = 0;
264+
goto out;
261265
}
262266

263267
bio = bio_alloc(GFP_KERNEL, nr_pages);
@@ -268,7 +272,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
268272
bio->bi_private = dio;
269273
bio->bi_end_io = iomap_dio_bio_end_io;
270274

271-
ret = bio_iov_iter_get_pages(bio, &iter);
275+
ret = bio_iov_iter_get_pages(bio, dio->submit.iter);
272276
if (unlikely(ret)) {
273277
/*
274278
* 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,
294298
bio_set_pages_dirty(bio);
295299
}
296300

297-
iov_iter_advance(dio->submit.iter, n);
298-
299301
dio->size += n;
300302
pos += n;
301303
copied += n;
302304

303-
nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
305+
nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES);
304306
iomap_dio_submit_bio(dio, iomap, bio);
305307
} while (nr_pages);
306308

@@ -318,6 +320,9 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
318320
if (pad)
319321
iomap_dio_zero(dio, iomap, pos, fs_block_size - pad);
320322
}
323+
out:
324+
/* Undo iter limitation to current extent */
325+
iov_iter_reexpand(dio->submit.iter, orig_count - copied);
321326
if (copied)
322327
return copied;
323328
return ret;

0 commit comments

Comments
 (0)