From: Pavel Begunkov <asml.silence@gmail.com>
To: Caleb Sander Mateos <csander@purestorage.com>
Cc: "Jens Axboe" <axboe@kernel.dk>, "Keith Busch" <kbusch@kernel.org>,
"Christoph Hellwig" <hch@lst.de>,
"Sagi Grimberg" <sagi@grimberg.me>,
linux-block@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-nvme@lists.infradead.org, linux-fsdevel@vger.kernel.org,
io-uring@vger.kernel.org, linux-media@vger.kernel.org,
dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org,
"Alexander Viro" <viro@zeniv.linux.org.uk>,
"Christian Brauner" <brauner@kernel.org>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Sumit Semwal" <sumit.semwal@linaro.org>,
"Christian König" <christian.koenig@amd.com>,
"Nitesh Shetty" <nj.shetty@samsung.com>,
"Kanchan Joshi" <joshi.k@samsung.com>,
"Anuj Gupta" <anuj20.g@samsung.com>,
"Tushar Gohad" <tushar.gohad@intel.com>,
"William Power" <william.power@intel.com>,
"Phil Cayton" <phil.cayton@intel.com>,
"Jason Gunthorpe" <jgg@nvidia.com>,
"Damien Le Moal" <dlemoal@kernel.org>,
"Alasdair Kergon" <agk@redhat.com>,
"Mike Snitzer" <snitzer@kernel.org>,
"Mikulas Patocka" <mpatocka@redhat.com>,
"Benjamin Marzinski" <bmarzins@redhat.com>,
"Vishal Verma" <vishal.l.verma@intel.com>,
"David Sterba" <dsterba@suse.com>,
"Ilya Dryomov" <idryomov@gmail.com>,
dm-devel@lists.linux.dev, nvdimm@lists.linux.dev,
linux-btrfs@vger.kernel.org, ceph-devel@vger.kernel.org
Subject: Re: [PATCH v4 08/14] nvme-pci: implement dma_token backed requests
Date: Thu, 30 Jul 2026 11:41:30 +0100 [thread overview]
Message-ID: <de4ec386-42ba-41c3-bcbe-1fe8b2f71ba9@gmail.com> (raw)
In-Reply-To: <CADUfDZpwF0jp2e=+c3w_NjWPbnQ858bkSD731M6+x27jzgcJiw@mail.gmail.com>
On 7/29/26 20:43, Caleb Sander Mateos wrote:
> On Tue, Jul 28, 2026 at 2:35 PM Pavel Begunkov <asml.silence@gmail.com> wrote:
>>
>> Enable BIO_DMABUF_MAP backed requests. It creates a prp list for the
>> dmabuf when it's mapped, which is then used to initialise requests.
>>
>> Suggested-by: Keith Busch <kbusch@kernel.org>
>> Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
>> ---
>> drivers/nvme/host/core.c | 12 ++
>> drivers/nvme/host/nvme.h | 2 +
>> drivers/nvme/host/pci.c | 259 +++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 273 insertions(+)
>>
>> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
>> index 453c1f0b2dd0..ce66a1843bec 100644
>> --- a/drivers/nvme/host/core.c
>> +++ b/drivers/nvme/host/core.c
>> @@ -2676,6 +2676,17 @@ static int nvme_report_zones(struct gendisk *disk, sector_t sector,
>> #define nvme_report_zones NULL
>> #endif /* CONFIG_BLK_DEV_ZONED */
>>
>> +static int nvme_init_dma_buf_io_ctx(struct block_device *bdev,
>> + struct dma_buf_io_ctx *ctx)
>> +{
>> + struct nvme_ns *ns = bdev->bd_disk->private_data;
>> + struct nvme_ctrl *ctrl = ns->ctrl;
>> +
>> + if (!ctrl->ops->init_dma_buf_io_ctx)
>> + return -EINVAL;
>> + return ctrl->ops->init_dma_buf_io_ctx(ctrl, ctx);
>> +}
>> +
>> const struct block_device_operations nvme_bdev_ops = {
>> .owner = THIS_MODULE,
>> .ioctl = nvme_ioctl,
>> @@ -2686,6 +2697,7 @@ const struct block_device_operations nvme_bdev_ops = {
>> .get_unique_id = nvme_get_unique_id,
>> .report_zones = nvme_report_zones,
>> .pr_ops = &nvme_pr_ops,
>> + .init_dma_buf_io_ctx = nvme_init_dma_buf_io_ctx,
>> };
>>
>> static int nvme_wait_ready(struct nvme_ctrl *ctrl, u32 mask, u32 val,
>> diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
>> index 824651cc898d..034c31af8fec 100644
>> --- a/drivers/nvme/host/nvme.h
>> +++ b/drivers/nvme/host/nvme.h
>> @@ -652,6 +652,8 @@ struct nvme_ctrl_ops {
>> int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
>> void (*print_device_info)(struct nvme_ctrl *ctrl);
>> bool (*supports_pci_p2pdma)(struct nvme_ctrl *ctrl);
>> + int (*init_dma_buf_io_ctx)(struct nvme_ctrl *ctrl,
>> + struct dma_buf_io_ctx *ctx);
>> unsigned long (*get_virt_boundary)(struct nvme_ctrl *ctrl, bool is_admin);
>> };
>>
>> diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
>> index 69932d640b53..f1b67c191892 100644
>> --- a/drivers/nvme/host/pci.c
>> +++ b/drivers/nvme/host/pci.c
>> @@ -27,6 +27,8 @@
>> #include <linux/io-64-nonatomic-lo-hi.h>
>> #include <linux/io-64-nonatomic-hi-lo.h>
>> #include <linux/sed-opal.h>
>> +#include <linux/dma-buf-io.h>
>> +#include <linux/dma-resv.h>
>>
>> #include "trace.h"
>> #include "nvme.h"
>> @@ -393,6 +395,13 @@ struct nvme_queue {
>> struct completion delete_done;
>> };
>>
>> +struct nvme_dmabuf_map {
>> + struct dma_buf_io_map base;
>> + struct sg_table *sgt;
>> + unsigned nr_entries;
>> + dma_addr_t dma_list[];
>> +};
>> +
>> /* bits for iod->flags */
>> enum nvme_iod_flags {
>> /* this command has been aborted by the timeout handler */
>> @@ -859,6 +868,138 @@ static void nvme_free_descriptors(struct request *req)
>> }
>> }
>>
>> +static inline struct nvme_dmabuf_map *
>> +to_nvme_dmabuf_map(struct dma_buf_io_map *map)
>> +{
>> + return container_of(map, struct nvme_dmabuf_map, base);
>> +}
>> +
>> +static void nvme_dmabuf_map_sync_for_cpu(struct nvme_dev *nvme_dev,
>> + struct request *req)
>> +{
>> + struct device *dev = nvme_dev->dev;
>> + enum dma_data_direction dma_dir;
>> + struct bio *bio = req->bio;
>> + struct nvme_dmabuf_map *map = to_nvme_dmabuf_map(bio->bi_dmabuf_map);
>> + dma_addr_t *dma_list = map->dma_list;
>> + unsigned offset = bio->bi_iter.bi_offset;
>> + unsigned map_idx = offset / NVME_CTRL_PAGE_SIZE;
>> + int length = blk_rq_payload_bytes(req) +
>> + (offset & (NVME_CTRL_PAGE_SIZE - 1));
>> +
>> + dma_dir = rq_data_dir(req) == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
>> +
>> + while (length > 0) {
>> + dma_sync_single_for_cpu(dev, dma_list[map_idx++],
>> + NVME_CTRL_PAGE_SIZE, dma_dir);
>> + length -= NVME_CTRL_PAGE_SIZE;
>> + }
>> +}
>> +
>> +static void nvme_dmabuf_map_sync_for_device(struct nvme_dev *nvme_dev,
>> + struct request *req)
>> +{
>> + struct device *dev = nvme_dev->dev;
>> + enum dma_data_direction dma_dir;
>> + struct bio *bio = req->bio;
>> + struct nvme_dmabuf_map *map = to_nvme_dmabuf_map(bio->bi_dmabuf_map);
>> + dma_addr_t *dma_list = map->dma_list;
>> + unsigned offset = bio->bi_iter.bi_offset;
>> + unsigned map_idx = offset / NVME_CTRL_PAGE_SIZE;
>> + int length = blk_rq_payload_bytes(req) +
>> + (offset & (NVME_CTRL_PAGE_SIZE - 1));
>> +
>> + dma_dir = rq_data_dir(req) == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
>> +
>> + while (length > 0) {
>> + dma_sync_single_for_device(dev, dma_list[map_idx++],
>> + NVME_CTRL_PAGE_SIZE, dma_dir);
>> + length -= NVME_CTRL_PAGE_SIZE;
>> + }
>> +}
>> +
>> +static void nvme_rq_clean_dmabuf_map(struct nvme_dev *dev,
>> + struct request *req)
>> +{
>> + struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
>> +
>> + nvme_dmabuf_map_sync_for_cpu(dev, req);
>> +
>> + if (!(iod->flags & IOD_SINGLE_SEGMENT))
>> + nvme_free_descriptors(req);
>> +}
>> +
>> +static blk_status_t nvme_rq_setup_dmabuf_map(struct request *req,
>> + struct nvme_queue *nvmeq)
>> +{
>> + struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
>> + struct bio *bio = req->bio;
>> + struct nvme_dmabuf_map *map = to_nvme_dmabuf_map(bio->bi_dmabuf_map);
>> + unsigned bvec_done = bio->bi_iter.bi_offset;
>> + unsigned map_idx = bvec_done / NVME_CTRL_PAGE_SIZE;
>> + unsigned offset = bvec_done & (NVME_CTRL_PAGE_SIZE - 1);
>> + int length = blk_rq_payload_bytes(req) - (NVME_CTRL_PAGE_SIZE - offset);
>> + dma_addr_t *dma_list = map->dma_list;
>> + u64 prp1_dma = dma_list[map_idx++] + offset;
>> + u64 dma_addr, prp2_dma;
>> + dma_addr_t prp_dma;
>> + __le64 *prp_list;
>> + unsigned i;
>> +
>> + nvme_dmabuf_map_sync_for_device(nvmeq->dev, req);
>> +
>> + if (length <= 0) {
>> + prp2_dma = 0;
>> + goto done;
>> + }
>> +
>> + if (length <= NVME_CTRL_PAGE_SIZE) {
>> + prp2_dma = dma_list[map_idx];
>> + goto done;
>> + }
>> +
>> + if (DIV_ROUND_UP(length, NVME_CTRL_PAGE_SIZE) <=
>> + NVME_SMALL_POOL_SIZE / sizeof(__le64))
>> + iod->flags |= IOD_SMALL_DESCRIPTOR;
>> +
>> + prp_list = dma_pool_alloc(nvme_dma_pool(nvmeq, iod), GFP_ATOMIC,
>> + &prp_dma);
>
> I wonder if it's possible to perform the PRP list page allocations and
> initialization in nvme_dma_buf_io_map() instead of the I/O path. The
> NVMe dma_pools are per-NUMA-node linked lists protected by spinlocks,
> making them significant CPU hotspots. If the dmabuf registration set
> up a contiguous DMA-coherent list of PRP entries for the pages of the
> registered buffer, any command using the dmabuf and requiring at most
> 1 PRP list page (i.e. length <= 2 MB) could just set its PRP list
> pointer to an offset into the dmabuf's PRP list.
Possible to an extent, predecessor patches tried that, I left it for
later to keep the series simpler. I guess chaining won't work in
general case.
I mentioned this to Kanchan, Anuj and Nitesh before, they were up to
playing with nvme optimisations in general, and since sgl from Anuj
is ready, maybe they already have a prototype somewhere for that.
--
Pavel Begunkov
next prev parent reply other threads:[~2026-07-30 10:41 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-28 21:29 [PATCH v4 00/14] Add dmabuf read/write via io_uring Pavel Begunkov
2026-07-28 21:29 ` [PATCH v4 01/14] dma-buf: introduce initial file I/O infrastructure Pavel Begunkov
2026-07-29 6:59 ` Christoph Hellwig
2026-07-29 10:37 ` Pavel Begunkov
2026-07-29 11:28 ` Christoph Hellwig
2026-07-29 13:11 ` Pavel Begunkov
2026-08-05 8:27 ` Christian König
2026-08-05 10:59 ` Pavel Begunkov
2026-08-06 7:29 ` Christian König
2026-08-06 1:37 ` [Linaro-mm-sig] " Matthew Brost
2026-07-28 21:29 ` [PATCH v4 02/14] iov_iter: add iterator type for dmabuf maps Pavel Begunkov
2026-07-29 6:59 ` Christoph Hellwig
2026-07-29 10:40 ` Pavel Begunkov
2026-07-28 21:29 ` [PATCH v4 03/14] block: rename bi_bvec_done Pavel Begunkov
2026-07-29 7:00 ` Christoph Hellwig
2026-07-28 21:29 ` [PATCH v4 04/14] block: always adjust bi_offset on bio_advance_iter Pavel Begunkov
2026-07-29 7:00 ` Christoph Hellwig
2026-07-28 21:29 ` [PATCH v4 05/14] block: move bvec init into __bio_clone Pavel Begunkov
2026-07-29 7:00 ` Christoph Hellwig
2026-07-28 21:29 ` [PATCH v4 06/14] block: introduce dma map backed bio type Pavel Begunkov
2026-07-29 7:07 ` Christoph Hellwig
2026-07-29 11:03 ` Pavel Begunkov
2026-07-28 21:29 ` [PATCH v4 07/14] block: forward init_dma_buf_io_ctx to drivers Pavel Begunkov
2026-07-29 7:07 ` Christoph Hellwig
2026-07-28 21:29 ` [PATCH v4 08/14] nvme-pci: implement dma_token backed requests Pavel Begunkov
2026-07-29 7:10 ` Christoph Hellwig
2026-07-29 10:49 ` Pavel Begunkov
2026-07-29 19:43 ` Caleb Sander Mateos
2026-07-30 10:41 ` Pavel Begunkov [this message]
2026-07-30 11:36 ` Anuj Gupta/Anuj Gupta
2026-07-30 16:17 ` Caleb Sander Mateos
2026-07-28 21:29 ` [PATCH v4 09/14] nvme-pci: add SGL support for the dmabuf path Pavel Begunkov
2026-07-29 7:21 ` Christoph Hellwig
2026-07-29 10:17 ` Anuj Gupta/Anuj Gupta
2026-07-29 11:31 ` Christoph Hellwig
2026-07-29 11:45 ` Pavel Begunkov
2026-07-29 11:55 ` Christoph Hellwig
2026-07-29 13:08 ` Pavel Begunkov
2026-07-28 21:29 ` [PATCH v4 10/14] io_uring/rsrc: introduce buf registration structure Pavel Begunkov
2026-07-28 21:29 ` [PATCH v4 11/14] io_uring/rsrc: extend buffer update Pavel Begunkov
2026-07-29 13:31 ` Anuj Gupta/Anuj Gupta
2026-07-29 13:39 ` Pavel Begunkov
2026-07-28 21:29 ` [PATCH v4 12/14] io_uring/rsrc: add uncloneable regbuf flag Pavel Begunkov
2026-07-28 21:29 ` [PATCH v4 13/14] io_uring/rsrc: add regbuf import flags Pavel Begunkov
2026-07-28 21:29 ` [PATCH v4 14/14] io_uring/rsrc: add dmabuf backed registered buffers Pavel Begunkov
2026-07-29 13:30 ` Anuj Gupta/Anuj Gupta
2026-07-29 13:43 ` Pavel Begunkov
2026-07-29 16:52 ` Anuj gupta
2026-07-29 17:45 ` Pavel Begunkov
2026-07-29 6:54 ` [PATCH v4 00/14] Add dmabuf read/write via io_uring Christoph Hellwig
2026-07-29 11:28 ` Pavel Begunkov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=de4ec386-42ba-41c3-bcbe-1fe8b2f71ba9@gmail.com \
--to=asml.silence@gmail.com \
--cc=agk@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=anuj20.g@samsung.com \
--cc=axboe@kernel.dk \
--cc=bmarzins@redhat.com \
--cc=brauner@kernel.org \
--cc=ceph-devel@vger.kernel.org \
--cc=christian.koenig@amd.com \
--cc=csander@purestorage.com \
--cc=dlemoal@kernel.org \
--cc=dm-devel@lists.linux.dev \
--cc=dri-devel@lists.freedesktop.org \
--cc=dsterba@suse.com \
--cc=hch@lst.de \
--cc=idryomov@gmail.com \
--cc=io-uring@vger.kernel.org \
--cc=jgg@nvidia.com \
--cc=joshi.k@samsung.com \
--cc=kbusch@kernel.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=mpatocka@redhat.com \
--cc=nj.shetty@samsung.com \
--cc=nvdimm@lists.linux.dev \
--cc=phil.cayton@intel.com \
--cc=sagi@grimberg.me \
--cc=snitzer@kernel.org \
--cc=sumit.semwal@linaro.org \
--cc=tushar.gohad@intel.com \
--cc=viro@zeniv.linux.org.uk \
--cc=vishal.l.verma@intel.com \
--cc=william.power@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.