All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support
@ 2026-11-13  7:06 Mengmeng Zhao
  2026-11-13  7:06 ` [RFC PATCH v2 1/8] block: factor out bdev_init_dma_buf_io_ctx() Mengmeng Zhao
                   ` (7 more replies)
  0 siblings, 8 replies; 17+ messages in thread
From: Mengmeng Zhao @ 2026-11-13  7:06 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta, Nitesh Shetty, Jens Axboe,
	Sumit Semwal, christian.koenig, Philipp Stanner, Dan Williams,
	Matthew Wilcox, Jan Kara, Alexander Viro, Christian Brauner,
	tytso, Andreas Dilger, Baokun Li, Ojaswin Mujoo,
	Ritesh Harjani (IBM), Zhang Yi, asml.silence, Jonathan Corbet,
	Shuah Khan, Randy Dunlap
  Cc: linux-block, linux-kernel, linux-fsdevel, nvdimm, linux-ext4,
	linux-xfs, linux-doc, linux-media, dri-devel, linaro-mm-sig,
	Li Wang, Mengmeng Zhao

From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>

This series adds dma-buf read/write support for ext4. The dma-buf direct
I/O infrastructure allows dma-buf to be handed to file I/O as an iov_iter,
but currently it only supports raw block devices. To better serve the
GPU-NVMe direct access through normal filesystems, prior work for XFS has
been discussed at [1]. We are also interested in this field and working on
it [2].

The series is based on v7.4-rc2 (7475ea8b5861), which already contains
the common dma-buf direct I/O infrastructure, so it no longer depends on a
separate base tree.
Patches 1-2 carry the block and iomap prerequisites from Nitesh Shetty and
Anuj Gupta:
- bdev_init_dma_buf_io_ctx in patch 1 was moved to block/bdev.c as
suggested by Christoph.
- iomap_file_init_dma_buf_io_ctx from that series is not carried. ext4
calls bdev_init_dma_buf_io_ctx directly, and the capability check is
handled by FMODE_CAN_DMABUF_IO.

The design is:
- FMODE_CAN_DMABUF_IO marks files that can be the target of dma-buf I/O;
  a filesystem sets it at open time for inodes whose data can be reached
  without the page cache.
- dma_buf_io_ctx_create() refuses files that lack the flag and checks the
  current f_flags for O_DIRECT at registration.
- As F_SETFL can clear O_DIRECT afterwards, the paths that would fall back
  to buffered or copied I/O still need per-I/O checks in the callers.
- DAX is rechecked per I/O because it can be enabled after open.
- iomap must not ask for a buffered fallback on behalf of a dma-buf
  iterator: -ENOTBLK would be refused by the callers and would turn a
  failure into a successful transfer of zero bytes.

Patch 3 keeps the buffered fallback out of dma-buf I/O, patches 4-7 add
the refusals on the common paths and the capability flag, and patch 8
enables ext4.

Known limitation: 
1. A dma-buf read that reaches a hole or an unwritten
extent fails as a whole, even when an earlier mapped extent was already
transferred into the buffer, so the caller does not learn how much of the
dma-buf was filled.  Reporting the prefix instead would return a short
read, which callers cannot tell apart from the end of the file, and both
the buffered and the direct path normally hide holes by zero-filling.
Probing the mapping before submitting anything would fix it, but that
belongs to the common iomap series.

2. A refused dma-buf I/O reaches the caller as -EOPNOTSUPP through
iomap_dio_set_error(), which also emits an fserror notification even
though no I/O was submitted.  The report could be limited to requests
that did submit a bio, since iomap_dio_bio_iter() accounts dio->size at
submission time, but that changes what fserror users see for every iomap
filesystem, so this version leaves it as it is and asks the fserror
maintainers.

Testing:
- io_uring dma-buf suite (udmabuf + REGISTER_BUFFERS_UPDATE + READ_FIXED /
  WRITE_FIXED) against ext4 on a PCIe NVMe namespace, all passed.
- xfstests -g quick on ext4 devices: 689 tests ran, 11 reported  failures,
  all of them environment related, no failure is attributable to this 
  series.

[1] https://lore.kernel.org/linux-xfs/20261016091919.971295-1-anuj1072538@gmail.com/
[2] https://lore.kernel.org/all/20260908131545.105987-1-liwang@kylinos.cn/

Changelog:
==========
RFC v2:
- Rebased onto v7.4-rc2 and dropped the dependency on a separate base
  tree; the block and iomap prerequisites are patches 1-2.
- Added patch 3, which reports why a dma-buf direct I/O could not be done
  instead of asking for a buffered fallback that the callers refuse.
- Split the block changes: patch 4 only factors the integrity check
  into a helper, and patch 5 refuses a dma-buf bio in the inline
  encryption fallback, which is where the data pages are walked
  instead of in blk_mq_submit_bio(). (Christoph)
- Dropped the mm/filemap and iomap_file_buffered_write() guards; the
  refusals now happen in the callers that would fall back to buffered
  or copied I/O. (Christoph)
- Added the FMODE_CAN_DMABUF_IO flag and use it to check whether a bdev or
  a filesystem can do dma-buf I/O. (Christoph)

RFC v1:
- https://lore.kernel.org/all/20261105065847.196540-1-mengmeng.zhao@linux.dev/

Mengmeng Zhao (6):
  iomap: don't ask for a buffered fallback for dma-buf iterators
  blk-mq: factor out a dma-buf bio refusal helper
  blk-crypto: refuse dma-buf bios in the fallback path
  fs: add FMODE_CAN_DMABUF_IO and require it for dma-buf I/O contexts
  dax: refuse dma-buf iterators in dax_iomap_rw()
  ext4: support dma-buf registered buffers for direct I/O

Nitesh Shetty (2):
  block: factor out bdev_init_dma_buf_io_ctx()
  iomap: add dma-buf direct I/O guards

 .../filesystems/iomap/operations.rst          |  3 ++
 block/bdev.c                                  | 14 ++++++
 block/blk-crypto.c                            |  8 ++++
 block/blk-mq.c                                | 24 ++++++----
 block/fops.c                                  | 12 +----
 drivers/dma-buf/dma-buf-io.c                  | 13 ++++--
 fs/dax.c                                      |  4 ++
 fs/ext4/ext4.h                                | 11 +++++
 fs/ext4/file.c                                | 44 +++++++++++++++++--
 fs/iomap/direct-io.c                          | 41 +++++++++++++++--
 include/linux/blkdev.h                        |  8 ++++
 include/linux/fs.h                            |  8 +++-
 12 files changed, 159 insertions(+), 31 deletions(-)


base-commit: 7475ea8b58616b33c04afb976cf0fbaad9dd63fb
-- 
2.43.0


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

