Skip to content

Commit 3373503

Browse files
Christoph Hellwigaxboe
authored andcommitted
xfs: use bounce buffering direct I/O when the device requires stable pages
Fix direct I/O on devices that require stable pages by asking iomap to bounce buffer. To support this, ioends are used for direct reads in this case to provide a user context for copying data back from the bounce buffer. This fixes qemu when used on devices using T10 protection information and probably other cases like iSCSI using data digests. 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 c9d1148 commit 3373503

2 files changed

Lines changed: 44 additions & 5 deletions

File tree

fs/xfs/xfs_aops.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ xfs_ioend_put_open_zones(
103103
* IO write completion.
104104
*/
105105
STATIC void
106-
xfs_end_ioend(
106+
xfs_end_ioend_write(
107107
struct iomap_ioend *ioend)
108108
{
109109
struct xfs_inode *ip = XFS_I(ioend->io_inode);
@@ -202,7 +202,11 @@ xfs_end_io(
202202
io_list))) {
203203
list_del_init(&ioend->io_list);
204204
iomap_ioend_try_merge(ioend, &tmp);
205-
xfs_end_ioend(ioend);
205+
if (bio_op(&ioend->io_bio) == REQ_OP_READ)
206+
iomap_finish_ioends(ioend,
207+
blk_status_to_errno(ioend->io_bio.bi_status));
208+
else
209+
xfs_end_ioend_write(ioend);
206210
cond_resched();
207211
}
208212
}

fs/xfs/xfs_file.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,34 @@ xfs_ilock_iocb_for_write(
224224
return 0;
225225
}
226226

227+
/*
228+
* Bounce buffering dio reads need a user context to copy back the data.
229+
* Use an ioend to provide that.
230+
*/
231+
static void
232+
xfs_dio_read_bounce_submit_io(
233+
const struct iomap_iter *iter,
234+
struct bio *bio,
235+
loff_t file_offset)
236+
{
237+
iomap_init_ioend(iter->inode, bio, file_offset, IOMAP_IOEND_DIRECT);
238+
bio->bi_end_io = xfs_end_bio;
239+
submit_bio(bio);
240+
}
241+
242+
static const struct iomap_dio_ops xfs_dio_read_bounce_ops = {
243+
.submit_io = xfs_dio_read_bounce_submit_io,
244+
.bio_set = &iomap_ioend_bioset,
245+
};
246+
227247
STATIC ssize_t
228248
xfs_file_dio_read(
229249
struct kiocb *iocb,
230250
struct iov_iter *to)
231251
{
232252
struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp));
253+
unsigned int dio_flags = 0;
254+
const struct iomap_dio_ops *dio_ops = NULL;
233255
ssize_t ret;
234256

235257
trace_xfs_file_direct_read(iocb, to);
@@ -242,7 +264,12 @@ xfs_file_dio_read(
242264
ret = xfs_ilock_iocb(iocb, XFS_IOLOCK_SHARED);
243265
if (ret)
244266
return ret;
245-
ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, 0, NULL, 0);
267+
if (mapping_stable_writes(iocb->ki_filp->f_mapping)) {
268+
dio_ops = &xfs_dio_read_bounce_ops;
269+
dio_flags |= IOMAP_DIO_BOUNCE;
270+
}
271+
ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, dio_ops, dio_flags,
272+
NULL, 0);
246273
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
247274

248275
return ret;
@@ -703,6 +730,8 @@ xfs_file_dio_write_aligned(
703730
xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
704731
iolock = XFS_IOLOCK_SHARED;
705732
}
733+
if (mapping_stable_writes(iocb->ki_filp->f_mapping))
734+
dio_flags |= IOMAP_DIO_BOUNCE;
706735
trace_xfs_file_direct_write(iocb, from);
707736
ret = iomap_dio_rw(iocb, from, ops, dops, dio_flags, ac, 0);
708737
out_unlock:
@@ -750,6 +779,7 @@ xfs_file_dio_write_atomic(
750779
{
751780
unsigned int iolock = XFS_IOLOCK_SHARED;
752781
ssize_t ret, ocount = iov_iter_count(from);
782+
unsigned int dio_flags = 0;
753783
const struct iomap_ops *dops;
754784

755785
/*
@@ -777,8 +807,10 @@ xfs_file_dio_write_atomic(
777807
}
778808

779809
trace_xfs_file_direct_write(iocb, from);
780-
ret = iomap_dio_rw(iocb, from, dops, &xfs_dio_write_ops,
781-
0, NULL, 0);
810+
if (mapping_stable_writes(iocb->ki_filp->f_mapping))
811+
dio_flags |= IOMAP_DIO_BOUNCE;
812+
ret = iomap_dio_rw(iocb, from, dops, &xfs_dio_write_ops, dio_flags,
813+
NULL, 0);
782814

783815
/*
784816
* The retry mechanism is based on the ->iomap_begin method returning
@@ -867,6 +899,9 @@ xfs_file_dio_write_unaligned(
867899
if (flags & IOMAP_DIO_FORCE_WAIT)
868900
inode_dio_wait(VFS_I(ip));
869901

902+
if (mapping_stable_writes(iocb->ki_filp->f_mapping))
903+
flags |= IOMAP_DIO_BOUNCE;
904+
870905
trace_xfs_file_direct_write(iocb, from);
871906
ret = iomap_dio_rw(iocb, from, &xfs_direct_write_iomap_ops,
872907
&xfs_dio_write_ops, flags, NULL, 0);

0 commit comments

Comments
 (0)