* [RFC 0/4] fs: support dma-buf backed direct I/O
@ 2026-10-16 9:19 Anuj Gupta
2026-10-16 9:19 ` [RFC 1/4] block: factor out bdev_init_dma_buf_io_ctx() Anuj Gupta
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Anuj Gupta @ 2026-10-16 9:19 UTC (permalink / raw)
To: asml.silence, hch, djwong, cem, brauner, axboe
Cc: linux-block, linux-xfs, linux-fsdevel, joshi.k, anuj20.g,
nj.shetty
This series lets an application register a dma-buf against a file,
so reads and writes go directly to the device as dma-buf backed
bios with no per-command DMA mapping.
This series builds on Pavel Begunkov's dma-buf block support v11,
https://lore.kernel.org/all/cover.1791975048.git.asml.silence@gmail.com/
which is queued in Jens Axboe's tree:
https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux.git/log/?h=for-7.4/io_uring-dmabuf
A separate kernel tree is present here:
https://github.com/anuj7781/linux-kernel/tree/anuj/fs-dmabuf-rfc-v11-desc-v2
Nitesh Shetty (4):
block: factor out bdev_init_dma_buf_io_ctx()
block: refuse a dma-buf bio for a disk the buffer was not registered
on
iomap: add dma-buf direct I/O guards and registration helper
xfs: support dma-buf registered buffers for direct I/O
block/bio.c | 15 +++++++++++++++
block/fops.c | 19 +++++++++++++++----
fs/iomap/direct-io.c | 31 ++++++++++++++++++++++++++++++-
fs/xfs/xfs_file.c | 30 ++++++++++++++++++++++++++++++
include/linux/blkdev.h | 3 +++
include/linux/dma-buf-io.h | 2 ++
include/linux/iomap.h | 3 +++
7 files changed, 98 insertions(+), 5 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC 1/4] block: factor out bdev_init_dma_buf_io_ctx()
2026-10-16 9:19 [RFC 0/4] fs: support dma-buf backed direct I/O Anuj Gupta
@ 2026-10-16 9:19 ` Anuj Gupta
2026-10-16 9:23 ` Christoph Hellwig
2026-10-16 9:19 ` [RFC 2/4] block: refuse a dma-buf bio for a disk the buffer was not registered on Anuj Gupta
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: Anuj Gupta @ 2026-10-16 9:19 UTC (permalink / raw)
To: asml.silence, hch, djwong, cem, brauner, axboe
Cc: linux-block, linux-xfs, linux-fsdevel, joshi.k, anuj20.g,
nj.shetty
From: Nitesh Shetty <nj.shetty@samsung.com>
Factor the checks and driver setup into an exported helper that takes
an explicit block device, so filesystems can initialize a dma-buf I/O
context for the device backing a regular file. The block-device file
operation becomes a wrapper using file_bdev(), so its behavior is
unchanged.
Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
---
block/fops.c | 12 +++++++++---
include/linux/blkdev.h | 3 +++
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/block/fops.c b/block/fops.c
index 49ae0302f123..18a755f6e0b0 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -934,10 +934,9 @@ static int blkdev_mmap_prepare(struct vm_area_desc *desc)
return generic_file_mmap_prepare(desc);
}
-static int blkdev_init_dma_buf_io_ctx(struct file *file,
- struct dma_buf_io_ctx *ctx)
+int bdev_init_dma_buf_io_ctx(struct file *file, struct block_device *bdev,
+ 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))
@@ -948,6 +947,13 @@ static int blkdev_init_dma_buf_io_ctx(struct file *file,
return -EOPNOTSUPP;
return disk->fops->init_dma_buf_io_ctx(bdev, ctx);
}
+EXPORT_SYMBOL_GPL(bdev_init_dma_buf_io_ctx);
+
+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);
+}
const struct file_operations def_blk_fops = {
.open = blkdev_open,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 2d555a992e75..a0abdf94e7d6 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1609,6 +1609,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] 9+ messages in thread
* [RFC 2/4] block: refuse a dma-buf bio for a disk the buffer was not registered on
2026-10-16 9:19 [RFC 0/4] fs: support dma-buf backed direct I/O Anuj Gupta
2026-10-16 9:19 ` [RFC 1/4] block: factor out bdev_init_dma_buf_io_ctx() Anuj Gupta
@ 2026-10-16 9:19 ` Anuj Gupta
2026-10-16 9:24 ` Christoph Hellwig
2026-10-16 9:19 ` [RFC 3/4] iomap: add dma-buf direct I/O guards and registration helper Anuj Gupta
2026-10-16 9:19 ` [RFC 4/4] xfs: support dma-buf registered buffers for direct I/O Anuj Gupta
3 siblings, 1 reply; 9+ messages in thread
From: Anuj Gupta @ 2026-10-16 9:19 UTC (permalink / raw)
To: asml.silence, hch, djwong, cem, brauner, axboe
Cc: linux-block, linux-xfs, linux-fsdevel, joshi.k, anuj20.g,
nj.shetty
From: Nitesh Shetty <nj.shetty@samsung.com>
A registered dma-buf map belongs to the device it was mapped for.
The device backing a file can change after registration. Record
the registered disk's dev_t at init and refuse a bio that targets
a different one.
Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
---
block/bio.c | 15 +++++++++++++++
block/fops.c | 7 ++++++-
include/linux/dma-buf-io.h | 2 ++
3 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/block/bio.c b/block/bio.c
index 795b88e4a994..b9e5c73cd3d1 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -19,6 +19,7 @@
#include <linux/blk-crypto.h>
#include <linux/xarray.h>
#include <linux/kmemleak.h>
+#include <linux/dma-buf-io.h>
#include <trace/events/block.h>
#include "blk.h"
@@ -1269,6 +1270,17 @@ static inline bool bio_iov_bvec_aligned(const struct bio *bio,
}
#endif
+/*
+ * A dma-buf map is only valid for the disk it was registered on, but
+ * the device backing a file can change after the registration.
+ */
+static bool bio_dmabuf_map_valid(const struct bio *bio,
+ const struct iov_iter *iter)
+{
+ return iter->dmabuf_map->ctx->registered_devt ==
+ disk_devt(bio->bi_bdev->bd_disk);
+}
+
/**
* bio_iov_iter_get_pages - add user or kernel pages to a bio
* @bio: bio to add pages to
@@ -1300,6 +1312,9 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter,
if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)))
return -EIO;
+ if (iov_iter_is_dmabuf_map(iter) && !bio_dmabuf_map_valid(bio, iter))
+ return -EXDEV;
+
if (bio_iov_iter_set(bio, iter)) {
if (iov_iter_is_bvec(iter) &&
!bio_iov_bvec_aligned(bio, mem_align_mask))
diff --git a/block/fops.c b/block/fops.c
index 18a755f6e0b0..b36dde10a4ac 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -19,6 +19,7 @@
#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)
@@ -938,6 +939,7 @@ int bdev_init_dma_buf_io_ctx(struct file *file, struct block_device *bdev,
struct dma_buf_io_ctx *ctx)
{
struct gendisk *disk = bdev->bd_disk;
+ int ret;
if (!(file->f_flags & O_DIRECT))
return -EINVAL;
@@ -945,7 +947,10 @@ int bdev_init_dma_buf_io_ctx(struct file *file, struct block_device *bdev,
return -EOPNOTSUPP;
if (bdev_has_integrity_csum(bdev))
return -EOPNOTSUPP;
- return disk->fops->init_dma_buf_io_ctx(bdev, ctx);
+ ret = disk->fops->init_dma_buf_io_ctx(bdev, ctx);
+ if (!ret)
+ ctx->registered_devt = disk_devt(disk);
+ return ret;
}
EXPORT_SYMBOL_GPL(bdev_init_dma_buf_io_ctx);
diff --git a/include/linux/dma-buf-io.h b/include/linux/dma-buf-io.h
index b9bbeca1744f..d42a79f2ac9b 100644
--- a/include/linux/dma-buf-io.h
+++ b/include/linux/dma-buf-io.h
@@ -50,6 +50,8 @@ struct dma_buf_io_ctx {
void *dev_priv;
const struct dma_buf_io_ops *dev_ops;
+
+ dev_t registered_devt;
};
int dma_buf_io_ctx_create(struct file *file,
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC 3/4] iomap: add dma-buf direct I/O guards and registration helper
2026-10-16 9:19 [RFC 0/4] fs: support dma-buf backed direct I/O Anuj Gupta
2026-10-16 9:19 ` [RFC 1/4] block: factor out bdev_init_dma_buf_io_ctx() Anuj Gupta
2026-10-16 9:19 ` [RFC 2/4] block: refuse a dma-buf bio for a disk the buffer was not registered on Anuj Gupta
@ 2026-10-16 9:19 ` Anuj Gupta
2026-10-16 9:26 ` Christoph Hellwig
2026-10-16 9:19 ` [RFC 4/4] xfs: support dma-buf registered buffers for direct I/O Anuj Gupta
3 siblings, 1 reply; 9+ messages in thread
From: Anuj Gupta @ 2026-10-16 9:19 UTC (permalink / raw)
To: asml.silence, hch, djwong, cem, brauner, axboe
Cc: linux-block, linux-xfs, linux-fsdevel, joshi.k, anuj20.g,
nj.shetty
From: Nitesh Shetty <nj.shetty@samsung.com>
Direct I/O copies data from the CPU in three places, zero-filling
holes, inline data, and bounce pages. A dma-buf iterator has no
CPU-visible pages, so refuse it.
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.
Also add iomap_file_init_dma_buf_io_ctx(), so filesystems can register
without open-coding the DAX check. The filesystem picks the device,
iomap does the rest.
Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
---
fs/iomap/direct-io.c | 31 ++++++++++++++++++++++++++++++-
include/linux/iomap.h | 3 +++
2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index 8b4039d16ce8..fc40f4367ee7 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -427,6 +427,10 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
unsigned int alignment;
ssize_t ret = 0;
+ 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.
@@ -595,7 +599,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 length = iov_iter_zero(iomap_length(iter), dio->submit.iter);
+ loff_t length;
+
+ /* a device mapping cannot be zeroed from the CPU */
+ if (iov_iter_is_dmabuf_map(dio->submit.iter))
+ return -EOPNOTSUPP;
+
+ length = iov_iter_zero(iomap_length(iter), dio->submit.iter);
dio->size += length;
if (!length)
@@ -612,6 +622,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, which a device mapping bypasses */
+ if (iov_iter_is_dmabuf_map(iter))
+ return -EOPNOTSUPP;
+
if (WARN_ON_ONCE(!inline_data))
return -EIO;
@@ -710,6 +724,10 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
if (!iomi.len)
return NULL;
+ /* bouncing copies the data from the CPU, which a device mapping bypasses */
+ 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);
@@ -915,6 +933,17 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
}
EXPORT_SYMBOL_GPL(iomap_dio_rw);
+int iomap_file_init_dma_buf_io_ctx(struct file *file, struct block_device *bdev,
+ struct dma_buf_io_ctx *ctx)
+{
+ struct inode *inode = file_inode(file);
+
+ if (IS_DAX(inode))
+ return -EOPNOTSUPP;
+ return bdev_init_dma_buf_io_ctx(file, bdev, ctx);
+}
+EXPORT_SYMBOL_GPL(iomap_file_init_dma_buf_io_ctx);
+
struct iomap_dio_simple {
struct kiocb *iocb;
size_t size;
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index bc7ae6327dbf..ce97df81c644 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -682,6 +682,9 @@ struct iomap_dio *__iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
ssize_t iomap_dio_complete(struct iomap_dio *dio);
void iomap_dio_bio_end_io(struct bio *bio);
+int iomap_file_init_dma_buf_io_ctx(struct file *file, struct block_device *bdev,
+ struct dma_buf_io_ctx *ctx);
+
/*
* Fast path for small, block-aligned direct I/Os that map to a single
* contiguous on-disk extent.
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC 4/4] xfs: support dma-buf registered buffers for direct I/O
2026-10-16 9:19 [RFC 0/4] fs: support dma-buf backed direct I/O Anuj Gupta
` (2 preceding siblings ...)
2026-10-16 9:19 ` [RFC 3/4] iomap: add dma-buf direct I/O guards and registration helper Anuj Gupta
@ 2026-10-16 9:19 ` Anuj Gupta
2026-10-16 9:28 ` Christoph Hellwig
3 siblings, 1 reply; 9+ messages in thread
From: Anuj Gupta @ 2026-10-16 9:19 UTC (permalink / raw)
To: asml.silence, hch, djwong, cem, brauner, axboe
Cc: linux-block, linux-xfs, linux-fsdevel, joshi.k, anuj20.g,
nj.shetty
From: Nitesh Shetty <nj.shetty@samsung.com>
Add the init_dma_buf_io_ctx fop for XFS files.
XFS picks the device and calls the iomap layer with
the relevant device.
Refuse the iterator from every CPU-copy path: DAX, buffered
fallback from a -ENOTBLK direct write, and read/writes
without O_DIRECT.
If a file is switched between the data and realtime devices
after registration, the block layer cross-device check refuses
the I/O.
Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
---
fs/xfs/xfs_file.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 426a67b813a7..f97d5acfaf68 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -340,6 +340,11 @@ xfs_file_read_iter(
if (xfs_is_shutdown(mp))
return -EIO;
+ /* a device mapping can only be read by a direct I/O bio */
+ if (iov_iter_is_dmabuf_map(to) &&
+ (IS_DAX(inode) || !(iocb->ki_flags & IOCB_DIRECT)))
+ return -EOPNOTSUPP;
+
if (IS_DAX(inode))
ret = xfs_file_dax_read(iocb, to);
else if (iocb->ki_flags & IOCB_DIRECT)
@@ -1196,6 +1201,11 @@ xfs_file_write_iter(
return ret;
}
+ /* a device mapping can only be written by a direct I/O bio */
+ if (iov_iter_is_dmabuf_map(from) &&
+ (IS_DAX(inode) || !(iocb->ki_flags & IOCB_DIRECT)))
+ return -EOPNOTSUPP;
+
if (IS_DAX(inode))
return xfs_file_dax_write(iocb, from);
@@ -1209,6 +1219,9 @@ xfs_file_write_iter(
ret = xfs_file_dio_write(iocb, from);
if (ret != -ENOTBLK)
return ret;
+ /* the page cache cannot copy from a device mapping */
+ if (iov_iter_is_dmabuf_map(from))
+ return -EOPNOTSUPP;
}
if (xfs_is_zoned_inode(ip))
@@ -2173,10 +2186,27 @@ xfs_file_mmap_prepare(
return 0;
}
+/*
+ * A realtime file's data lives on the realtime device, anything else on the
+ * data device. If a file is switched between them after registration, the
+ * block layer cross-device check refuses the I/O.
+ */
+static int
+xfs_file_init_dma_buf_io_ctx(
+ struct file *file,
+ struct dma_buf_io_ctx *ctx)
+{
+ struct xfs_inode *ip = XFS_I(file_inode(file));
+
+ return iomap_file_init_dma_buf_io_ctx(file,
+ xfs_inode_buftarg(ip)->bt_bdev, ctx);
+}
+
const struct file_operations xfs_file_operations = {
.llseek = xfs_file_llseek,
.read_iter = xfs_file_read_iter,
.write_iter = xfs_file_write_iter,
+ .init_dma_buf_io_ctx = xfs_file_init_dma_buf_io_ctx,
.splice_read = xfs_file_splice_read,
.splice_write = iter_file_splice_write,
.iopoll = iocb_bio_iopoll,
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [RFC 1/4] block: factor out bdev_init_dma_buf_io_ctx()
2026-10-16 9:19 ` [RFC 1/4] block: factor out bdev_init_dma_buf_io_ctx() Anuj Gupta
@ 2026-10-16 9:23 ` Christoph Hellwig
0 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2026-10-16 9:23 UTC (permalink / raw)
To: Anuj Gupta
Cc: asml.silence, hch, djwong, cem, brauner, axboe, linux-block,
linux-xfs, linux-fsdevel, joshi.k, anuj20.g, nj.shetty
On Fri, Oct 16, 2026 at 02:49:11PM +0530, Anuj Gupta wrote:
> From: Nitesh Shetty <nj.shetty@samsung.com>
>
> Factor the checks and driver setup into an exported helper that takes
> an explicit block device, so filesystems can initialize a dma-buf I/O
> context for the device backing a regular file. The block-device file
> operation becomes a wrapper using file_bdev(), so its behavior is
> unchanged.
Please move hte helper out of block/fops.c, as that only is for
the block device file operations.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC 2/4] block: refuse a dma-buf bio for a disk the buffer was not registered on
2026-10-16 9:19 ` [RFC 2/4] block: refuse a dma-buf bio for a disk the buffer was not registered on Anuj Gupta
@ 2026-10-16 9:24 ` Christoph Hellwig
0 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2026-10-16 9:24 UTC (permalink / raw)
To: Anuj Gupta
Cc: asml.silence, hch, djwong, cem, brauner, axboe, linux-block,
linux-xfs, linux-fsdevel, joshi.k, anuj20.g, nj.shetty
On Fri, Oct 16, 2026 at 02:49:12PM +0530, Anuj Gupta wrote:
> From: Nitesh Shetty <nj.shetty@samsung.com>
>
> A registered dma-buf map belongs to the device it was mapped for.
> The device backing a file can change after registration. Record
> the registered disk's dev_t at init and refuse a bio that targets
> a different one.
Can you explain a bit better what this is trying to solve?
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC 3/4] iomap: add dma-buf direct I/O guards and registration helper
2026-10-16 9:19 ` [RFC 3/4] iomap: add dma-buf direct I/O guards and registration helper Anuj Gupta
@ 2026-10-16 9:26 ` Christoph Hellwig
0 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2026-10-16 9:26 UTC (permalink / raw)
To: Anuj Gupta
Cc: asml.silence, hch, djwong, cem, brauner, axboe, linux-block,
linux-xfs, linux-fsdevel, joshi.k, anuj20.g, nj.shetty
On Fri, Oct 16, 2026 at 02:49:13PM +0530, Anuj Gupta wrote:
> From: Nitesh Shetty <nj.shetty@samsung.com>
>
> Direct I/O copies data from the CPU in three places, zero-filling
> holes, inline data, and bounce pages. A dma-buf iterator has no
> CPU-visible pages, so refuse it.
>
> 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.
>
> Also add iomap_file_init_dma_buf_io_ctx(), so filesystems can register
> without open-coding the DAX check. The filesystem picks the device,
> iomap does the rest.
>
> Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
> Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
> ---
> fs/iomap/direct-io.c | 31 ++++++++++++++++++++++++++++++-
> include/linux/iomap.h | 3 +++
> 2 files changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
> index 8b4039d16ce8..fc40f4367ee7 100644
> --- a/fs/iomap/direct-io.c
> +++ b/fs/iomap/direct-io.c
> @@ -427,6 +427,10 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio)
> unsigned int alignment;
> ssize_t ret = 0;
>
> + 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.
> @@ -595,7 +599,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 length = iov_iter_zero(iomap_length(iter), dio->submit.iter);
> + loff_t length;
> +
> + /* a device mapping cannot be zeroed from the CPU */
> + if (iov_iter_is_dmabuf_map(dio->submit.iter))
> + return -EOPNOTSUPP;
> +
> + length = iov_iter_zero(iomap_length(iter), dio->submit.iter);
>
> dio->size += length;
> if (!length)
> @@ -612,6 +622,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, which a device mapping bypasses */
Overly lone line here.
> + /* bouncing copies the data from the CPU, which a device mapping bypasses */
.. and here. Note that could still copy to/from the device memory in
either case, but that's probably rather pointless at least for actual
device dmabufs. It might be useful for udmabuf or other kernel
allocations, though.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC 4/4] xfs: support dma-buf registered buffers for direct I/O
2026-10-16 9:19 ` [RFC 4/4] xfs: support dma-buf registered buffers for direct I/O Anuj Gupta
@ 2026-10-16 9:28 ` Christoph Hellwig
0 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2026-10-16 9:28 UTC (permalink / raw)
To: Anuj Gupta
Cc: asml.silence, hch, djwong, cem, brauner, axboe, linux-block,
linux-xfs, linux-fsdevel, joshi.k, anuj20.g, nj.shetty
On Fri, Oct 16, 2026 at 02:49:14PM +0530, Anuj Gupta wrote:
> From: Nitesh Shetty <nj.shetty@samsung.com>
>
> Add the init_dma_buf_io_ctx fop for XFS files.
> XFS picks the device and calls the iomap layer with
> the relevant device.
>
> Refuse the iterator from every CPU-copy path: DAX, buffered
> fallback from a -ENOTBLK direct write, and read/writes
> without O_DIRECT.
>
> If a file is switched between the data and realtime devices
> after registration, the block layer cross-device check refuses
> the I/O.
>
> Signed-off-by: Nitesh Shetty <nj.shetty@samsung.com>
> ---
> fs/xfs/xfs_file.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 426a67b813a7..f97d5acfaf68 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -340,6 +340,11 @@ xfs_file_read_iter(
> if (xfs_is_shutdown(mp))
> return -EIO;
>
> + /* a device mapping can only be read by a direct I/O bio */
> + if (iov_iter_is_dmabuf_map(to) &&
> + (IS_DAX(inode) || !(iocb->ki_flags & IOCB_DIRECT)))
> + return -EOPNOTSUPP;
Maybe move this into the actual methods for dax/buffered instead
to avoid extra conditionals? Same for the write side.
>
> @@ -1209,6 +1219,9 @@ xfs_file_write_iter(
> ret = xfs_file_dio_write(iocb, from);
> if (ret != -ENOTBLK)
> return ret;
> + /* the page cache cannot copy from a device mapping */
> + if (iov_iter_is_dmabuf_map(from))
> + return -EOPNOTSUPP;
I suspect these random fallbacks are going to cause trouble, but
I'm not really sure what to do about it either.
> +/*
> + * A realtime file's data lives on the realtime device, anything else on the
> + * data device. If a file is switched between them after registration, the
> + * block layer cross-device check refuses the I/O.
> + */
> +static int
> +xfs_file_init_dma_buf_io_ctx(
> + struct file *file,
> + struct dma_buf_io_ctx *ctx)
> +{
> + struct xfs_inode *ip = XFS_I(file_inode(file));
> +
> + return iomap_file_init_dma_buf_io_ctx(file,
> + xfs_inode_buftarg(ip)->bt_bdev, ctx);
> +}
Ah, this is where the previous cross check comes from. What about
simply disallowing toggling the RT flag with outstanding reservations
instead?
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-16 9:28 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 9:19 [RFC 0/4] fs: support dma-buf backed direct I/O Anuj Gupta
2026-10-16 9:19 ` [RFC 1/4] block: factor out bdev_init_dma_buf_io_ctx() Anuj Gupta
2026-10-16 9:23 ` Christoph Hellwig
2026-10-16 9:19 ` [RFC 2/4] block: refuse a dma-buf bio for a disk the buffer was not registered on Anuj Gupta
2026-10-16 9:24 ` Christoph Hellwig
2026-10-16 9:19 ` [RFC 3/4] iomap: add dma-buf direct I/O guards and registration helper Anuj Gupta
2026-10-16 9:26 ` Christoph Hellwig
2026-10-16 9:19 ` [RFC 4/4] xfs: support dma-buf registered buffers for direct I/O Anuj Gupta
2026-10-16 9:28 ` Christoph Hellwig
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.