diff --git a/libnvme/src/libnvme.ld b/libnvme/src/libnvme.ld index 961ca78d3c..3af83e27c9 100644 --- a/libnvme/src/libnvme.ld +++ b/libnvme/src/libnvme.ld @@ -188,6 +188,7 @@ LIBNVME_3 { libnvme_transport_handle_set_decide_retry; libnvme_transport_handle_set_submit_entry; libnvme_transport_handle_set_submit_exit; + libnvme_transport_handle_set_timeout; libnvme_unlink_ctrl; libnvme_update_block_size; libnvme_update_key; diff --git a/libnvme/src/nvme/ioctl.c b/libnvme/src/nvme/ioctl.c index 522e96db2f..ad6b828810 100644 --- a/libnvme/src/nvme/ioctl.c +++ b/libnvme/src/nvme/ioctl.c @@ -193,6 +193,9 @@ static int libnvme_submit_passthru64(struct libnvme_transport_handle *hdl, __public int libnvme_submit_io_passthru(struct libnvme_transport_handle *hdl, struct libnvme_passthru_cmd *cmd) { + if (!cmd->timeout_ms && hdl->timeout) + cmd->timeout_ms = hdl->timeout; + if (hdl->ioctl_io64) return libnvme_submit_passthru64(hdl, LIBNVME_IOCTL_IO64_CMD, cmd); @@ -202,6 +205,9 @@ __public int libnvme_submit_io_passthru(struct libnvme_transport_handle *hdl, __public int libnvme_submit_admin_passthru(struct libnvme_transport_handle *hdl, struct libnvme_passthru_cmd *cmd) { + if (!cmd->timeout_ms && hdl->timeout) + cmd->timeout_ms = hdl->timeout; + switch (hdl->type) { case LIBNVME_TRANSPORT_HANDLE_TYPE_DIRECT: if (hdl->ioctl_admin64) diff --git a/libnvme/src/nvme/lib.c b/libnvme/src/nvme/lib.c index 8755cf704f..350a6a1ca4 100644 --- a/libnvme/src/nvme/lib.c +++ b/libnvme/src/nvme/lib.c @@ -137,6 +137,12 @@ __public void libnvme_transport_handle_set_decide_retry(struct libnvme_transport hdl->decide_retry = __libnvme_decide_retry; } +__public void libnvme_transport_handle_set_timeout( + struct libnvme_transport_handle *hdl, __u32 timeout_ms) +{ + hdl->timeout = timeout_ms; +} + static int __nvme_transport_handle_open_direct( struct libnvme_transport_handle *hdl, const char *devname) { diff --git a/libnvme/src/nvme/lib.h b/libnvme/src/nvme/lib.h index 0ae450e515..92b8cd3762 100644 --- a/libnvme/src/nvme/lib.h +++ b/libnvme/src/nvme/lib.h @@ -216,6 +216,19 @@ void libnvme_transport_handle_set_decide_retry( bool (*decide_retry)(struct libnvme_transport_handle *hdl, struct libnvme_passthru_cmd *cmd, int err)); +/** + * libnvme_transport_handle_set_timeout() - Set the default command timeout + * @hdl: Transport handle to configure + * @timeout_ms: Timeout in milliseconds. A value of 0 means use the kernel + * default (NVME_DEFAULT_IOCTL_TIMEOUT). + * + * Sets a default timeout that is applied to every passthrough command + * submitted through @hdl when the command's own timeout_ms field is 0. + * Commands that set a non-zero timeout_ms override this default. + */ +void libnvme_transport_handle_set_timeout(struct libnvme_transport_handle *hdl, + __u32 timeout_ms); + /** * libnvme_set_probe_enabled() - enable/disable the probe for new MI endpoints * @ctx: &struct libnvme_global_ctx object diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index 8f9e72382c..47a52aae7a 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -150,6 +150,9 @@ struct libnvme_transport_handle { bool (*decide_retry)(struct libnvme_transport_handle *hdl, struct libnvme_passthru_cmd *cmd, int err); + /* global command timeout */ + __u32 timeout; + /* direct */ int fd; struct stat stat; diff --git a/nvme.c b/nvme.c index d65b78a080..e3378b042a 100644 --- a/nvme.c +++ b/nvme.c @@ -381,6 +381,9 @@ int parse_and_open(struct libnvme_global_ctx **ctx, libnvme_transport_handle_set_submit_exit(hdl_new , nvme_submit_exit); libnvme_transport_handle_set_decide_retry(hdl_new, nvme_decide_retry); libnvme_set_dry_run(ctx_new, argconfig_parse_seen(opts, "dry-run")); + if (argconfig_parse_seen(opts, "timeout")) + libnvme_transport_handle_set_timeout(hdl_new, + nvme_args.timeout); *ctx = ctx_new; *hdl = hdl_new;