Skip to content

Commit c9d1148

Browse files
Christoph Hellwigaxboe
authored andcommitted
iomap: add a flag to bounce buffer direct I/O
Add a new flag that request bounce buffering for direct I/O. This is needed to provide the stable pages requirement requested by devices that need to calculate checksums or parity over the data and allows file systems to properly work with things like T10 protection information. The implementation just calls out to the new bio bounce buffering helpers to allocate a bounce buffer, which is used for I/O and to copy to/from it. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Tested-by: Anuj Gupta <anuj20.g@samsung.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent d969bd7 commit c9d1148

2 files changed

Lines changed: 29 additions & 10 deletions

File tree

fs/iomap/direct-io.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,11 @@ static void __iomap_dio_bio_end_io(struct bio *bio, bool inline_completion)
215215
{
216216
struct iomap_dio *dio = bio->bi_private;
217217

218-
if (dio->flags & IOMAP_DIO_USER_BACKED) {
218+
if (dio->flags & IOMAP_DIO_BOUNCE) {
219+
bio_iov_iter_unbounce(bio, !!dio->error,
220+
dio->flags & IOMAP_DIO_USER_BACKED);
221+
bio_put(bio);
222+
} else if (dio->flags & IOMAP_DIO_USER_BACKED) {
219223
bio_check_pages_dirty(bio);
220224
} else {
221225
bio_release_pages(bio, false);
@@ -303,12 +307,16 @@ static ssize_t iomap_dio_bio_iter_one(struct iomap_iter *iter,
303307
struct iomap_dio *dio, loff_t pos, unsigned int alignment,
304308
blk_opf_t op)
305309
{
310+
unsigned int nr_vecs;
306311
struct bio *bio;
307312
ssize_t ret;
308313

309-
bio = iomap_dio_alloc_bio(iter, dio,
310-
bio_iov_vecs_to_alloc(dio->submit.iter, BIO_MAX_VECS),
311-
op);
314+
if (dio->flags & IOMAP_DIO_BOUNCE)
315+
nr_vecs = bio_iov_bounce_nr_vecs(dio->submit.iter, op);
316+
else
317+
nr_vecs = bio_iov_vecs_to_alloc(dio->submit.iter, BIO_MAX_VECS);
318+
319+
bio = iomap_dio_alloc_bio(iter, dio, nr_vecs, op);
312320
fscrypt_set_bio_crypt_ctx(bio, iter->inode,
313321
pos >> iter->inode->i_blkbits, GFP_KERNEL);
314322
bio->bi_iter.bi_sector = iomap_sector(&iter->iomap, pos);
@@ -317,7 +325,11 @@ static ssize_t iomap_dio_bio_iter_one(struct iomap_iter *iter,
317325
bio->bi_private = dio;
318326
bio->bi_end_io = iomap_dio_bio_end_io;
319327

320-
ret = bio_iov_iter_get_pages(bio, dio->submit.iter, alignment - 1);
328+
if (dio->flags & IOMAP_DIO_BOUNCE)
329+
ret = bio_iov_iter_bounce(bio, dio->submit.iter);
330+
else
331+
ret = bio_iov_iter_get_pages(bio, dio->submit.iter,
332+
alignment - 1);
321333
if (unlikely(ret))
322334
goto out_put_bio;
323335
ret = bio->bi_iter.bi_size;
@@ -333,7 +345,8 @@ static ssize_t iomap_dio_bio_iter_one(struct iomap_iter *iter,
333345

334346
if (dio->flags & IOMAP_DIO_WRITE)
335347
task_io_account_write(ret);
336-
else if (dio->flags & IOMAP_DIO_USER_BACKED)
348+
else if ((dio->flags & IOMAP_DIO_USER_BACKED) &&
349+
!(dio->flags & IOMAP_DIO_BOUNCE))
337350
bio_set_pages_dirty(bio);
338351

339352
/*
@@ -662,7 +675,7 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
662675
dio->i_size = i_size_read(inode);
663676
dio->dops = dops;
664677
dio->error = 0;
665-
dio->flags = 0;
678+
dio->flags = dio_flags & (IOMAP_DIO_FSBLOCK_ALIGNED | IOMAP_DIO_BOUNCE);
666679
dio->done_before = done_before;
667680

668681
dio->submit.iter = iter;
@@ -671,9 +684,6 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
671684
if (iocb->ki_flags & IOCB_NOWAIT)
672685
iomi.flags |= IOMAP_NOWAIT;
673686

674-
if (dio_flags & IOMAP_DIO_FSBLOCK_ALIGNED)
675-
dio->flags |= IOMAP_DIO_FSBLOCK_ALIGNED;
676-
677687
if (iov_iter_rw(iter) == READ) {
678688
if (iomi.pos >= dio->i_size)
679689
goto out_free_dio;

include/linux/iomap.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,15 @@ struct iomap_dio_ops {
562562
*/
563563
#define IOMAP_DIO_FSBLOCK_ALIGNED (1 << 3)
564564

565+
/*
566+
* Bounce buffer instead of using zero copy access.
567+
*
568+
* This is needed if the device needs stable data to checksum or generate
569+
* parity. The file system must hook into the I/O submission and offload
570+
* completions to user context for reads when this is set.
571+
*/
572+
#define IOMAP_DIO_BOUNCE (1 << 4)
573+
565574
ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
566575
const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
567576
unsigned int dio_flags, void *private, size_t done_before);

0 commit comments

Comments
 (0)