return 0;
}
+/*
+ * Bounce buffering dio reads need a user context to copy back the data.
+ * Use an ioend to provide that.
+ */
+static void
+xfs_dio_read_bounce_submit_io(
+ const struct iomap_iter *iter,
+ struct bio *bio,
+ loff_t file_offset)
+{
+ iomap_init_ioend(iter->inode, bio, file_offset, IOMAP_IOEND_DIRECT);
+ bio->bi_end_io = xfs_end_bio;
+ submit_bio(bio);
+}
+
+static const struct iomap_dio_ops xfs_dio_read_bounce_ops = {
+ .submit_io = xfs_dio_read_bounce_submit_io,
+ .bio_set = &iomap_ioend_bioset,
+};
+
STATIC ssize_t
xfs_file_dio_read(
struct kiocb *iocb,
struct iov_iter *to)
{
struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp));
+ unsigned int dio_flags = 0;
+ const struct iomap_dio_ops *dio_ops = NULL;
ssize_t ret;
trace_xfs_file_direct_read(iocb, to);
ret = xfs_ilock_iocb(iocb, XFS_IOLOCK_SHARED);
if (ret)
return ret;
- ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, 0, NULL, 0);
+ if (mapping_stable_writes(iocb->ki_filp->f_mapping)) {
+ dio_ops = &xfs_dio_read_bounce_ops;
+ dio_flags |= IOMAP_DIO_BOUNCE;
+ }
+ ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, dio_ops, dio_flags,
+ NULL, 0);
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return ret;
xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
iolock = XFS_IOLOCK_SHARED;
}
+ if (mapping_stable_writes(iocb->ki_filp->f_mapping))
+ dio_flags |= IOMAP_DIO_BOUNCE;
trace_xfs_file_direct_write(iocb, from);
ret = iomap_dio_rw(iocb, from, ops, dops, dio_flags, ac, 0);
out_unlock:
{
unsigned int iolock = XFS_IOLOCK_SHARED;
ssize_t ret, ocount = iov_iter_count(from);
+ unsigned int dio_flags = 0;
const struct iomap_ops *dops;
/*
}
trace_xfs_file_direct_write(iocb, from);
- ret = iomap_dio_rw(iocb, from, dops, &xfs_dio_write_ops,
- 0, NULL, 0);
+ if (mapping_stable_writes(iocb->ki_filp->f_mapping))
+ dio_flags |= IOMAP_DIO_BOUNCE;
+ ret = iomap_dio_rw(iocb, from, dops, &xfs_dio_write_ops, dio_flags,
+ NULL, 0);
/*
* The retry mechanism is based on the ->iomap_begin method returning
if (flags & IOMAP_DIO_FORCE_WAIT)
inode_dio_wait(VFS_I(ip));
+ if (mapping_stable_writes(iocb->ki_filp->f_mapping))
+ flags |= IOMAP_DIO_BOUNCE;
+
trace_xfs_file_direct_write(iocb, from);
ret = iomap_dio_rw(iocb, from, &xfs_direct_write_iomap_ops,
&xfs_dio_write_ops, flags, NULL, 0);