Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions libnvme/src/libnvme.ld
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ LIBNVME_3 {
libnvme_dump_config;
libnvme_dump_tree;
libnvme_errno_to_string;
libnvme_exec_admin_passthru;
libnvme_exec_io_passthru;
libnvme_export_tls_key;
libnvme_export_tls_key_versioned;
libnvme_filter_ctrls;
Expand Down Expand Up @@ -149,6 +151,7 @@ LIBNVME_3 {
libnvme_read_hostnqn;
libnvme_read_key;
libnvme_realloc;
libnvme_reap_passthru_async;
libnvme_refresh_topology;
libnvme_rescan_ctrl;
libnvme_rescan_ns;
Expand Down Expand Up @@ -176,7 +179,9 @@ LIBNVME_3 {
libnvme_status_to_string;
libnvme_strerror;
libnvme_submit_admin_passthru;
libnvme_submit_admin_passthru_async;
libnvme_submit_io_passthru;
libnvme_submit_io_passthru_async;
libnvme_subsystem_first_ctrl;
libnvme_subsystem_first_ns;
libnvme_subsystem_get_host;
Expand All @@ -201,8 +206,7 @@ LIBNVME_3 {
libnvme_update_key;
libnvme_uuid_from_string;
libnvme_uuid_to_string;
libnvme_wait_admin_passthru;
libnvme_wait_io_passthru;
libnvme_wait_passthru;
local:
*;
};
65 changes: 62 additions & 3 deletions libnvme/src/nvme/ioctl-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,6 @@ __libnvme_public int libnvme_submit_admin_passthru(
if (!hdl)
return -ENODEV;

if (hdl->uring_enabled)
return libnvme_submit_admin_passthru_async(hdl, cmd);

if (!cmd->timeout_ms && hdl->timeout)
cmd->timeout_ms = hdl->timeout;

Expand All @@ -259,3 +256,65 @@ __libnvme_public int libnvme_submit_admin_passthru(

return -ENOTSUP;
}

__libnvme_public int libnvme_exec_admin_passthru(
struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd)
{
struct libnvme_passthru_completion completion;
int err;

if (!hdl)
return -ENODEV;

if (hdl->uring_state == LIBNVME_IO_URING_STATE_NOT_AVAILABLE)
goto no_uring;

err = libnvme_submit_admin_passthru_async(hdl, cmd, NULL);
if (err) {
if (err == -ENOTSUP)
goto no_uring;

return err;
}

err = libnvme_reap_passthru_async(hdl, &completion);
if (err)
return err;

return completion.status;

no_uring:
return libnvme_submit_admin_passthru(hdl, cmd);
}

__libnvme_public int libnvme_exec_io_passthru(
struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd)
{
struct libnvme_passthru_completion completion;
int err;

if (!hdl)
return -ENODEV;

if (hdl->uring_state == LIBNVME_IO_URING_STATE_NOT_AVAILABLE)
goto no_uring;

err = libnvme_submit_io_passthru_async(hdl, cmd, NULL);
if (err) {
if (err == -ENOTSUP)
goto no_uring;

return err;
}

err = libnvme_reap_passthru_async(hdl, &completion);
if (err)
return err;

return completion.status;

no_uring:
return libnvme_submit_io_passthru(hdl, cmd);
}
14 changes: 14 additions & 0 deletions libnvme/src/nvme/ioctl-win.c
Original file line number Diff line number Diff line change
Expand Up @@ -1728,3 +1728,17 @@ __libnvme_public int libnvme_submit_admin_passthru(struct libnvme_transport_hand
return -ENOTSUP;
}
}

__libnvme_public int libnvme_exec_admin_passthru(
struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd)
{
return libnvme_submit_admin_passthru(hdl, cmd);
}

__libnvme_public int libnvme_exec_io_passthru(
struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd)
{
return libnvme_submit_io_passthru(hdl, cmd);
}
97 changes: 64 additions & 33 deletions libnvme/src/nvme/ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,39 +40,45 @@ int libnvme_submit_admin_passthru(struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd);

/**
* libnvme_wait_admin_passthru() - Wait for pending admin passthru completions
* @hdl: Transport handle
* struct libnvme_passthru_completion - Async passthru completion record
* @cmd: Command that completed
* @cookie: User cookie provided to libnvme_submit_*_passthru_async()
* @status: Completion status (NVMe status or negative errno)
*
* When io_uring is enabled, libnvme_submit_admin_passthru() queues commands
* asynchronously. Call this function after one or more submits to drain all
* pending completions before inspecting response data.
* Used for both admin and IO passthru command completions.
*/
struct libnvme_passthru_completion {
struct libnvme_passthru_cmd *cmd;
void *cookie;
int status;
};

/**
* libnvme_submit_admin_passthru_async() - Queue admin passthru command
* @hdl: Transport handle
* @cmd: The nvme admin command to send
* @cookie: User-defined opaque value returned at completion
*
* This is a no-op when io_uring is not available.
* Queues @cmd for asynchronous execution. Completion is reported via
* libnvme_reap_admin_passthru_async().
*
* Return: 0 on success, negative error code otherwise.
* Return: 0 on successful queueing, negative error code otherwise.
*/
int libnvme_wait_admin_passthru(struct libnvme_transport_handle *hdl);
int libnvme_submit_admin_passthru_async(struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd, void *cookie);

/**
* libnvme_exec_admin_passthru() - Submit an admin passthru command and wait
* @hdl: Transport handle
* @cmd: The nvme admin command to send
*
* Convenience wrapper that combines libnvme_submit_admin_passthru() and
* libnvme_wait_admin_passthru() into a single synchronous call. Use this
* for the common case where commands are sent one at a time. Use the
* split-phase API directly when batching multiple commands with io_uring.
* Synchronous command execution.
*
* Return: The nvme command status if a response was received (see
* &enum nvme_status_field), or negative error code otherwise.
*/
static inline int libnvme_exec_admin_passthru(
struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd)
{
int err = libnvme_submit_admin_passthru(hdl, cmd);
return err ? err : libnvme_wait_admin_passthru(hdl);
}
int libnvme_exec_admin_passthru(struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd);

/**
* libnvme_submit_io_passthru() - Submit an nvme passthrough command
Expand All @@ -88,34 +94,59 @@ int libnvme_submit_io_passthru(struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd);

/**
* libnvme_wait_io_passthru() - Wait for pending IO passthru completions
* libnvme_submit_io_passthru_async() - Queue IO passthru command
* @hdl: Transport handle
* @cmd: The nvme IO command to send
* @cookie: User-defined opaque value returned at completion
*
* Counterpart to libnvme_submit_io_passthru() for the split-phase API.
* Currently a no-op as the IO passthru path does not yet use io_uring.
* Queues @cmd for asynchronous execution. Completion is reported via
* libnvme_reap_io_passthru_async().
*
* Return: 0 on success, negative error code otherwise.
* Return: 0 on successful queueing, negative error code otherwise.
*/
int libnvme_wait_io_passthru(struct libnvme_transport_handle *hdl);
int libnvme_submit_io_passthru_async(struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd, void *cookie);

/**
* libnvme_exec_io_passthru() - Submit an IO passthru command and wait
* @hdl: Transport handle
* @cmd: The nvme IO command to send
*
* Convenience wrapper combining libnvme_submit_io_passthru() and
* libnvme_wait_io_passthru() into a single synchronous call.
* Synchronous command execution. Note: when io_uring is enabled, this shares
* the async queue. Avoid mixing this with direct async API usage on the same
* handle. For batching, use the async API exclusively.
*
* Return: The nvme command status if a response was received (see
* &enum nvme_status_field), or negative error code otherwise.
*/
static inline int libnvme_exec_io_passthru(
struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd)
{
int err = libnvme_submit_io_passthru(hdl, cmd);
return err ? err : libnvme_wait_io_passthru(hdl);
}
int libnvme_exec_io_passthru(struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd);

/**
* libnvme_reap_passthru_async() - Reap one async completion
* @hdl: Transport handle
* @completion: Completion output structure
*
* Waits for one queued passthru command to complete and stores the
* completed command pointer, associated cookie, and completion status in
* @completion.
*
* Return: 0 on success, negative error code otherwise.
*/
int libnvme_reap_passthru_async(struct libnvme_transport_handle *hdl,
struct libnvme_passthru_completion *completion);

/**
* libnvme_wait_passthru() - Wait for all pending passthru completions
* @hdl: Transport handle
*
* Drains all pending passthru commands from the async queue. Use this
* after batching multiple libnvme_submit_admin_passthru() calls when io_uring
* is enabled.
*
* Return: 0 on success, or the first non-zero status encountered.
*/
int libnvme_wait_passthru(struct libnvme_transport_handle *hdl);

/**
* libnvme_reset_subsystem() - Initiate a subsystem reset
Expand Down
3 changes: 1 addition & 2 deletions libnvme/src/nvme/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ __libnvme_public void libnvme_free_global_ctx(struct libnvme_global_ctx *ctx)
#endif
free(ctx->config_file);
free(ctx->application);
libnvme_close_uring(ctx);
free(ctx);
}

Expand Down Expand Up @@ -197,6 +196,7 @@ static int __nvme_transport_handle_open_direct(
void __libnvme_transport_handle_close_direct(
struct libnvme_transport_handle *hdl)
{
libnvme_close_uring(hdl);
close(hdl->fd);
free(hdl);
}
Expand Down Expand Up @@ -316,4 +316,3 @@ __libnvme_public bool libnvme_transport_handle_is_mi(
{
return hdl->type == LIBNVME_TRANSPORT_HANDLE_TYPE_MI;
}

38 changes: 28 additions & 10 deletions libnvme/src/nvme/no-uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,52 @@
#include "private.h"
#include "compiler-attributes.h"

int libnvme_open_uring(struct libnvme_global_ctx *ctx)
int libnvme_open_uring(__libnvme_unused struct libnvme_transport_handle *hdl)
{
return -ENOTSUP;
}
void libnvme_close_uring(struct libnvme_global_ctx *ctx)
void libnvme_close_uring(__libnvme_unused struct libnvme_transport_handle *hdl)
{
}

int __libnvme_transport_handle_open_uring(struct libnvme_transport_handle *hdl)
{
hdl->ctx->uring_state = LIBNVME_IO_URING_STATE_NOT_AVAILABLE;
hdl->uring_state = LIBNVME_IO_URING_STATE_NOT_AVAILABLE;

return -ENOTSUP;
}

int libnvme_submit_admin_passthru_async(struct libnvme_transport_handle *hdl,
struct libnvme_passthru_cmd *cmd)
__libnvme_public int libnvme_submit_admin_passthru_async(
__libnvme_unused struct libnvme_transport_handle *hdl,
__libnvme_unused struct libnvme_passthru_cmd *cmd,
__libnvme_unused void *cookie)
{
if (hdl->uring_state == LIBNVME_IO_URING_STATE_UNKNOWN)
return __libnvme_transport_handle_open_uring(hdl);

return -ENOTSUP;
}

__libnvme_public int libnvme_wait_admin_passthru(
__libnvme_unused struct libnvme_transport_handle *hdl)
__libnvme_public int libnvme_submit_io_passthru_async(
__libnvme_unused struct libnvme_transport_handle *hdl,
__libnvme_unused struct libnvme_passthru_cmd *cmd,
__libnvme_unused void *cookie)
{
if (hdl->uring_state == LIBNVME_IO_URING_STATE_UNKNOWN)
return __libnvme_transport_handle_open_uring(hdl);

return -ENOTSUP;
}

__libnvme_public int libnvme_reap_passthru_async(
__libnvme_unused struct libnvme_transport_handle *hdl,
__libnvme_unused struct libnvme_passthru_completion *completion)
{
return 0;
return -ENOTSUP;
}

__libnvme_public int libnvme_wait_io_passthru(
__libnvme_public int libnvme_wait_passthru(
__libnvme_unused struct libnvme_transport_handle *hdl)
{
return 0;
return -ENOTSUP;
}
Loading
Loading