* [RFC PATCH v2 1/8] block: factor out bdev_init_dma_buf_io_ctx()
  2026-11-13  7:06 [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support Mengmeng Zhao
@ 2026-11-13  7:06 ` Mengmeng Zhao
  2026-11-13  7:24   ` sashiko-bot
  2026-11-13  7:06 ` [RFC PATCH v2 2/8] iomap: add dma-buf direct I/O guards Mengmeng Zhao
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Mengmeng Zhao @ 2026-11-13  7:06 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta, Nitesh Shetty, Jens Axboe,
	Sumit Semwal, christian.koenig, Philipp Stanner, Dan Williams,
	Matthew Wilcox, Jan Kara, Alexander Viro, Christian Brauner,
	tytso, Andreas Dilger, Baokun Li, Ojaswin Mujoo,
	Ritesh Harjani (IBM), Zhang Yi, asml.silence, Jonathan Corbet,
	Shuah Khan, Randy Dunlap
  Cc: linux-block, linux-kernel, linux-fsdevel, nvdimm, linux-ext4,
	linux-xfs, linux-doc, linux-media, dri-devel, linaro-mm-sig,
	Li Wang, Mengmeng Zhao

From: Nitesh Shetty <nj.shetty@samsung.com>

Factor the checks and the driver setup out of
blkdev_init_dma_buf_io_ctx() into an exported helper that takes the
block device as an argument, so callers can set up a dma-buf I/O
context for any block device.  The block device file operation becomes
a thin wrapper using file_bdev(), so its behavior is unchanged.

Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
Signed-off-by: Li Wang <liwang@kylinos.cn>
---
 block/bdev.c           | 14 ++++++++++++++
 block/fops.c           | 12 +-----------
 include/linux/blkdev.h |  3 +++
 3 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/block/bdev.c b/block/bdev.c
index f20f91b3176e..88e3f552f5d4 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -17,6 +17,7 @@
 #include <linux/blkpg.h>
 #include <linux/magic.h>
 #include <linux/buffer_head.h>
+#include <linux/dma-buf-io.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
 #include <linux/mount.h>
@@ -60,6 +61,19 @@ struct block_device *file_bdev(struct file *bdev_file)
 }
 EXPORT_SYMBOL(file_bdev);
 
+int bdev_init_dma_buf_io_ctx(struct file *file, struct block_device *bdev,
+			     struct dma_buf_io_ctx *ctx)
+{
+	if (!(file->f_flags & O_DIRECT))
+		return -EINVAL;
+	if (ctx->dmabuf->size > UINT_MAX)
+		return -EINVAL;
+	if (!bdev->bd_disk->fops->init_dma_buf_io_ctx)
+		return -EOPNOTSUPP;
+	return bdev->bd_disk->fops->init_dma_buf_io_ctx(bdev, ctx);
+}
+EXPORT_SYMBOL_GPL(bdev_init_dma_buf_io_ctx);
+
 static void bdev_write_inode(struct block_device *bdev)
 {
 	struct inode *inode = BD_INODE(bdev);
diff --git a/block/fops.c b/block/fops.c
index a0ccadaa9c79..86bf1f298b79 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -19,7 +19,6 @@
 #include <linux/iomap.h>
 #include <linux/module.h>
 #include <linux/io_uring/cmd.h>
-#include <linux/dma-buf-io.h>
 #include "blk.h"
 
 static inline struct inode *bdev_file_inode(struct file *file)
@@ -1009,16 +1008,7 @@ static int blkdev_mmap_prepare(struct vm_area_desc *desc)
 static int blkdev_init_dma_buf_io_ctx(struct file *file,
 				      struct dma_buf_io_ctx *ctx)
 {
-	struct block_device *bdev = file_bdev(file);
-	struct gendisk *disk = bdev->bd_disk;
-
-	if (!(file->f_flags & O_DIRECT))
-		return -EINVAL;
-	if (ctx->dmabuf->size > UINT_MAX)
-		return -EINVAL;
-	if (!disk->fops->init_dma_buf_io_ctx)
-		return -EOPNOTSUPP;
-	return disk->fops->init_dma_buf_io_ctx(bdev, ctx);
+	return bdev_init_dma_buf_io_ctx(file, file_bdev(file), ctx);
 }
 
 const struct file_operations def_blk_fops = {
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 215753171cef..b98f43478cc0 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1610,6 +1610,9 @@ struct block_device_operations {
 	int (*alternative_gpt_sector)(struct gendisk *disk, sector_t *sector);
 };
 
+int bdev_init_dma_buf_io_ctx(struct file *file, struct block_device *bdev,
+			     struct dma_buf_io_ctx *ctx);
+
 #ifdef CONFIG_COMPAT
 extern int blkdev_compat_ptr_ioctl(struct block_device *, blk_mode_t,
 				      unsigned int, unsigned long);
-- 
2.43.0


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

* [RFC PATCH v2 2/8] iomap: add dma-buf direct I/O guards
  2026-11-13  7:06 [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support Mengmeng Zhao
  2026-11-13  7:06 ` [RFC PATCH v2 1/8] block: factor out bdev_init_dma_buf_io_ctx() Mengmeng Zhao
@ 2026-11-13  7:06 ` Mengmeng Zhao
  2026-11-13  7:31   ` sashiko-bot
  2026-11-13  7:06 ` [RFC PATCH v2 3/8] iomap: don't ask for a buffered fallback for dma-buf iterators Mengmeng Zhao
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Mengmeng Zhao @ 2026-11-13  7:06 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta, Nitesh Shetty, Jens Axboe,
	Sumit Semwal, christian.koenig, Philipp Stanner, Dan Williams,
	Matthew Wilcox, Jan Kara, Alexander Viro, Christian Brauner,
	tytso, Andreas Dilger, Baokun Li, Ojaswin Mujoo,
	Ritesh Harjani (IBM), Zhang Yi, asml.silence, Jonathan Corbet,
	Shuah Khan, Randy Dunlap
  Cc: linux-block, linux-kernel, linux-fsdevel, nvdimm, linux-ext4,
	linux-xfs, linux-doc, linux-media, dri-devel, linaro-mm-sig,
	Li Wang, Mengmeng Zhao

From: Nitesh Shetty <nj.shetty@samsung.com>

Direct I/O copies data from the CPU in four places, zero-filling
holes, inline data, bounce pages and integrity metadata. A dma-buf
iterator has no pages behind it, so refuse it there.

Reads that encounter a hole or unwritten extent therefore return
-EOPNOTSUPP for the entire operation, even if I/O for an earlier
mapped extent was already submitted.

Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
Signed-off-by: Li Wang <liwang@kylinos.cn>
---
 fs/iomap/direct-io.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index ad041ac3252a..4a2b0f9df5a7 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -425,6 +425,11 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
 	unsigned int alignment;
 	ssize_t ret = 0;
 
+	/* integrity metadata is generated from the data pages */
+	if (iov_iter_is_dmabuf_map(dio->submit.iter) &&
+	    (iomap->flags & IOMAP_F_INTEGRITY))
+		return -EOPNOTSUPP;
+
 	/*
 	 * File systems that write out of place and always allocate new blocks
 	 * need each bio to be block aligned as that's the unit of allocation.
@@ -589,7 +594,13 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
 
 static int iomap_dio_hole_iter(struct iomap_iter *iter, struct iomap_dio *dio)
 {
-	loff_t copied = iov_iter_zero(iomap_length(iter), dio->submit.iter);
+	loff_t copied;
+
+	/* zero-filling walks the data pages */
+	if (iov_iter_is_dmabuf_map(dio->submit.iter))
+		return -EOPNOTSUPP;
+
+	copied = iov_iter_zero(iomap_length(iter), dio->submit.iter);
 
 	if (dio->flags & IOMAP_DIO_FSBLOCK_ALIGNED) {
 		loff_t aligned_copied = round_down(copied,
@@ -619,6 +630,10 @@ static int iomap_dio_inline_iter(struct iomap_iter *iomi, struct iomap_dio *dio)
 	loff_t pos = iomi->pos;
 	u64 copied;
 
+	/* inline data is copied from the CPU */
+	if (iov_iter_is_dmabuf_map(iter))
+		return -EOPNOTSUPP;
+
 	if (WARN_ON_ONCE(!inline_data))
 		return -EIO;
 
@@ -717,6 +732,10 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 	if (!iomi.len)
 		return NULL;
 
+	/* bouncing copies the data from the CPU */
+	if (iov_iter_is_dmabuf_map(iter) && (dio_flags & IOMAP_DIO_BOUNCE))
+		return ERR_PTR(-EOPNOTSUPP);
+
 	dio = kmalloc_obj(*dio);
 	if (!dio)
 		return ERR_PTR(-ENOMEM);
-- 
2.43.0


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

* [RFC PATCH v2 3/8] iomap: don't ask for a buffered fallback for dma-buf iterators
  2026-11-13  7:06 [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support Mengmeng Zhao
  2026-11-13  7:06 ` [RFC PATCH v2 1/8] block: factor out bdev_init_dma_buf_io_ctx() Mengmeng Zhao
  2026-11-13  7:06 ` [RFC PATCH v2 2/8] iomap: add dma-buf direct I/O guards Mengmeng Zhao
@ 2026-11-13  7:06 ` Mengmeng Zhao
  2026-11-13  7:28   ` sashiko-bot
  2026-11-13  7:06 ` [RFC PATCH v2 4/8] blk-mq: factor out a dma-buf bio refusal helper Mengmeng Zhao
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Mengmeng Zhao @ 2026-11-13  7:06 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta, Nitesh Shetty, Jens Axboe,
	Sumit Semwal, christian.koenig, Philipp Stanner, Dan Williams,
	Matthew Wilcox, Jan Kara, Alexander Viro, Christian Brauner,
	tytso, Andreas Dilger, Baokun Li, Ojaswin Mujoo,
	Ritesh Harjani (IBM), Zhang Yi, asml.silence, Jonathan Corbet,
	Shuah Khan, Randy Dunlap
  Cc: linux-block, linux-kernel, linux-fsdevel, nvdimm, linux-ext4,
	linux-xfs, linux-doc, linux-media, dri-devel, linaro-mm-sig,
	Li Wang, Mengmeng Zhao

From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>

-ENOTBLK tells the caller to retry with buffered I/O.  A dma-buf iterator
has no pages to copy, so the callers refuse that fallback, which would
turn the error into a successful transfer of zero bytes.

Report the reason instead: a busy folio becomes -EAGAIN, which the caller
can retry, any other invalidation failure keeps its error code, and
-ENOTBLK from ->iomap_begin() becomes -EOPNOTSUPP when nothing was
transferred.  A partial direct I/O still reports its progress.  Both
branches are reachable only through a file that opted into dma-buf I/O,
which ext4 does in the last patch.

Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
Signed-off-by: Li Wang <liwang@kylinos.cn>
---
 .../filesystems/iomap/operations.rst          |  3 +++
 fs/iomap/direct-io.c                          | 20 +++++++++++++++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/iomap/operations.rst b/Documentation/filesystems/iomap/operations.rst
index da982ca7e413..ca59716d225c 100644
--- a/Documentation/filesystems/iomap/operations.rst
+++ b/Documentation/filesystems/iomap/operations.rst
@@ -513,6 +513,9 @@ Return Values
    cache before issuing the I/O to storage.
    The ``->iomap_begin`` or ``->iomap_end`` functions may also return
    this value.
+   A dma-buf iterator cannot fall back to buffered I/O, so it gets
+   ``-EAGAIN`` when the failure is retryable and ``-EOPNOTSUPP`` when no
+   data could be transferred.
 
  * ``-EIOCBQUEUED``: The asynchronous direct I/O request has been
    queued and will be completed separately.
diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index 4a2b0f9df5a7..83fda6973bb9 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -706,7 +706,9 @@ static int iomap_dio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
  * completing partial requests asynchronously.
  *
  * Returns -ENOTBLK In case of a page invalidation invalidation failure for
- * writes.  The callers needs to fall back to buffered I/O in this case.
+ * writes.  The callers needs to fall back to buffered I/O in this case.  A
+ * dma-buf iterator cannot use that fallback, so it gets -EAGAIN when the
+ * failure is retryable and -EOPNOTSUPP when nothing was transferred.
  */
 struct iomap_dio *
 __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
@@ -806,7 +808,7 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 		/*
 		 * Try to invalidate cache pages for the range we are writing.
 		 * If this invalidation fails, let the caller fall back to
-		 * buffered I/O.
+		 * buffered I/O unless the iterator cannot be handled there.
 		 */
 		ret = kiocb_invalidate_pages(iocb, iomi.len);
 		if (ret) {
@@ -820,6 +822,14 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 					 * the caller tries again.
 					 */
 					ret = -EAGAIN;
+				} else if (iov_iter_is_dmabuf_map(iter)) {
+					/*
+					 * A dma-buf iterator has no buffered
+					 * fallback, so -ENOTBLK would hide the
+					 * real failure.  A busy folio is retryable.
+					 */
+					if (ret == -EBUSY)
+						ret = -EAGAIN;
 				} else {
 					/* fall back to buffered write */
 					ret = -ENOTBLK;
@@ -867,6 +877,12 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
 	if (ret == -ENOTBLK) {
 		wait_for_completion = true;
 		ret = 0;
+		/*
+		 * A dma-buf iterator cannot use that fallback.  Anything
+		 * already transferred is still reported as a short I/O.
+		 */
+		if (!dio->size && iov_iter_is_dmabuf_map(iter))
+			ret = -EOPNOTSUPP;
 	}
 	if (ret < 0)
 		iomap_dio_set_error(dio, ret);
-- 
2.43.0


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

* [RFC PATCH v2 4/8] blk-mq: factor out a dma-buf bio refusal helper
  2026-11-13  7:06 [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support Mengmeng Zhao
                   ` (2 preceding siblings ...)
  2026-11-13  7:06 ` [RFC PATCH v2 3/8] iomap: don't ask for a buffered fallback for dma-buf iterators Mengmeng Zhao
@ 2026-11-13  7:06 ` Mengmeng Zhao
  2026-11-13  7:12   ` sashiko-bot
  2026-11-13  7:06 ` [RFC PATCH v2 5/8] blk-crypto: refuse dma-buf bios in the fallback path Mengmeng Zhao
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Mengmeng Zhao @ 2026-11-13  7:06 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta, Nitesh Shetty, Jens Axboe,
	Sumit Semwal, christian.koenig, Philipp Stanner, Dan Williams,
	Matthew Wilcox, Jan Kara, Alexander Viro, Christian Brauner,
	tytso, Andreas Dilger, Baokun Li, Ojaswin Mujoo,
	Ritesh Harjani (IBM), Zhang Yi, asml.silence, Jonathan Corbet,
	Shuah Khan, Randy Dunlap
  Cc: linux-block, linux-kernel, linux-fsdevel, nvdimm, linux-ext4,
	linux-xfs, linux-doc, linux-media, dri-devel, linaro-mm-sig,
	Li Wang, Mengmeng Zhao

From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>

Move the dma-buf integrity check out of blk_mq_submit_bio() into
bio_dmabuf_should_reject(), so that such checks have one place to grow.

No functional change.

Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
Signed-off-by: Li Wang <liwang@kylinos.cn>
---
 block/blk-mq.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 5ae22d556540..887d5cc5bb5e 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -3099,6 +3099,20 @@ static bool bio_unaligned(const struct bio *bio, struct request_queue *q)
 	return false;
 }
 
+/*
+ * A dma-buf bio carries a driver-private map instead of pages, so the block
+ * layer cannot generate or verify integrity metadata for it.  Only reject when
+ * it would have to do that itself, not if the submitter attached its own
+ * payload or if generation or verification is turned off for the device.
+ */
+static bool bio_dmabuf_should_reject(struct bio *bio)
+{
+	if (!op_is_dmabuf(bio->bi_opf))
+		return false;
+	return bdev_has_integrity_csum(bio->bi_bdev) &&
+	       (bio_integrity_action(bio) & BI_ACT_CHECK);
+}
+
 /**
  * blk_mq_submit_bio - Create and send a request to block device.
  * @bio: Bio pointer.
@@ -3160,15 +3174,7 @@ void blk_mq_submit_bio(struct bio *bio)
 		goto queue_exit;
 	}
 
-	/*
-	 * The block layer cannot generate or verify PI for a dma-buf bio, as
-	 * that walks the data pages.  Only fail the bio if it needs that, not
-	 * if the submitter attached its own integrity payload or if PI
-	 * generation or verification is turned off for the device.
-	 */
-	if (unlikely(op_is_dmabuf(bio->bi_opf) &&
-		     bdev_has_integrity_csum(bio->bi_bdev) &&
-		     (bio_integrity_action(bio) & BI_ACT_CHECK))) {
+	if (unlikely(bio_dmabuf_should_reject(bio))) {
 		bio_endio_status(bio, BLK_STS_NOTSUPP);
 		goto queue_exit;
 	}
-- 
2.43.0


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

* [RFC PATCH v2 5/8] blk-crypto: refuse dma-buf bios in the fallback path
  2026-11-13  7:06 [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support Mengmeng Zhao
                   ` (3 preceding siblings ...)
  2026-11-13  7:06 ` [RFC PATCH v2 4/8] blk-mq: factor out a dma-buf bio refusal helper Mengmeng Zhao
@ 2026-11-13  7:06 ` Mengmeng Zhao
  2026-11-13  7:24   ` sashiko-bot
  2026-11-13  7:06 ` [RFC PATCH v2 6/8] fs: add FMODE_CAN_DMABUF_IO and require it for dma-buf I/O contexts Mengmeng Zhao
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Mengmeng Zhao @ 2026-11-13  7:06 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta, Nitesh Shetty, Jens Axboe,
	Sumit Semwal, christian.koenig, Philipp Stanner, Dan Williams,
	Matthew Wilcox, Jan Kara, Alexander Viro, Christian Brauner,
	tytso, Andreas Dilger, Baokun Li, Ojaswin Mujoo,
	Ritesh Harjani (IBM), Zhang Yi, asml.silence, Jonathan Corbet,
	Shuah Khan, Randy Dunlap
  Cc: linux-block, linux-kernel, linux-fsdevel, nvdimm, linux-ext4,
	linux-xfs, linux-doc, linux-media, dri-devel, linaro-mm-sig,
	Li Wang, Mengmeng Zhao

From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>

The inline encryption fallback encrypts through the data pages of a bio,
which a dma-buf bio does not have: its vec pointer holds the
driver-private dma_buf_io_map.  A crypt context the device supports
natively is programmed from the request instead, so refuse only where
the fallback is about to run.

blk_mq_submit_bio() is too late for this: submit_bio_noacct() has already
rejected a context the device does not support natively, while submitters
reach the fallback before the bio is queued.  No in-tree submitter builds
such a bio today.

Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
Signed-off-by: Li Wang <liwang@kylinos.cn>
---
 block/blk-crypto.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/block/blk-crypto.c b/block/blk-crypto.c
index bc3a9f59574b..01b8d26040dc 100644
--- a/block/blk-crypto.c
+++ b/block/blk-crypto.c
@@ -271,6 +271,14 @@ bool __blk_crypto_submit_bio(struct bio *bio)
 			bio_endio_status(bio, BLK_STS_NOTSUPP);
 			return false;
 		}
+		/*
+		 * The fallback encrypts from the data pages, which a dma-buf
+		 * bio does not have.
+		 */
+		if (op_is_dmabuf(bio->bi_opf)) {
+			bio_endio_status(bio, BLK_STS_NOTSUPP);
+			return false;
+		}
 		return blk_crypto_fallback_bio_prep(bio);
 	}
 
-- 
2.43.0


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

* [RFC PATCH v2 6/8] fs: add FMODE_CAN_DMABUF_IO and require it for dma-buf I/O contexts
  2026-11-13  7:06 [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support Mengmeng Zhao
                   ` (4 preceding siblings ...)
  2026-11-13  7:06 ` [RFC PATCH v2 5/8] blk-crypto: refuse dma-buf bios in the fallback path Mengmeng Zhao
@ 2026-11-13  7:06 ` Mengmeng Zhao
  2026-11-13  7:24   ` sashiko-bot
  2026-11-13  7:06 ` [RFC PATCH v2 7/8] dax: refuse dma-buf iterators in dax_iomap_rw() Mengmeng Zhao
  2026-11-13  7:06 ` [RFC PATCH v2 8/8] ext4: support dma-buf registered buffers for direct I/O Mengmeng Zhao
  7 siblings, 1 reply; 17+ messages in thread
From: Mengmeng Zhao @ 2026-11-13  7:06 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta, Nitesh Shetty, Jens Axboe,
	Sumit Semwal, christian.koenig, Philipp Stanner, Dan Williams,
	Matthew Wilcox, Jan Kara, Alexander Viro, Christian Brauner,
	tytso, Andreas Dilger, Baokun Li, Ojaswin Mujoo,
	Ritesh Harjani (IBM), Zhang Yi, asml.silence, Jonathan Corbet,
	Shuah Khan, Randy Dunlap
  Cc: linux-block, linux-kernel, linux-fsdevel, nvdimm, linux-ext4,
	linux-xfs, linux-doc, linux-media, dri-devel, linaro-mm-sig,
	Li Wang, Mengmeng Zhao

From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>

Add a file mode bit for files that can be the target of dma-buf I/O and
require it when a buffer is registered.  Block device files set it when
the backing disk supports dma-buf I/O, and filesystems can set it for
inodes whose data can be reached without the page cache.  The bit is
coarse: a driver that installs ->init_dma_buf_io_ctx for every
namespace, like nvme, still decides per device at registration.

dma_buf_io_ctx_create() is the only caller of ->init_dma_buf_io_ctx, so
the capability and the O_DIRECT requirement are checked there for every
file type rather than in each helper; O_DIRECT belongs at registration
because F_SETFL can change it afterwards.  Add bdev_can_dmabuf_io() so
the open-time and registration checks share one predicate.

Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
Signed-off-by: Li Wang <liwang@kylinos.cn>
---
 block/bdev.c                 |  8 ++++----
 block/fops.c                 |  2 +-
 drivers/dma-buf/dma-buf-io.c | 13 +++++++++----
 include/linux/blkdev.h       |  7 ++++++-
 include/linux/fs.h           |  8 +++++++-
 5 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/block/bdev.c b/block/bdev.c
index 88e3f552f5d4..4e7a7f7e1e8b 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -61,14 +61,12 @@ struct block_device *file_bdev(struct file *bdev_file)
 }
 EXPORT_SYMBOL(file_bdev);
 
-int bdev_init_dma_buf_io_ctx(struct file *file, struct block_device *bdev,
+int bdev_init_dma_buf_io_ctx(struct block_device *bdev,
 			     struct dma_buf_io_ctx *ctx)
 {
-	if (!(file->f_flags & O_DIRECT))
-		return -EINVAL;
 	if (ctx->dmabuf->size > UINT_MAX)
 		return -EINVAL;
-	if (!bdev->bd_disk->fops->init_dma_buf_io_ctx)
+	if (!bdev_can_dmabuf_io(bdev))
 		return -EOPNOTSUPP;
 	return bdev->bd_disk->fops->init_dma_buf_io_ctx(bdev, ctx);
 }
@@ -1041,6 +1039,8 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder,
 
 	bdev_file->f_flags |= O_LARGEFILE;
 	bdev_file->f_mode |= FMODE_CAN_ODIRECT;
+	if (bdev_can_dmabuf_io(bdev))
+		bdev_file->f_mode |= FMODE_CAN_DMABUF_IO;
 	if (bdev_nowait(bdev))
 		bdev_file->f_mode |= FMODE_NOWAIT;
 	if (mode & BLK_OPEN_RESTRICT_WRITES)
diff --git a/block/fops.c b/block/fops.c
index 86bf1f298b79..7e5702e047a2 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -1008,7 +1008,7 @@ static int blkdev_mmap_prepare(struct vm_area_desc *desc)
 static int blkdev_init_dma_buf_io_ctx(struct file *file,
 				      struct dma_buf_io_ctx *ctx)
 {
-	return bdev_init_dma_buf_io_ctx(file, file_bdev(file), ctx);
+	return bdev_init_dma_buf_io_ctx(file_bdev(file), ctx);
 }
 
 const struct file_operations def_blk_fops = {
diff --git a/drivers/dma-buf/dma-buf-io.c b/drivers/dma-buf/dma-buf-io.c
index 8440151de860..9575b7d65ec5 100644
--- a/drivers/dma-buf/dma-buf-io.c
+++ b/drivers/dma-buf/dma-buf-io.c
@@ -152,9 +152,11 @@ static void dma_buf_io_ctx_shutdown(struct dma_buf_io_ctx *ctx)
  * @out_ctx:	[out]	resulting ctx
  *
  * Create a new I/O context from the given DMA buffer for the given file.
- * It only works with files implementing ->init_dma_buf_io_ctx and fails
- * with -EOPNOTSUPP otherwise. Once created, the user can create a map
- * and use it to issue I/O, such as read/write requests, to @file.
+ * It only works with files implementing ->init_dma_buf_io_ctx,
+ * advertising FMODE_CAN_DMABUF_IO and currently opened for direct I/O,
+ * and fails with -EOPNOTSUPP or -EINVAL otherwise. Once created, the
+ * user can create a map and use it to issue I/O, such as read/write
+ * requests, to @file.
  */
 int dma_buf_io_ctx_create(struct file *file,
 			   struct dma_buf *dmabuf,
@@ -164,8 +166,11 @@ int dma_buf_io_ctx_create(struct file *file,
 	struct dma_buf_io_ctx *ctx;
 	int ret;
 
-	if (!file->f_op->init_dma_buf_io_ctx)
+	if (!file->f_op->init_dma_buf_io_ctx ||
+	    !(file->f_mode & FMODE_CAN_DMABUF_IO))
 		return -EOPNOTSUPP;
+	if (!(file->f_flags & O_DIRECT))
+		return -EINVAL;
 
 	ctx = kzalloc_obj(*ctx);
 	if (!ctx)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index b98f43478cc0..0cfb6fb6b4e2 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1610,9 +1610,14 @@ struct block_device_operations {
 	int (*alternative_gpt_sector)(struct gendisk *disk, sector_t *sector);
 };
 
-int bdev_init_dma_buf_io_ctx(struct file *file, struct block_device *bdev,
+int bdev_init_dma_buf_io_ctx(struct block_device *bdev,
 			     struct dma_buf_io_ctx *ctx);
 
+static inline bool bdev_can_dmabuf_io(struct block_device *bdev)
+{
+	return !!bdev->bd_disk->fops->init_dma_buf_io_ctx;
+}
+
 #ifdef CONFIG_COMPAT
 extern int blkdev_compat_ptr_ioctl(struct block_device *, blk_mode_t,
 				      unsigned int, unsigned long);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 99caef43ff3c..f5524fc770d4 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -121,7 +121,13 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 /* File supports atomic writes */
 #define FMODE_CAN_ATOMIC_WRITE	((__force fmode_t)(1 << 7))
 
-/* FMODE_* bit 8 */
+/*
+ * File can be the target of dma-buf I/O.  Set it for files whose data can be
+ * reached with direct I/O without the page cache: a dma-buf iterator has no
+ * pages to copy, so a buffered path cannot serve it.  The bit is coarse; both
+ * the device behind it and O_DIRECT are checked when a buffer is registered.
+ */
+#define FMODE_CAN_DMABUF_IO	((__force fmode_t)(1 << 8))
 
 /* 32bit hashes as llseek() offset (for directories) */
 #define FMODE_32BITHASH         ((__force fmode_t)(1 << 9))
-- 
2.43.0


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

* [RFC PATCH v2 7/8] dax: refuse dma-buf iterators in dax_iomap_rw()
  2026-11-13  7:06 [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support Mengmeng Zhao
                   ` (5 preceding siblings ...)
  2026-11-13  7:06 ` [RFC PATCH v2 6/8] fs: add FMODE_CAN_DMABUF_IO and require it for dma-buf I/O contexts Mengmeng Zhao
@ 2026-11-13  7:06 ` Mengmeng Zhao
  2026-11-13  7:25   ` sashiko-bot
  2026-11-13  7:06 ` [RFC PATCH v2 8/8] ext4: support dma-buf registered buffers for direct I/O Mengmeng Zhao
  7 siblings, 1 reply; 17+ messages in thread
From: Mengmeng Zhao @ 2026-11-13  7:06 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta, Nitesh Shetty, Jens Axboe,
	Sumit Semwal, christian.koenig, Philipp Stanner, Dan Williams,
	Matthew Wilcox, Jan Kara, Alexander Viro, Christian Brauner,
	tytso, Andreas Dilger, Baokun Li, Ojaswin Mujoo,
	Ritesh Harjani (IBM), Zhang Yi, asml.silence, Jonathan Corbet,
	Shuah Khan, Randy Dunlap
  Cc: linux-block, linux-kernel, linux-fsdevel, nvdimm, linux-ext4,
	linux-xfs, linux-doc, linux-media, dri-devel, linaro-mm-sig,
	Li Wang, Mengmeng Zhao

From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>

DAX copies data through the CPU, so a dma-buf iterator has no meaning
in the DAX I/O path and must be refused.  A DAX inode does not get
FMODE_CAN_DMABUF_IO at open time, but DAX can be enabled later, so
check per I/O.

Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
Signed-off-by: Li Wang <liwang@kylinos.cn>
---
 fs/dax.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/fs/dax.c b/fs/dax.c
index 94ba41273347..84d24db5ed35 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -1752,6 +1752,10 @@ dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,
 	if (!iomi.len)
 		return 0;
 
+	/* a dma-buf iterator has no CPU-visible pages to copy through */
+	if (iov_iter_is_dmabuf_map(iter))
+		return -EOPNOTSUPP;
+
 	if (iov_iter_rw(iter) == WRITE) {
 		lockdep_assert_held_write(&iomi.inode->i_rwsem);
 		iomi.flags |= IOMAP_WRITE;
-- 
2.43.0


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

* [RFC PATCH v2 8/8] ext4: support dma-buf registered buffers for direct I/O
  2026-11-13  7:06 [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support Mengmeng Zhao
                   ` (6 preceding siblings ...)
  2026-11-13  7:06 ` [RFC PATCH v2 7/8] dax: refuse dma-buf iterators in dax_iomap_rw() Mengmeng Zhao
@ 2026-11-13  7:06 ` Mengmeng Zhao
  2026-11-13  7:26   ` sashiko-bot
  7 siblings, 1 reply; 17+ messages in thread
From: Mengmeng Zhao @ 2026-11-13  7:06 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta, Nitesh Shetty, Jens Axboe,
	Sumit Semwal, christian.koenig, Philipp Stanner, Dan Williams,
	Matthew Wilcox, Jan Kara, Alexander Viro, Christian Brauner,
	tytso, Andreas Dilger, Baokun Li, Ojaswin Mujoo,
	Ritesh Harjani (IBM), Zhang Yi, asml.silence, Jonathan Corbet,
	Shuah Khan, Randy Dunlap
  Cc: linux-block, linux-kernel, linux-fsdevel, nvdimm, linux-ext4,
	linux-xfs, linux-doc, linux-media, dri-devel, linaro-mm-sig,
	Li Wang, Mengmeng Zhao

From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>

Advertise FMODE_CAN_DMABUF_IO for inodes that can support dma-buf I/O
and implement ->init_dma_buf_io_ctx() by registering the buffer against
the filesystem's block device.  The capability follows
ext4_dio_alignment(), so an inode that can never do direct I/O -
fs-verity, data=journal or inline data - is refused at open, and
encrypted inodes are refused on the inode flag, which is set even
without CONFIG_FS_ENCRYPTION.  The inode is rechecked at registration
because DAX can be enabled after the file was opened.

A dma-buf iterator has no pages to copy from, so it must never reach the
page cache.  ext4_buffered_read_iter() and ext4_buffered_write_iter() are
the single sinks of the buffered fallbacks and refuse it there; a short
direct I/O write still reports its progress, and the DAX write path
refuses at its entry instead of after starting a journal handle.

Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
Signed-off-by: Li Wang <liwang@kylinos.cn>
---
 fs/ext4/ext4.h | 11 +++++++++++
 fs/ext4/file.c | 44 +++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f38fec3167fb..028b2e5ddc8b 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -4135,6 +4135,17 @@ static inline bool ext4_inode_can_atomic_write(struct inode *inode)
 		EXT4_SB(inode->i_sb)->s_awu_min > 0;
 }
 
+/*
+ * dma-buf I/O needs an inode that supports direct I/O without the page cache.
+ * IS_ENCRYPTED() tests the inode flag, which is set even without
+ * CONFIG_FS_ENCRYPTION.
+ */
+static inline bool ext4_inode_can_dmabuf_io(struct inode *inode)
+{
+	return !IS_DAX(inode) && !IS_ENCRYPTED(inode) &&
+	       ext4_dio_alignment(inode) != 0;
+}
+
 extern int ext4_block_write_begin(handle_t *handle, struct folio *folio,
 				  loff_t pos, unsigned len,
 				  get_block_t *get_block);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 50d3c92709c8..5a8481637da5 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -30,6 +30,7 @@
 #include <linux/uio.h>
 #include <linux/mman.h>
 #include <linux/backing-dev.h>
+#include <linux/blkdev.h>
 #include "ext4.h"
 #include "ext4_jbd2.h"
 #include "xattr.h"
@@ -66,6 +67,15 @@ static bool ext4_should_use_dio(struct kiocb *iocb, struct iov_iter *iter)
 	return IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), dio_align);
 }
 
+static ssize_t ext4_buffered_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+	/* a dma-buf iterator has no pages for the page cache to copy into */
+	if (iov_iter_is_dmabuf_map(to))
+		return -EOPNOTSUPP;
+
+	return generic_file_read_iter(iocb, to);
+}
+
 static ssize_t ext4_dio_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
 	ssize_t ret;
@@ -88,7 +98,7 @@ static ssize_t ext4_dio_read_iter(struct kiocb *iocb, struct iov_iter *to)
 		 * taken.
 		 */
 		iocb->ki_flags &= ~IOCB_DIRECT;
-		return generic_file_read_iter(iocb, to);
+		return ext4_buffered_read_iter(iocb, to);
 	}
 
 	ret = iomap_dio_read_simple(iocb, to, ext4_iomap_begin);
@@ -119,7 +129,7 @@ static ssize_t ext4_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
 	if (!IS_DAX(inode)) {
 		inode_unlock_shared(inode);
 		/* Fallback to buffered IO in case we cannot support DAX */
-		return generic_file_read_iter(iocb, to);
+		return ext4_buffered_read_iter(iocb, to);
 	}
 	ret = dax_iomap_rw(iocb, to, &ext4_iomap_ops);
 	inode_unlock_shared(inode);
@@ -146,7 +156,7 @@ static ssize_t ext4_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 	if (iocb->ki_flags & IOCB_DIRECT)
 		return ext4_dio_read_iter(iocb, to);
 
-	return generic_file_read_iter(iocb, to);
+	return ext4_buffered_read_iter(iocb, to);
 }
 
 static ssize_t ext4_file_splice_read(struct file *in, loff_t *ppos,
@@ -354,6 +364,10 @@ static ssize_t ext4_buffered_write_iter(struct kiocb *iocb,
 	if (iocb->ki_flags & IOCB_NOWAIT)
 		return -EOPNOTSUPP;
 
+	/* a dma-buf iterator cannot be handled by buffered I/O */
+	if (iov_iter_is_dmabuf_map(from))
+		return -EOPNOTSUPP;
+
 	inode_lock(inode);
 
 	/*
@@ -688,6 +702,10 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
 		ssize_t err;
 		loff_t endbyte;
 
+		/* a dma-buf iterator cannot fall back to buffered I/O */
+		if (iov_iter_is_dmabuf_map(from))
+			return ret;
+
 		/*
 		 * There is no support for atomic writes on buffered-io yet,
 		 * we should never fallback to buffered-io for DIO atomic
@@ -731,6 +749,10 @@ ext4_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
 	bool extend = false;
 	struct inode *inode = file_inode(iocb->ki_filp);
 
+	/* a dma-buf iterator cannot be handled by DAX either */
+	if (iov_iter_is_dmabuf_map(from))
+		return -EOPNOTSUPP;
+
 	if (iocb->ki_flags & IOCB_NOWAIT) {
 		if (!inode_trylock(inode))
 			return -EAGAIN;
@@ -1014,6 +1036,8 @@ static int ext4_file_open(struct inode *inode, struct file *filp)
 		filp->f_mode |= FMODE_CAN_ATOMIC_WRITE;
 
 	filp->f_mode |= FMODE_NOWAIT | FMODE_CAN_ODIRECT;
+	if (ext4_inode_can_dmabuf_io(inode))
+		filp->f_mode |= FMODE_CAN_DMABUF_IO;
 	return dquot_file_open(inode, filp);
 }
 
@@ -1050,10 +1074,24 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int whence)
 	return vfs_setpos(file, offset, maxbytes);
 }
 
+static int ext4_file_init_dma_buf_io_ctx(struct file *file,
+					 struct dma_buf_io_ctx *ctx)
+{
+	struct inode *inode = file_inode(file);
+
+	/* DAX can be enabled after the file was opened */
+	if (!ext4_inode_can_dmabuf_io(inode))
+		return -EOPNOTSUPP;
+
+	/* all file data lives on s_bdev, which never changes for ext4 */
+	return bdev_init_dma_buf_io_ctx(inode->i_sb->s_bdev, ctx);
+}
+
 const struct file_operations ext4_file_operations = {
 	.llseek		= ext4_llseek,
 	.read_iter	= ext4_file_read_iter,
 	.write_iter	= ext4_file_write_iter,
+	.init_dma_buf_io_ctx = ext4_file_init_dma_buf_io_ctx,
 	.iopoll		= iocb_bio_iopoll,
 	.unlocked_ioctl = ext4_ioctl,
 #ifdef CONFIG_COMPAT
-- 
2.43.0


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

* Re: [RFC PATCH v2 4/8] blk-mq: factor out a dma-buf bio refusal helper
  2026-11-13  7:06 ` [RFC PATCH v2 4/8] blk-mq: factor out a dma-buf bio refusal helper Mengmeng Zhao
@ 2026-11-13  7:12   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-11-13  7:12 UTC (permalink / raw)
  To: Mengmeng Zhao; +Cc: linux-ext4, tytso

> From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> 
> Move the dma-buf integrity check out of blk_mq_submit_bio() into
> bio_dmabuf_should_reject(), so that such checks have one place to grow.
> 
> No functional change.
> 
> Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> Signed-off-by: Li Wang <liwang@kylinos.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113070621.273953-1-mengmeng.zhao@linux.dev?part=4


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

* Re: [RFC PATCH v2 5/8] blk-crypto: refuse dma-buf bios in the fallback path
  2026-11-13  7:06 ` [RFC PATCH v2 5/8] blk-crypto: refuse dma-buf bios in the fallback path Mengmeng Zhao
@ 2026-11-13  7:24   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-11-13  7:24 UTC (permalink / raw)
  To: Mengmeng Zhao; +Cc: linux-ext4, tytso

> From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> 
> The inline encryption fallback encrypts through the data pages of a bio,
> which a dma-buf bio does not have: its vec pointer holds the
> driver-private dma_buf_io_map.  A crypt context the device supports
> natively is programmed from the request instead, so refuse only where
> the fallback is about to run.
> 
> blk_mq_submit_bio() is too late for this: submit_bio_noacct() has already
> rejected a context the device does not support natively, while submitters
> reach the fallback before the bio is queued.  No in-tree submitter builds
> such a bio today.
> 
> Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> Signed-off-by: Li Wang <liwang@kylinos.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113070621.273953-1-mengmeng.zhao@linux.dev?part=5


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

* Re: [RFC PATCH v2 6/8] fs: add FMODE_CAN_DMABUF_IO and require it for dma-buf I/O contexts
  2026-11-13  7:06 ` [RFC PATCH v2 6/8] fs: add FMODE_CAN_DMABUF_IO and require it for dma-buf I/O contexts Mengmeng Zhao
@ 2026-11-13  7:24   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-11-13  7:24 UTC (permalink / raw)
  To: Mengmeng Zhao; +Cc: linux-ext4, tytso

> From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> 
> Add a file mode bit for files that can be the target of dma-buf I/O and
> require it when a buffer is registered.  Block device files set it when
> the backing disk supports dma-buf I/O, and filesystems can set it for
> inodes whose data can be reached without the page cache.  The bit is
> coarse: a driver that installs ->init_dma_buf_io_ctx for every
> namespace, like nvme, still decides per device at registration.
> 
> dma_buf_io_ctx_create() is the only caller of ->init_dma_buf_io_ctx, so
> the capability and the O_DIRECT requirement are checked there for every
> file type rather than in each helper; O_DIRECT belongs at registration
> because F_SETFL can change it afterwards.  Add bdev_can_dmabuf_io() so
> the open-time and registration checks share one predicate.
> 
> Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> Signed-off-by: Li Wang <liwang@kylinos.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113070621.273953-1-mengmeng.zhao@linux.dev?part=6


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

* Re: [RFC PATCH v2 1/8] block: factor out bdev_init_dma_buf_io_ctx()
  2026-11-13  7:06 ` [RFC PATCH v2 1/8] block: factor out bdev_init_dma_buf_io_ctx() Mengmeng Zhao
@ 2026-11-13  7:24   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-11-13  7:24 UTC (permalink / raw)
  To: Mengmeng Zhao; +Cc: linux-ext4, tytso

> From: Nitesh Shetty <nj.shetty@samsung.com>
> 
> Factor the checks and the driver setup out of
> blkdev_init_dma_buf_io_ctx() into an exported helper that takes the
> block device as an argument, so callers can set up a dma-buf I/O
> context for any block device.  The block device file operation becomes
> a thin wrapper using file_bdev(), so its behavior is unchanged.
> 
> Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
> Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> Signed-off-by: Li Wang <liwang@kylinos.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113070621.273953-1-mengmeng.zhao@linux.dev?part=1


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

* Re: [RFC PATCH v2 7/8] dax: refuse dma-buf iterators in dax_iomap_rw()
  2026-11-13  7:06 ` [RFC PATCH v2 7/8] dax: refuse dma-buf iterators in dax_iomap_rw() Mengmeng Zhao
@ 2026-11-13  7:25   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-11-13  7:25 UTC (permalink / raw)
  To: Mengmeng Zhao; +Cc: linux-ext4, tytso

> From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> 
> DAX copies data through the CPU, so a dma-buf iterator has no meaning
> in the DAX I/O path and must be refused.  A DAX inode does not get
> FMODE_CAN_DMABUF_IO at open time, but DAX can be enabled later, so
> check per I/O.
> 
> Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> Signed-off-by: Li Wang <liwang@kylinos.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113070621.273953-1-mengmeng.zhao@linux.dev?part=7


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

* Re: [RFC PATCH v2 8/8] ext4: support dma-buf registered buffers for direct I/O
  2026-11-13  7:06 ` [RFC PATCH v2 8/8] ext4: support dma-buf registered buffers for direct I/O Mengmeng Zhao
@ 2026-11-13  7:26   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-11-13  7:26 UTC (permalink / raw)
  To: Mengmeng Zhao; +Cc: linux-ext4, tytso

> From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> 
> Advertise FMODE_CAN_DMABUF_IO for inodes that can support dma-buf I/O
> and implement ->init_dma_buf_io_ctx() by registering the buffer against
> the filesystem's block device.  The capability follows
> ext4_dio_alignment(), so an inode that can never do direct I/O -
> fs-verity, data=journal or inline data - is refused at open, and
> encrypted inodes are refused on the inode flag, which is set even
> without CONFIG_FS_ENCRYPTION.  The inode is rechecked at registration
> because DAX can be enabled after the file was opened.
> 
> A dma-buf iterator has no pages to copy from, so it must never reach the
> page cache.  ext4_buffered_read_iter() and ext4_buffered_write_iter() are
> the single sinks of the buffered fallbacks and refuse it there; a short
> direct I/O write still reports its progress, and the DAX write path
> refuses at its entry instead of after starting a journal handle.
> 
> Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> Signed-off-by: Li Wang <liwang@kylinos.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113070621.273953-1-mengmeng.zhao@linux.dev?part=8


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

* Re: [RFC PATCH v2 3/8] iomap: don't ask for a buffered fallback for dma-buf iterators
  2026-11-13  7:06 ` [RFC PATCH v2 3/8] iomap: don't ask for a buffered fallback for dma-buf iterators Mengmeng Zhao
@ 2026-11-13  7:28   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-11-13  7:28 UTC (permalink / raw)
  To: Mengmeng Zhao; +Cc: linux-ext4, tytso

> From: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> 
> -ENOTBLK tells the caller to retry with buffered I/O.  A dma-buf iterator
> has no pages to copy, so the callers refuse that fallback, which would
> turn the error into a successful transfer of zero bytes.
> 
> Report the reason instead: a busy folio becomes -EAGAIN, which the caller
> can retry, any other invalidation failure keeps its error code, and
> -ENOTBLK from ->iomap_begin() becomes -EOPNOTSUPP when nothing was
> transferred.  A partial direct I/O still reports its progress.  Both
> branches are reachable only through a file that opted into dma-buf I/O,
> which ext4 does in the last patch.
> 
> Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> Signed-off-by: Li Wang <liwang@kylinos.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113070621.273953-1-mengmeng.zhao@linux.dev?part=3


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

* Re: [RFC PATCH v2 2/8] iomap: add dma-buf direct I/O guards
  2026-11-13  7:06 ` [RFC PATCH v2 2/8] iomap: add dma-buf direct I/O guards Mengmeng Zhao
@ 2026-11-13  7:31   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-11-13  7:31 UTC (permalink / raw)
  To: Mengmeng Zhao; +Cc: linux-ext4, tytso

> From: Nitesh Shetty <nj.shetty@samsung.com>
> 
> Direct I/O copies data from the CPU in four places, zero-filling
> holes, inline data, bounce pages and integrity metadata. A dma-buf
> iterator has no pages behind it, so refuse it there.
> 
> Reads that encounter a hole or unwritten extent therefore return
> -EOPNOTSUPP for the entire operation, even if I/O for an earlier
> mapped extent was already submitted.
> 
> Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
> Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
> Signed-off-by: Mengmeng Zhao <zhaomengmeng@kylinos.cn>
> Signed-off-by: Li Wang <liwang@kylinos.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113070621.273953-1-mengmeng.zhao@linux.dev?part=2


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

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

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-13  7:06 [RFC PATCH v2 0/8] ext4: Add dma-buf read/write support Mengmeng Zhao
2026-11-13  7:06 ` [RFC PATCH v2 1/8] block: factor out bdev_init_dma_buf_io_ctx() Mengmeng Zhao
2026-11-13  7:24   ` sashiko-bot
2026-11-13  7:06 ` [RFC PATCH v2 2/8] iomap: add dma-buf direct I/O guards Mengmeng Zhao
2026-11-13  7:31   ` sashiko-bot
2026-11-13  7:06 ` [RFC PATCH v2 3/8] iomap: don't ask for a buffered fallback for dma-buf iterators Mengmeng Zhao
2026-11-13  7:28   ` sashiko-bot
2026-11-13  7:06 ` [RFC PATCH v2 4/8] blk-mq: factor out a dma-buf bio refusal helper Mengmeng Zhao
2026-11-13  7:12   ` sashiko-bot
2026-11-13  7:06 ` [RFC PATCH v2 5/8] blk-crypto: refuse dma-buf bios in the fallback path Mengmeng Zhao
2026-11-13  7:24   ` sashiko-bot
2026-11-13  7:06 ` [RFC PATCH v2 6/8] fs: add FMODE_CAN_DMABUF_IO and require it for dma-buf I/O contexts Mengmeng Zhao
2026-11-13  7:24   ` sashiko-bot
2026-11-13  7:06 ` [RFC PATCH v2 7/8] dax: refuse dma-buf iterators in dax_iomap_rw() Mengmeng Zhao
2026-11-13  7:25   ` sashiko-bot
2026-11-13  7:06 ` [RFC PATCH v2 8/8] ext4: support dma-buf registered buffers for direct I/O Mengmeng Zhao
2026-11-13  7:26   ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.