linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] iomap: add IOMAP_DIO_ALIGNED flag for btrfs
@ 2025-10-13  6:08 Qu Wenruo
  2025-10-13  6:33 ` Christoph Hellwig
  0 siblings, 1 reply; 4+ messages in thread
From: Qu Wenruo @ 2025-10-13  6:08 UTC (permalink / raw)
  To: linux-btrfs; +Cc: brauner, djwong, linux-xfs, linux-fsdevel

With the recent bs > ps support for btrfs, btrfs requires block
alignment for all of its bios.

However the current iomap_dio_bio_iter() calls bio_iov_iter_get_pages()
which only ensure alignment to bdev_logical_block_size().

In the real world it's mostly 512 or 4K, resulting some bio to be split
at page boundary, breaking the btrfs requirement.

To address this problem, introduce a new public iomap dio flag,
IOMAP_DIO_ALIGNED.

When calling __iomap_dio_rw() with that new flag, iomap_dio::flags will
also get that new flag, and iomap_dio_bio_iter() will take fs block size
into the calculation of the alignment, and pass it to
bio_iov_iter_get_pages() so that the bio will always be fs block
aligned.

For now only btrfs will utilize this flag, as btrfs needs to calculate
checksum for direct read.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/direct-io.c  | 4 ++--
 fs/iomap/direct-io.c  | 9 +++++++--
 include/linux/iomap.h | 7 +++++++
 3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/direct-io.c b/fs/btrfs/direct-io.c
index 802d4dbe5b38..15aff186642d 100644
--- a/fs/btrfs/direct-io.c
+++ b/fs/btrfs/direct-io.c
@@ -763,7 +763,7 @@ static ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter,
 	struct btrfs_dio_data data = { 0 };
 
 	return iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
-			    IOMAP_DIO_PARTIAL, &data, done_before);
+			    IOMAP_DIO_PARTIAL | IOMAP_DIO_ALIGNED, &data, done_before);
 }
 
 static struct iomap_dio *btrfs_dio_write(struct kiocb *iocb, struct iov_iter *iter,
@@ -772,7 +772,7 @@ static struct iomap_dio *btrfs_dio_write(struct kiocb *iocb, struct iov_iter *it
 	struct btrfs_dio_data data = { 0 };
 
 	return __iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
-			    IOMAP_DIO_PARTIAL, &data, done_before);
+			    IOMAP_DIO_PARTIAL | IOMAP_DIO_ALIGNED, &data, done_before);
 }
 
 static ssize_t check_direct_IO(struct btrfs_fs_info *fs_info,
diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index 5d5d63efbd57..154bfc4ff3c4 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -336,6 +336,9 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
 	int nr_pages, ret = 0;
 	u64 copied = 0;
 	size_t orig_count;
+	const unsigned int alignment = (dio->flags & IOMAP_DIO_ALIGNED) ?
+		max(fs_block_size, bdev_logical_block_size(iomap->bdev)) :
+		bdev_logical_block_size(iomap->bdev);
 
 	if ((pos | length) & (bdev_logical_block_size(iomap->bdev) - 1))
 		return -EINVAL;
@@ -433,8 +436,7 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
 		bio->bi_private = dio;
 		bio->bi_end_io = iomap_dio_bio_end_io;
 
-		ret = bio_iov_iter_get_pages(bio, dio->submit.iter,
-				bdev_logical_block_size(iomap->bdev) - 1);
+		ret = bio_iov_iter_get_pages(bio, dio->submit.iter, alignment - 1);
 		if (unlikely(ret)) {
 			/*
 			 * We have to stop part way through an IO. We must fall
@@ -639,6 +641,9 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 	if (iocb->ki_flags & IOCB_NOWAIT)
 		iomi.flags |= IOMAP_NOWAIT;
 
+	if (dio_flags & IOMAP_DIO_ALIGNED)
+		dio->flags |= IOMAP_DIO_ALIGNED;
+
 	if (iov_iter_rw(iter) == READ) {
 		/* reads can always complete inline */
 		dio->flags |= IOMAP_DIO_INLINE_COMP;
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 73dceabc21c8..9bbd36fd69cf 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -518,6 +518,13 @@ struct iomap_dio_ops {
  */
 #define IOMAP_DIO_PARTIAL		(1 << 2)
 
+/*
+ * Ensure each bio is aligned to fs block size.
+ *
+ * For filesystems which need to calculate/verify data checksum for each data bio.
+ */
+#define IOMAP_DIO_ALIGNED		(1 << 3)
+
 ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 		const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
 		unsigned int dio_flags, void *private, size_t done_before);
-- 
2.50.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-10-13  7:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-13  6:08 [PATCH] iomap: add IOMAP_DIO_ALIGNED flag for btrfs Qu Wenruo
2025-10-13  6:33 ` Christoph Hellwig
2025-10-13  7:06   ` Qu Wenruo
2025-10-13  7:11     ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).