From 7c7f5e7431e4131c9cb3462bbd03d9db330bee45 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 11 Feb 2021 08:35:43 -0700 Subject: [PATCH] iomap: relax memory alignment restriction for O_DIRECT We currently require blocksize alignment for both position/length and the memory range. The latter is overly restrictive, as most devices can do DMA at a much finer granularity. Honor the bdev setting for DMA alignment, and use that for checking if we can process the IO or need to error it. Signed-off-by: Jens Axboe --- fs/iomap/direct-io.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c index 933f234d5bec..7f962011fa0c 100644 --- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -207,7 +207,8 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, { unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev)); unsigned int fs_block_size = i_blocksize(inode), pad; - unsigned int align = iov_iter_alignment(dio->submit.iter); + struct request_queue *q = bdev_get_queue(iomap->bdev); + unsigned long mem_align = q->dma_alignment; struct bio *bio; bool need_zeroout = false; bool use_fua = false; @@ -215,7 +216,9 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, size_t copied = 0; size_t orig_count; - if ((pos | length | align) & ((1 << blkbits) - 1)) + if ((pos | length) & ((1 << blkbits) - 1)) + return -EINVAL; + if (iov_iter_alignment(dio->submit.iter) & mem_align) return -EINVAL; if (iomap->type == IOMAP_UNWRITTEN) { @@ -237,8 +240,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, * cache flushes on IO completion. */ if (!(iomap->flags & (IOMAP_F_SHARED|IOMAP_F_DIRTY)) && - (dio->flags & IOMAP_DIO_WRITE_FUA) && - blk_queue_fua(bdev_get_queue(iomap->bdev))) + (dio->flags & IOMAP_DIO_WRITE_FUA) && blk_queue_fua(q)) use_fua = true; } -- 2.25.1