Skip to content

Commit 93b1e69

Browse files
committed
uring: move io_uring code to new file
Factor out the io_uring code into a new file to make it easier to move the nvme_get_log code as well. While at it, initialize the ring lazily on the first transport handle creation instead of creating and tearing it down for each nvme_get_log call. Signed-off-by: Daniel Wagner <[email protected]>
1 parent e31d29a commit 93b1e69

6 files changed

Lines changed: 204 additions & 135 deletions

File tree

libnvme/src/meson.build

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ if want_fabrics
4646
]
4747
endif
4848

49+
if liburing_dep.found()
50+
sources += 'nvme/uring.c'
51+
endif
52+
4953
if json_c_dep.found()
5054
sources += 'nvme/json.c'
5155
else

libnvme/src/nvme/ioctl.c

Lines changed: 5 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
#include <sys/ioctl.h>
1717
#include <sys/stat.h>
1818

19-
#ifdef CONFIG_LIBURING
20-
#include <liburing.h>
21-
#endif
22-
2319
#include <ccan/build_assert/build_assert.h>
2420
#include <ccan/endian/endian.h>
2521
#include <ccan/minmax/minmax.h>
@@ -219,95 +215,6 @@ static void nvme_init_env(void)
219215
force_4k = true;
220216
}
221217

222-
#ifdef CONFIG_LIBURING
223-
enum {
224-
IO_URING_NOT_AVAILABLE,
225-
IO_URING_AVAILABLE,
226-
} io_uring_kernel_support = IO_URING_NOT_AVAILABLE;
227-
228-
/*
229-
* gcc specific attribute, call automatically on the library loading.
230-
* if IORING_OP_URING_CMD is not supported, fallback to ioctl interface.
231-
*
232-
* The uring API expects the command of type struct nvme_passthru_cmd64.
233-
*/
234-
__attribute__((constructor))
235-
static void nvme_uring_cmd_probe()
236-
{
237-
struct io_uring_probe *probe = io_uring_get_probe();
238-
239-
if (!probe)
240-
return;
241-
242-
if (!io_uring_opcode_supported(probe, IORING_OP_URING_CMD))
243-
return;
244-
245-
io_uring_kernel_support = IO_URING_AVAILABLE;
246-
}
247-
248-
static int nvme_uring_cmd_setup(struct io_uring *ring)
249-
{
250-
if (io_uring_queue_init(NVME_URING_ENTRIES, ring,
251-
IORING_SETUP_SQE128 | IORING_SETUP_CQE32))
252-
return -errno;
253-
return 0;
254-
}
255-
256-
static void nvme_uring_cmd_exit(struct io_uring *ring)
257-
{
258-
io_uring_queue_exit(ring);
259-
}
260-
261-
static int nvme_uring_cmd_admin_passthru_async(struct nvme_transport_handle *hdl,
262-
struct io_uring *ring, struct nvme_passthru_cmd *cmd)
263-
{
264-
struct io_uring_sqe *sqe;
265-
int ret;
266-
267-
sqe = io_uring_get_sqe(ring);
268-
if (!sqe)
269-
return -1;
270-
271-
memcpy(&sqe->cmd, cmd, sizeof(*cmd));
272-
273-
sqe->fd = hdl->fd;
274-
sqe->opcode = IORING_OP_URING_CMD;
275-
sqe->cmd_op = NVME_URING_CMD_ADMIN;
276-
277-
ret = io_uring_submit(ring);
278-
if (ret < 0)
279-
return -errno;
280-
281-
return 0;
282-
}
283-
284-
static int nvme_uring_cmd_wait_complete(struct io_uring *ring, int n)
285-
{
286-
struct io_uring_cqe *cqe;
287-
int ret, i;
288-
289-
for (i = 0; i < n; i++) {
290-
ret = io_uring_wait_cqe(ring, &cqe);
291-
if (ret < 0)
292-
return -errno;
293-
io_uring_cqe_seen(ring, cqe);
294-
}
295-
296-
return 0;
297-
}
298-
299-
static bool nvme_uring_is_usable(struct nvme_transport_handle *hdl)
300-
{
301-
struct stat st;
302-
303-
if (io_uring_kernel_support != IO_URING_AVAILABLE ||
304-
hdl->type != NVME_TRANSPORT_HANDLE_TYPE_DIRECT ||
305-
fstat(hdl->fd, &st) || !S_ISCHR(st.st_mode))
306-
return false;
307-
308-
return true;
309-
}
310-
#endif /* CONFIG_LIBURING */
311218

