[PATCH v6 05/13] block: add dma-buf support for raw bdev

From: Pavel Begunkov

Date: Mon Sep 21 2026 - 09:43:17 EST


Add a simple proxy implementation of init_dma_buf_io_ctx() forwarding
the call to a new struct block_device_operations operation. Also reject
dma-buf backed iterators for buffered IO.

Reviewed-by: Christoph Hellwig <hch@xxxxxx>
[pavel: reject dma-buf without O_DIRECT]
Signed-off-by: Pavel Begunkov <asml.silence@xxxxxxxxx>
---
block/fops.c | 22 +++++++++++++++++++++-
include/linux/blkdev.h | 2 ++
2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/block/fops.c b/block/fops.c
index 09fa42f8d8fa..0252d26969a4 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -782,7 +782,8 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)

if (iocb->ki_flags & IOCB_DIRECT) {
ret = blkdev_direct_write(iocb, from);
- if (ret >= 0 && iov_iter_count(from)) {
+ if (ret >= 0 && iov_iter_count(from) &&
+ !iov_iter_is_dmabuf_map(from)) {
ret = direct_write_fallback(iocb, from, ret,
blkdev_buffered_write(iocb, from));
need_sync = true;
@@ -795,6 +796,9 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
need_sync = true;
}
} else {
+ if (unlikely(iov_iter_is_dmabuf_map(from)))
+ return -EOPNOTSUPP;
+
/*
* Take i_rwsem and invalidate_lock to avoid racing with
* set_blocksize changing i_blkbits/folio order and punching
@@ -850,6 +854,8 @@ static ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
if (ret < 0 || !count)
goto reexpand;
}
+ if (unlikely(iov_iter_is_dmabuf_map(to)))
+ return -EOPNOTSUPP;

/*
* Take i_rwsem and invalidate_lock to avoid racing with set_blocksize
@@ -953,6 +959,19 @@ 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)
+{
+ struct block_device *bdev = file_bdev(file);
+ struct gendisk *disk = bdev->bd_disk;
+
+ if (!(file->f_flags & O_DIRECT))
+ return -EINVAL;
+ if (!disk->fops->init_dma_buf_io_ctx)
+ return -EOPNOTSUPP;
+ return disk->fops->init_dma_buf_io_ctx(bdev, ctx);
+}
+
const struct file_operations def_blk_fops = {
.open = blkdev_open,
.release = blkdev_release,
@@ -971,6 +990,7 @@ const struct file_operations def_blk_fops = {
.fallocate = blkdev_fallocate,
.uring_cmd = blkdev_uring_cmd,
.fop_flags = FOP_BUFFER_RASYNC | FOP_DONTCACHE,
+ .init_dma_buf_io_ctx = blkdev_init_dma_buf_io_ctx,
};

static __init int blkdev_init(void)
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d003a9d2d1f6..2d5c30823aab 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1599,6 +1599,8 @@ struct block_device_operations {
/* returns the length of the identifier or a negative errno: */
int (*get_unique_id)(struct gendisk *disk, u8 id[16],
enum blk_unique_id id_type);
+ int (*init_dma_buf_io_ctx)(struct block_device *,
+ struct dma_buf_io_ctx *);
struct module *owner;
const struct pr_ops *pr_ops;

--
2.54.0