[PATCHv4 9/9] fs: add support for dma aligned direct-io

Keith Busch
2022-05-26T01:08:50Z

From: Keith Busch <kbusch@kernel.org>

Use the address alignment requirements from the hardware for direct io
instead of requiring addresses be aligned to the block size.

Signed-off-by: Keith Busch <kbusch@kernel.org>
---
fs/direct-io.c | 11 +++++++----
fs/iomap/direct-io.c | 3 ++-
2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/fs/direct-io.c b/fs/direct-io.c
index 840752006f60..64cc176be60c 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1131,7 +1131,7 @@ ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
struct dio_submit sdio = { 0, };
struct buffer_head map_bh = { 0, };
struct blk_plug plug;
- unsigned long align = offset | iov_iter_alignment(iter);
+ unsigned long align = iov_iter_alignment(iter);

/*
* Avoid references to bdev if not absolutely needed to give
@@ -1165,11 +1165,14 @@ ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
goto fail_dio;
}

- if (align & blocksize_mask) {
- if (bdev)
+ if ((offset | align) & blocksize_mask) {
+ if (bdev) {
blkbits = blksize_bits(bdev_logical_block_size(bdev));
+ if (align & bdev_dma_alignment(bdev))
+ goto fail_dio;
+ }
blocksize_mask = (1 << blkbits) - 1;
- if (align & blocksize_mask)
+ if ((offset | count) & blocksize_mask)
goto fail_dio;
}

diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index 80f9b047aa1b..0256d28baa8e 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -244,7 +244,8 @@ static loff_t iomap_dio_bio_iter(const struct iomap_iter *iter,
size_t copied = 0;
size_t orig_count;

- if ((pos | length | align) & ((1 << blkbits) - 1))
+ if ((pos | length) & ((1 << blkbits) - 1) ||
+ align & bdev_dma_alignment(iomap->bdev))
return -EINVAL;

if (iomap->type == IOMAP_UNWRITTEN) {
--
2.30.2