312219
int nvme_get_log(struct nvme_transport_handle *hdl,
313220
struct nvme_passthru_cmd *cmd, bool rae,
@@ -324,17 +231,6 @@ int nvme_get_log(struct nvme_transport_handle *hdl,
324231
__u32 cdw10 = cmd->cdw10 & (NVME_VAL(LOG_CDW10_LID) |
325232
NVME_VAL(LOG_CDW10_LSP));
326233
__u32 cdw11 = cmd->cdw11 & NVME_VAL(LOG_CDW11_LSI);
327-
#ifdef CONFIG_LIBURING
328-
bool use_uring = nvme_uring_is_usable(hdl);
329-
struct io_uring ring;
330-
int n = 0;
331-
332-
if (use_uring) {
333-
ret = nvme_uring_cmd_setup(&ring);
334-
if (ret)
335-
return ret;
336-
}
337-
#endif /* CONFIG_LIBURING */
338234

339235
if (force_4k)
340236
xfer_len = NVME_LOG_PAGE_PDU_SIZE;
@@ -373,43 +269,22 @@ int nvme_get_log(struct nvme_transport_handle *hdl,
373269
cmd->data_len = xfer;
374270
cmd->addr = (__u64)(uintptr_t)ptr;
375271

376-
#ifdef CONFIG_LIBURING
377-
if (use_uring) {
378-
if (n >= NVME_URING_ENTRIES) {
379-
ret = nvme_uring_cmd_wait_complete(&ring, n);
380-
if (ret)
381-
goto uring_exit;
382-
n = 0;
383-
}
384-
n += 1;
385-
ret = nvme_uring_cmd_admin_passthru_async(hdl,
386-
&ring, cmd);
387-
if (ret)
388-
goto uring_exit;
389-
} else {
272+
if (hdl->uring_enabled)
273+
ret = nvme_submit_admin_passthru_async(hdl, cmd);
274+
else
390275
ret = nvme_submit_admin_passthru(hdl, cmd);
391-
if (ret)
392-
return ret;
393-
}
394-
#else /* CONFIG_LIBURING */
395-
ret = nvme_submit_admin_passthru(hdl, cmd);
396-
#endif /* CONFIG_LIBURING */
397276
if (ret)
398277
return ret;
399278

400279
offset += xfer;
401280
ptr += xfer;
402281
} while (offset < data_len);
403282

404-
#ifdef CONFIG_LIBURING
405-
if (use_uring) {
406-
ret = nvme_uring_cmd_wait_complete(&ring, n);
407-
uring_exit:
408-
nvme_uring_cmd_exit(&ring);
283+
if (hdl->uring_enabled) {
284+
ret = nvme_wait_complete_passthru(hdl);
409285
if (ret)
410286
return ret;
411287
}
412-
#endif /* CONFIG_LIBURING */
413288

414289
return 0;
415290
}

libnvme/src/nvme/ioctl.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@
2626
*/
2727
#define NVME_LOG_PAGE_PDU_SIZE 4096
2828

29-
/*
30-
* should not exceed CAP.MQES, 16 is rational for most ssd
31-
*/
32-
#define NVME_URING_ENTRIES 16
33-
3429
/**
3530
* nvme_submit_admin_passthru() - Submit an nvme passthrough admin command
3631
* @hdl: Transport handle

libnvme/src/nvme/lib.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ void nvme_free_global_ctx(struct nvme_global_ctx *ctx)
8080
nvme_mi_close(ep);
8181
free(ctx->config_file);
8282
free(ctx->application);
83+
nvme_close_uring(ctx);
8384
free(ctx);
8485
}
8586

@@ -155,6 +156,11 @@ static int __nvme_transport_handle_open_direct(
155156
if (c) {
156157
if (!S_ISCHR(hdl->stat.st_mode))
157158
return -EINVAL;
159+
ret = __nvme_transport_handle_open_uring(hdl);
160+
if (ret && ret != -ENOTSUP) {
161+
close(hdl->fd);
162+
return ret;
163+
}
158164
} else if (!S_ISBLK(hdl->stat.st_mode)) {
159165
return -EINVAL;
160166
}

libnvme/src/nvme/private.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88
#pragma once
99

10+
#include <errno.h>
1011
#include <ifaddrs.h>
1112
#include <poll.h>
1213

@@ -117,6 +118,7 @@ struct nvme_transport_handle {
117118
struct stat stat;
118119
bool ioctl_admin64;
119120
bool ioctl_io64;
121+
bool uring_enabled;
120122

121123
/* mi */
122124
struct nvme_mi_ep *ep;
@@ -278,6 +280,12 @@ struct nvme_fabric_options {
278280
bool trsvcid;
279281
};
280282

283+
enum nvme_io_uring_state {
284+
NVME_IO_URING_STATE_UNKNOWN = 0,
285+
NVME_IO_URING_STATE_NOT_AVAILABLE,
286+
NVME_IO_URING_STATE_AVAILABLE,
287+
};
288+
281289
struct nvme_global_ctx {
282290
char *config_file;
283291
char *application;
@@ -290,6 +298,12 @@ struct nvme_global_ctx {
290298
bool dry_run;
291299
struct nvme_fabric_options *options;
292300
struct ifaddrs *ifaddrs_cache; /* init with nvme_getifaddrs() */
301+
302+
enum nvme_io_uring_state uring_state;
303+
#ifdef CONFIG_LIBURING
304+
int ring_cmds;
305+
struct io_uring *ring;
306+
#endif
293307
};
294308

295309
struct nvmf_discovery_ctx {
@@ -780,3 +794,40 @@ void nvme_ns_release_transport_handle(nvme_ns_t n);
780794
*/
781795
int nvme_mi_admin_admin_passthru(struct nvme_transport_handle *hdl,
782796
struct nvme_passthru_cmd *cmd);
797+
798+
#ifdef CONFIG_LIBURING
799+
int nvme_open_uring(struct nvme_global_ctx *ctx);
800+
void nvme_close_uring(struct nvme_global_ctx *ctx);
801+
int __nvme_transport_handle_open_uring(struct nvme_transport_handle *hdl);
802+
int nvme_submit_admin_passthru_async(struct nvme_transport_handle *hdl,
803+
struct nvme_passthru_cmd *cmd);
804+
int nvme_wait_complete_passthru(struct nvme_transport_handle *hdl);
805+
#else
806+
static inline int
807+
nvme_open_uring(struct nvme_global_ctx *ctx)
808+
{
809+
return -ENOTSUP;
810+
}
811+
static inline void
812+
nvme_close_uring(struct nvme_global_ctx *ctx)
813+
{
814+
}
815+
static inline int
816+
__nvme_transport_handle_open_uring(struct nvme_transport_handle *hdl)
817+
{
818+
hdl->ctx->uring_state = NVME_IO_URING_STATE_NOT_AVAILABLE;
819+
return -ENOTSUP;
820+
}
821+
static inline int
822+
nvme_submit_admin_passthru_async(struct nvme_transport_handle *hdl,
823+
struct nvme_passthru_cmd *cmd)
824+
{
825+
return -ENOTSUP;
826+
}
827+
static inline int
828+
nvme_wait_complete_passthru(struct nvme_transport_handle *hdl)
829+
{
830+
return -ENOTSUP;
831+
}
832+
#endif
833+

0 commit comments

Comments
 (0)