From: Ming Lei <tom.leiming@gmail.com>
To: Caleb Sander Mateos <csander@purestorage.com>
Cc: Jens Axboe <axboe@kernel.dk>,
linux-block@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 5/6] ublk: add UBLK_F_IO_DESC_SIZE
Date: Thu, 30 Jul 2026 10:14:20 -0500 [thread overview]
Message-ID: <amtqTIZiUgOrSJmg@fedora-laptop> (raw)
In-Reply-To: <20260729012951.3744582-6-csander@purestorage.com>
On Tue, Jul 28, 2026 at 07:29:50PM -0600, Caleb Sander Mateos wrote:
> ublk passes the parameters of incoming I/O in memory shared between the
> kernel ublk driver and userspace ublk server in struct ublksrv_io_desc.
> The size of this struct is currently fixed to 24 bytes, which has been
> an obstacle to extending it with additional fields [1]. Additionally,
> with multiple ublk server threads handling I/Os from the same ublk queue
> (possible with UBLK_F_PER_IO_DAEMON or UBLK_F_BATCH_IO), false sharing
> results from adjacent io_descs sharing the same cache line.
>
> Add a ublk feature UBLK_F_IO_DESC_SIZE to allow a ublk server to
> override the size of each io_desc. The size must be at least 24 and a
> multiple of 8 to store a properly-aligned struct ublksrv_io_desc. The
> struct ublksrv_io_desc is located at the beginning of each io_desc and
> the remainder is padding. The mmap() performed for each queue must have
> a length of queue_depth * io_desc_size, rounded up to the page size. The
> mmap() offset must be q_id * UBLK_MAX_QUEUE_DEPTH * io_desc_size, also
> rounded up to the page size.
>
> [1]: https://lore.kernel.org/linux-block/aV8QfvaNO5P6vOs6@fedora/
>
> Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
> ---
> drivers/block/ublk_drv.c | 35 ++++++++++++++++++++++++-----------
> include/uapi/linux/ublk_cmd.h | 5 ++++-
> 2 files changed, 28 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> index 46f5ab13f87e..1da45e382253 100644
> --- a/drivers/block/ublk_drv.c
> +++ b/drivers/block/ublk_drv.c
> @@ -87,11 +87,12 @@
> | UBLK_F_BUF_REG_OFF_DAEMON \
> | (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY) ? UBLK_F_INTEGRITY : 0) \
> | UBLK_F_SAFE_STOP_DEV \
> | UBLK_F_BATCH_IO \
> | UBLK_F_NO_AUTO_PART_SCAN \
> - | UBLK_F_SHMEM_ZC)
> + | UBLK_F_SHMEM_ZC \
> + | UBLK_F_IO_DESC_SIZE)
>
> #define UBLK_F_ALL_RECOVERY_FLAGS (UBLK_F_USER_RECOVERY \
> | UBLK_F_USER_RECOVERY_REISSUE \
> | UBLK_F_USER_RECOVERY_FAIL_IO)
>
> @@ -237,10 +238,11 @@ struct ublk_io {
> } ____cacheline_aligned_in_smp;
>
> struct ublk_queue {
> u16 q_id;
> u16 q_depth;
> + u16 io_desc_size;
>
> unsigned long flags;
> struct ublksrv_io_desc *io_cmd_buf;
>
> bool force_abort;
> @@ -403,11 +405,11 @@ static inline void ublk_io_evts_deinit(struct ublk_queue *q)
> }
>
> static inline struct ublksrv_io_desc *
> ublk_get_iod(const struct ublk_queue *ubq, u16 tag)
> {
> - return &ubq->io_cmd_buf[tag];
> + return (void *)ubq->io_cmd_buf + tag * (size_t)ubq->io_desc_size;
> }
>
> static inline bool ublk_support_zero_copy(const struct ublk_queue *ubq)
> {
> return ubq->flags & UBLK_F_SUPPORT_ZERO_COPY;
> @@ -1246,23 +1248,24 @@ static inline struct ublksrv_io_desc *
> ublk_queue_cmd_buf(struct ublk_device *ub, u16 q_id)
> {
> return ublk_get_queue(ub, q_id)->io_cmd_buf;
> }
>
> -static inline int __ublk_queue_cmd_buf_size(u16 depth)
> +static inline size_t __ublk_queue_cmd_buf_size(const struct ublk_device *ub,
> + u16 depth)
> {
> - return round_up(depth * sizeof(struct ublksrv_io_desc), PAGE_SIZE);
> + return round_up(depth * (size_t)ub->dev_info.io_desc_size, PAGE_SIZE);
> }
>
> -static inline int ublk_queue_cmd_buf_size(struct ublk_device *ub)
> +static inline size_t ublk_queue_cmd_buf_size(const struct ublk_device *ub)
> {
> - return __ublk_queue_cmd_buf_size(ub->dev_info.queue_depth);
> + return __ublk_queue_cmd_buf_size(ub, ub->dev_info.queue_depth);
> }
>
> -static int ublk_max_cmd_buf_size(void)
> +static size_t ublk_max_cmd_buf_size(const struct ublk_device *ub)
> {
> - return __ublk_queue_cmd_buf_size(UBLK_MAX_QUEUE_DEPTH);
> + return __ublk_queue_cmd_buf_size(ub, UBLK_MAX_QUEUE_DEPTH);
> }
>
> /*
> * Should I/O outstanding to the ublk server when it exits be reissued?
> * If not, outstanding I/O will get errors.
> @@ -2648,11 +2651,11 @@ static int ublk_ch_release(struct inode *inode, struct file *filp)
> /* map pre-allocated per-queue cmd buffer to ublksrv daemon */
> static int ublk_ch_mmap(struct file *filp, struct vm_area_struct *vma)
> {
> struct ublk_device *ub = filp->private_data;
> size_t sz = vma->vm_end - vma->vm_start;
> - unsigned max_sz = ublk_max_cmd_buf_size();
> + size_t max_sz = ublk_max_cmd_buf_size(ub);
> unsigned long pfn, end, phys_off = vma->vm_pgoff << PAGE_SHIFT;
> int ret = 0;
> u16 q_id;
>
> spin_lock(&ub->lock);
> @@ -4174,11 +4177,11 @@ static const struct file_operations ublk_ch_batch_io_fops = {
> .mmap = ublk_ch_mmap,
> };
>
> static void __ublk_deinit_queue(struct ublk_device *ub, struct ublk_queue *ubq)
> {
> - int size;
> + size_t size;
> u16 i;
>
> size = ublk_queue_cmd_buf_size(ub);
>
> for (i = 0; i < ubq->q_depth; i++) {
> @@ -4227,11 +4230,12 @@ static int ublk_init_queue(struct ublk_device *ub, u16 q_id)
> u16 depth = ub->dev_info.queue_depth;
> gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO;
> struct ublk_queue *ubq;
> struct page *page;
> int numa_node;
> - int size, ret;
> + size_t size;
> + int ret;
> u16 i;
>
> /* Determine NUMA node based on queue's CPU affinity */
> numa_node = ublk_get_queue_numa_node(ub, q_id);
>
> @@ -4252,10 +4256,11 @@ static int ublk_init_queue(struct ublk_device *ub, u16 q_id)
> if (!page) {
> kvfree(ubq);
> return -ENOMEM;
> }
> ubq->io_cmd_buf = page_address(page);
> + ubq->io_desc_size = ub->dev_info.io_desc_size;
>
> for (i = 0; i < ubq->q_depth; i++)
> spin_lock_init(&ubq->ios[i].lock);
>
> if (ublk_dev_support_batch_io(ub)) {
> @@ -4736,10 +4741,18 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
>
> /* User copy is required to access integrity buffer */
> if (info.flags & UBLK_F_INTEGRITY && !(info.flags & UBLK_F_USER_COPY))
> return -EINVAL;
>
> + if (info.flags & UBLK_F_IO_DESC_SIZE) {
> + if (info.io_desc_size < sizeof(struct ublksrv_io_desc) ||
> + info.io_desc_size % _Alignof(struct ublksrv_io_desc))
> + return -EINVAL;
> + } else {
> + info.io_desc_size = sizeof(struct ublksrv_io_desc);
> + }
> +
No upper bound on io_desc_size.
Also Missing selftest update — this causes generic_13 failure.
New feature needs sanity test to show it working at least.
Thanks,
Ming
next prev parent reply other threads:[~2026-07-30 15:14 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-29 1:29 [PATCH 0/6] ublk: io_desc optimizations Caleb Sander Mateos
2026-07-29 1:29 ` [PATCH 1/6] ublk: consistently use u16 for queue and tag numbers Caleb Sander Mateos
2026-07-29 14:51 ` Ming Lei
2026-07-29 1:29 ` [PATCH 2/6] ublk: remove struct ublk_zoned_report_desc's operation field Caleb Sander Mateos
2026-07-29 14:58 ` Ming Lei
2026-07-29 1:29 ` [PATCH 3/6] ublk: split request validation from io_desc init Caleb Sander Mateos
2026-07-30 14:37 ` Ming Lei
2026-07-29 1:29 ` [PATCH 4/6] ublk: initialize io_desc on daemon task Caleb Sander Mateos
2026-07-30 15:10 ` Ming Lei
2026-07-29 1:29 ` [PATCH 5/6] ublk: add UBLK_F_IO_DESC_SIZE Caleb Sander Mateos
2026-07-30 15:14 ` Ming Lei [this message]
2026-07-30 15:52 ` Caleb Sander Mateos
2026-07-29 1:29 ` [PATCH 6/6] ublk: lift need_map check out of ublk_{,un}map_io() Caleb Sander Mateos
2026-07-30 15:17 ` Ming Lei
2026-07-30 15:54 ` Caleb Sander Mateos
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=amtqTIZiUgOrSJmg@fedora-laptop \
--to=tom.leiming@gmail.com \
--cc=axboe@kernel.dk \
--cc=csander@purestorage.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox