All of lore.kernel.org
 help / color / mirror / Atom feed
From: Caleb Sander Mateos <csander@purestorage.com>
To: Ming Lei <tom.leiming@gmail.com>, Jens Axboe <axboe@kernel.dk>,
	Shuah Khan <shuah@kernel.org>
Cc: linux-block@vger.kernel.org, linux-kselftest@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Caleb Sander Mateos <csander@purestorage.com>
Subject: [PATCH v2 6/8] selftests: ublk: add support for --io_desc_size
Date: Mon,  3 Aug 2026 15:14:38 -0600	[thread overview]
Message-ID: <20260803211441.2538144-7-csander@purestorage.com> (raw)
In-Reply-To: <20260803211441.2538144-1-csander@purestorage.com>

Add an optional --io_desc_size argument to the kublk add/recover
commands to enable UBLK_F_IO_DESC on the ublk device. The mmap()
arguments and ublk_get_iod() computation are adjusted accordingly.

Display the configured io_desc_size in the kublk list output for ublk
devices with UBLK_F_IO_DESC.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
 tools/testing/selftests/ublk/kublk.c | 29 +++++++++++++++++++---------
 tools/testing/selftests/ublk/kublk.h |  6 ++++--
 2 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index 5c4a1f18d0a3..0e3e2d74cc4d 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -350,10 +350,12 @@ static void ublk_ctrl_dump(struct ublk_dev *dev)
 			info->dev_id, info->nr_hw_queues, info->queue_depth,
 			1 << p.basic.logical_bs_shift, p.basic.dev_sectors);
 	ublk_log("\tmax rq size %d daemon pid %d flags 0x%llx state %s\n",
 			info->max_io_buf_bytes, info->ublksrv_pid, info->flags,
 			ublk_dev_state_desc(dev));
+	if (info->flags & UBLK_F_IO_DESC_SIZE)
+		ublk_log("\tio_desc_size %u\n", info->io_desc_size);
 
 	if (affinity) {
 		char buf[512];
 		int i;
 
@@ -398,26 +400,26 @@ static struct ublk_dev *ublk_ctrl_init(void)
 	dev->nr_fds = 1;
 
 	return dev;
 }
 
-static int __ublk_queue_cmd_buf_sz(unsigned depth)
+static size_t __ublk_queue_cmd_buf_sz(const struct ublk_queue *q, __u16 depth)
 {
-	int size =  depth * sizeof(struct ublksrv_io_desc);
-	unsigned int page_sz = getpagesize();
+	size_t size = depth * (size_t)q->io_desc_size;
+	size_t page_sz = getpagesize();
 
 	return round_up(size, page_sz);
 }
 
-static int ublk_queue_max_cmd_buf_sz(void)
+static size_t ublk_queue_max_cmd_buf_sz(const struct ublk_queue *q)
 {
-	return __ublk_queue_cmd_buf_sz(UBLK_MAX_QUEUE_DEPTH);
+	return __ublk_queue_cmd_buf_sz(q, UBLK_MAX_QUEUE_DEPTH);
 }
 
-static int ublk_queue_cmd_buf_sz(struct ublk_queue *q)
+static size_t ublk_queue_cmd_buf_sz(const struct ublk_queue *q)
 {
-	return __ublk_queue_cmd_buf_sz(q->q_depth);
+	return __ublk_queue_cmd_buf_sz(q, q->q_depth);
 }
 
 static void ublk_queue_deinit(struct ublk_queue *q)
 {
 	int i;
@@ -451,26 +453,27 @@ static int ublk_queue_init(struct ublk_queue *q, unsigned long long extra_flags,
 			   __u8 metadata_size)
 {
 	struct ublk_dev *dev = q->dev;
 	int depth = dev->dev_info.queue_depth;
 	int i;
-	int cmd_buf_size, io_buf_size, integrity_size;
+	size_t cmd_buf_size, io_buf_size, integrity_size;
 	unsigned long off;
 
 	pthread_spin_init(&q->lock, PTHREAD_PROCESS_PRIVATE);
 	q->tgt_ops = dev->tgt.ops;
 	q->flags = 0;
 	q->q_depth = depth;
 	q->flags = dev->dev_info.flags;
 	q->flags |= extra_flags;
 	q->metadata_size = metadata_size;
+	q->io_desc_size = dev->dev_info.io_desc_size;
 
 	/* Cache fd in queue for fast path access */
 	q->ublk_fd = dev->fds[0];
 
 	cmd_buf_size = ublk_queue_cmd_buf_sz(q);
-	off = UBLKSRV_CMD_BUF_OFFSET + q->q_id * ublk_queue_max_cmd_buf_sz();
+	off = UBLKSRV_CMD_BUF_OFFSET + q->q_id * ublk_queue_max_cmd_buf_sz(q);
 	q->io_cmd_buf = mmap(0, cmd_buf_size, PROT_READ,
 			MAP_SHARED | MAP_POPULATE, dev->fds[0], off);
 	if (q->io_cmd_buf == MAP_FAILED) {
 		ublk_err("ublk dev %d queue %d map io_cmd_buf failed %m\n",
 				q->dev->dev_info.dev_id, q->q_id);
@@ -1706,10 +1709,11 @@ static int __cmd_dev_add(const struct dev_ctx *ctx)
 
 	info = &dev->dev_info;
 	info->dev_id = ctx->dev_id;
 	info->nr_hw_queues = nr_queues;
 	info->queue_depth = depth;
+	info->io_desc_size = ctx->io_desc_size;
 	info->flags = ctx->flags;
 	if ((features & UBLK_F_QUIESCE) &&
 			(info->flags & UBLK_F_USER_RECOVERY))
 		info->flags |= UBLK_F_QUIESCE;
 	dev->nthreads = nthreads;
@@ -2067,10 +2071,11 @@ static void __cmd_create_help(char *exe, bool recovery)
 	printf("\t[-e 0|1 ] [-i 0|1] [--no_ublk_fixed_fd]\n");
 	printf("\t[--nthreads threads] [--per_io_tasks]\n");
 	printf("\t[--integrity_capable] [--integrity_reftag] [--metadata_size SIZE] "
 		 "[--pi_offset OFFSET] [--csum_type ip|t10dif|nvme] [--tag_size SIZE]\n");
 	printf("\t[--batch|-b] [--no_auto_part_scan]\n");
+	printf("\t[--io_desc_size SIZE]\n");
 	printf("\t[target options] [backfile1] [backfile2] ...\n");
 	printf("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n");
 	printf("\tdefault: nthreads=nr_queues");
 
 	for (i = 0; i < ARRAY_SIZE(tgt_ops_list); i++) {
@@ -2144,10 +2149,11 @@ int main(int argc, char *argv[])
 		{ "batch",              0,      NULL, 'b'},
 		{ "no_auto_part_scan",	0,	NULL,  0 },
 		{ "shmem_zc",		0,	NULL,  0  },
 		{ "htlb",		1,	NULL,  0  },
 		{ "rdonly_shmem_buf",	0,	NULL,  0  },
+		{ "io_desc_size",	1,	NULL,  0  },
 		{ 0, 0, 0, 0 }
 	};
 	const struct ublk_tgt_ops *ops = NULL;
 	int option_idx, opt;
 	const char *cmd = argv[1];
@@ -2156,10 +2162,11 @@ int main(int argc, char *argv[])
 		.queue_depth	=	128,
 		.nr_hw_queues	=	2,
 		.dev_id		=	-1,
 		.tgt_type	=	"unknown",
 		.csum_type	=	LBMD_PI_CSUM_NONE,
+		.io_desc_size	=	sizeof(struct ublksrv_io_desc),
 	};
 	int ret = -EINVAL, i;
 	int tgt_argc = 1;
 	char *tgt_argv[MAX_NR_TGT_ARG] = { NULL };
 	int value;
@@ -2265,10 +2272,14 @@ int main(int argc, char *argv[])
 				ctx.flags |= UBLK_F_SHMEM_ZC;
 			if (!strcmp(longopts[option_idx].name, "htlb"))
 				ctx.htlb_path = strdup(optarg);
 			if (!strcmp(longopts[option_idx].name, "rdonly_shmem_buf"))
 				ctx.rdonly_shmem_buf = 1;
+			if (!strcmp(longopts[option_idx].name, "io_desc_size")) {
+				ctx.flags |= UBLK_F_IO_DESC_SIZE;
+				ctx.io_desc_size = strtoul(optarg, NULL, 0);
+			}
 			break;
 		case '?':
 			/*
 			 * target requires every option must have argument
 			 */
diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h
index 742c41d77df1..15b56ff45bb6 100644
--- a/tools/testing/selftests/ublk/kublk.h
+++ b/tools/testing/selftests/ublk/kublk.h
@@ -85,10 +85,11 @@ struct dev_ctx {
 	__u32 integrity_flags;
 	__u8 metadata_size;
 	__u8 pi_offset;
 	__u8 csum_type;
 	__u8 tag_size;
+	__u16 io_desc_size;
 
 	int _evtfd;
 	int _shmid;
 
 	/* built from shmem, only for ublk_dump_dev() */
@@ -185,10 +186,11 @@ struct ublk_queue {
 #define UBLKS_Q_NO_UBLK_FIXED_FD	(1ULL << 62)
 #define UBLKS_Q_PREPARED	(1ULL << 61)
 	__u64 flags;
 	int ublk_fd;	/* cached ublk char device fd */
 	__u8 metadata_size;
+	__u16 io_desc_size;
 	struct ublk_io ios[UBLK_QUEUE_DEPTH];
 
 	/* used for prep io commands */
 	pthread_spinlock_t lock;
 };
@@ -459,13 +461,13 @@ static inline void ublk_mark_io_done(struct ublk_io *io, int res)
 {
 	io->flags |= (UBLKS_IO_NEED_COMMIT_RQ_COMP | UBLKS_IO_FREE);
 	io->result = res;
 }
 
-static inline const struct ublksrv_io_desc *ublk_get_iod(const struct ublk_queue *q, int tag)
+static inline const struct ublksrv_io_desc *ublk_get_iod(const struct ublk_queue *q, __u16 tag)
 {
-	return &q->io_cmd_buf[tag];
+	return (void *)q->io_cmd_buf + tag * (size_t)q->io_desc_size;
 }
 
 static inline void ublk_set_sqe_cmd_op(struct io_uring_sqe *sqe, __u32 cmd_op)
 {
 	__u32 *addr = (__u32 *)&sqe->off;
-- 
2.54.0


  parent reply	other threads:[~2026-08-03 21:14 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-03 21:14 [PATCH v2 0/8] ublk: io_desc optimizations Caleb Sander Mateos
2026-08-03 21:14 ` [PATCH v2 1/8] ublk: consistently use u16 for queue and tag numbers Caleb Sander Mateos
2026-08-03 21:14 ` [PATCH v2 2/8] ublk: remove struct ublk_zoned_report_desc's operation field Caleb Sander Mateos
2026-08-03 21:14 ` [PATCH v2 3/8] ublk: split request validation from io_desc init Caleb Sander Mateos
2026-08-03 21:14 ` [PATCH v2 4/8] ublk: initialize io_desc on daemon task Caleb Sander Mateos
2026-08-03 21:14 ` [PATCH v2 5/8] ublk: add UBLK_F_IO_DESC_SIZE Caleb Sander Mateos
2026-08-03 21:14 ` Caleb Sander Mateos [this message]
2026-08-03 21:14 ` [PATCH v2 7/8] selftests: ublk: add UBLK_F_IO_DESC_SIZE test Caleb Sander Mateos
2026-08-03 21:14 ` [PATCH v2 8/8] ublk: lift checks out of ublk_{,un}map_io() Caleb Sander Mateos
2026-08-04  2:32 ` [PATCH v2 0/8] ublk: io_desc optimizations Jens Axboe

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=20260803211441.2538144-7-csander@purestorage.com \
    --to=csander@purestorage.com \
    --cc=axboe@kernel.dk \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=shuah@kernel.org \
    --cc=tom.leiming@gmail.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.