Skip to content

Commit 741dbcb

Browse files
committed
ioctl: add hooks into submission path
Don't expose the nvme_submit_passthru completely. Instead just provide hooks for printing or deciding if a command needs to be retried. This is similiar to the MI interface. Signed-off-by: Daniel Wagner <[email protected]>
1 parent 1ef3503 commit 741dbcb

File tree

8 files changed

+103
-59
lines changed

8 files changed

+103
-59
lines changed

libnvme/src/libnvme.map

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ LIBNVME_2_0 {
6464
nvme_ctrl_set_tls_key_identity;
6565
nvme_ctrl_set_unique_discovery_ctrl;
6666
nvme_ctrls_filter;
67+
nvme_decide_retry;
6768
nvme_default_host;
6869
nvme_describe_key_serial;
6970
nvme_disconnect_ctrl;
@@ -240,13 +241,16 @@ LIBNVME_2_0 {
240241
nvme_scan_topology;
241242
nvme_set_application;
242243
nvme_set_debug;
244+
nvme_set_dry_run;
243245
nvme_set_keyring;
244246
nvme_set_property;
245247
nvme_set_root;
246248
nvme_skip_namespaces;
247249
nvme_status_to_errno;
248250
nvme_status_to_string;
249251
nvme_submit_admin_passthru;
252+
nvme_submit_entry;
253+
nvme_submit_exit;
250254
nvme_submit_io_passthru;
251255
nvme_subsys_filter;
252256
nvme_subsystem_first_ctrl;

libnvme/src/nvme/ioctl.c

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
#include <ccan/endian/endian.h>
2828

2929
#include "ioctl.h"
30-
#include "util.h"
31-
#include "log.h"
3230
#include "private.h"
3331

3432
static int nvme_verify_chr(struct nvme_transport_handle *hdl)
@@ -100,17 +98,23 @@ int nvme_get_nsid(struct nvme_transport_handle *hdl, __u32 *nsid)
10098
}
10199

102100
__attribute__((weak))
103-
int nvme_submit_passthru(struct nvme_transport_handle *hdl,
104-
unsigned long ioctl_cmd, struct nvme_passthru_cmd *cmd,
105-
__u64 *result)
101+
void *nvme_submit_entry(struct nvme_transport_handle *hdl,
102+
struct nvme_passthru_cmd *cmd)
106103
{
107-
int err = ioctl(hdl->fd, ioctl_cmd, cmd);
104+
return NULL;
105+
}
108106

109-
if (err >= 0 && result)
110-
*result = cmd->result;
111-
if (err < 0)
112-
return -errno;
113-
return err;
107+
__attribute__((weak))
108+
void nvme_submit_exit(struct nvme_transport_handle *hdl,
109+
struct nvme_passthru_cmd *cmd, int err, void *user_data)
110+
{
111+
}
112+
113+
__attribute__((weak))
114+
bool nvme_decide_retry(struct nvme_transport_handle *hdl,
115+
struct nvme_passthru_cmd *cmd, int err)
116+
{
117+
return false;
114118
}
115119

116120
/*
@@ -122,17 +126,29 @@ static int nvme_submit_passthru32(struct nvme_transport_handle *hdl,
122126
__u64 *result)
123127
{
124128
struct linux_passthru_cmd32 cmd32;
125-
int err;
129+
void *user_data;
130+
int err = 0;
131+
132+
user_data = nvme_submit_entry(hdl, cmd);
133+
if (hdl->ctx->dry_run)
134+
goto out;
126135

127136
memcpy(&cmd32, cmd, offsetof(struct linux_passthru_cmd32, result));
128137
cmd32.result = 0;
129138

130-
err = ioctl(hdl->fd, ioctl_cmd, &cmd32);
139+
do {
140+
err = ioctl(hdl->fd, ioctl_cmd, &cmd32);
141+
if (err >= 0)
142+
break;
143+
err = -errno;
144+
} while (nvme_decide_retry(hdl, cmd, err));
145+
146+
out:
131147
cmd->result = cmd32.result;
132148
if (err >= 0 && result)
133149
*result = cmd->result;
134-
if (err < 0)
135-
return -errno;
150+
151+
nvme_submit_exit(hdl, cmd, err, user_data);
136152
return err;
137153
}
138154

@@ -144,13 +160,29 @@ static int nvme_submit_passthru64(struct nvme_transport_handle *hdl,
144160
unsigned long ioctl_cmd, struct nvme_passthru_cmd *cmd,
145161
__u64 *result)
146162
{
147-
int err;
163+
void *user_data;
164+
int err = 0;
165+
166+
user_data = nvme_submit_entry(hdl, cmd);
167+
if (hdl->ctx->dry_run)
168+
goto out;
148169

149-
err = ioctl(hdl->fd, ioctl_cmd, cmd);
170+
do {
171+
/*
172+
* struct nvme_passtrhu_cmd is identically to struct
173+
* linux_passthru_cmd64, thus just pass it in directly.
174+
*/
175+
err = ioctl(hdl->fd, ioctl_cmd, cmd);
176+
if (err >= 0)
177+
break;
178+
err = -errno;
179+
} while (nvme_decide_retry(hdl, cmd, err));
180+
181+
out:
150182
if (err >= 0 && result)
151183
*result = cmd->result;
152-
if (err < 0)
153-
return -errno;
184+
185+
nvme_submit_exit(hdl, cmd, err, user_data);
154186
return err;
155187
}
156188

libnvme/src/nvme/ioctl.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,18 @@ enum nvme_cmd_dword_fields {
448448
#define NVME_FIELD_DECODE(value, shift, mask) \
449449
(((value) >> (shift)) & (mask))
450450

451+
__attribute__((weak))
452+
void *nvme_submit_entry(struct nvme_transport_handle *hdl,
453+
struct nvme_passthru_cmd *cmd);
454+
455+
__attribute__((weak))
456+
void nvme_submit_exit(struct nvme_transport_handle *hdl,
457+
struct nvme_passthru_cmd *cmd, int err, void *user_data);
458+
459+
__attribute__((weak))
460+
bool nvme_decide_retry(struct nvme_transport_handle *hdl,
461+
struct nvme_passthru_cmd *cmd, int err);
462+
451463
/**
452464
* nvme_submit_admin_passthru() - Submit an nvme passthrough admin command
453465
* @hdl: Transport handle

libnvme/src/nvme/linux.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@
4141
#include "base64.h"
4242
#include "crc32.h"
4343

44+
void nvme_set_dry_run(struct nvme_global_ctx *ctx, bool enable)
45+
{
46+
ctx->dry_run = enable;
47+
}
48+
4449
static int __nvme_transport_handle_open_direct(struct nvme_transport_handle *hdl, const char *devname)
4550
{
4651
_cleanup_free_ char *path = NULL;

libnvme/src/nvme/linux.h

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -636,22 +636,7 @@ int nvme_import_tls_key_versioned(const char *encoded_key,
636636
unsigned char *hmac,
637637
size_t *key_len,
638638
unsigned char **key);
639-
/**
640-
* nvme_submit_passthru - Low level ioctl wrapper for passthru commands
641-
* @hdl: Transport handle
642-
* @ioctl_cmd: IOCTL command id
643-
* @cmd: Passhtru command
644-
* @result: Optional field to return the result
645-
*
646-
* This is a low level library function which should not be used directly. It is
647-
* exposed as weak symbol so that the user application is able to provide their own
648-
* implementation of this function with additional debugging or logging code.
649-
*
650-
* Return: The value from the ioctl system call (see ioctl documentation) or
651-
* a negative error code otherwise.
652-
*/
653-
__attribute__((weak))
654-
int nvme_submit_passthru(struct nvme_transport_handle *hdl, unsigned long ioctl_cmd,
655-
struct nvme_passthru_cmd *cmd, __u64 *result);
639+
640+
void nvme_set_dry_run(struct nvme_global_ctx *ctx, bool enable);
656641

657642
#endif /* _LIBNVME_LINUX_H */

libnvme/src/nvme/private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ struct nvme_global_ctx {
260260
bool modified;
261261
bool mi_probe_enabled;
262262
bool create_only;
263+
bool dry_run;
263264
struct nvme_fabric_options *options;
264265
};
265266

logging.c

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -100,38 +100,41 @@ static void nvme_log_retry(int errnum)
100100
printf("passthru command returned '%s'\n", strerror(errnum));
101101
}
102102

103-
int nvme_submit_passthru(struct nvme_transport_handle *hdl,
104-
unsigned long ioctl_cmd, struct nvme_passthru_cmd *cmd,
105-
__u64 *result)
103+
void *nvme_submit_entry(struct nvme_transport_handle *hdl,
104+
struct nvme_passthru_cmd *cmd)
106105
{
107-
struct timeval start;
108-
struct timeval end;
109-
int err = 0;
106+
memset(&sb, 0, sizeof(sb));
110107

111108
if (log_level >= LOG_DEBUG)
112-
gettimeofday(&start, NULL);
113-
114-
if (!nvme_cfg.dry_run) {
115-
retry:
116-
err = ioctl(nvme_transport_handle_get_fd(hdl), ioctl_cmd, cmd);
117-
if ((err && (errno == EAGAIN ||
118-
(errno == EINTR && !nvme_sigint_received))) &&
119-
!nvme_cfg.no_retries) {
120-
nvme_log_retry(errno);
121-
goto retry;
122-
}
123-
}
109+
gettimeofday(&sb.start, NULL);
110+
111+
return &sb;
112+
}
113+
114+
void nvme_submit_exit(struct nvme_transport_handle *hdl,
115+
struct nvme_passthru_cmd *cmd, int err, void *user_data)
116+
{
117+
struct submit_data *sb = user_data;
124118

125119
if (log_level >= LOG_DEBUG) {
126-
gettimeofday(&end, NULL);
120+
gettimeofday(&sb->end, NULL);
127121
nvme_show_command(cmd, err);
128-
nvme_show_latency(start, end);
122+
nvme_show_latency(sb->start, sb->end);
129123
}
124+
}
125+
126+
bool nvme_decide_retry(struct nvme_transport_handle *hdl,
127+
struct nvme_passthru_cmd *cmd, int err)
128+
{
129+
if (!nvme_cfg.no_retries)
130+
return false;
130131

131-
if (err >= 0 && result)
132-
*result = cmd->result;
132+
if (err != -EAGAIN ||
133+
!(err == -EINTR && !nvme_sigint_received))
134+
return false;
133135

134-
return err;
136+
nvme_log_retry(errno);
137+
return true;
135138
}
136139

137140
static void nvme_show_req_admin(const struct nvme_mi_admin_req_hdr *hdr, size_t hdr_len,

nvme.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,8 @@ int parse_and_open(struct nvme_global_ctx **ctx,
406406
return -ENXIO;
407407
}
408408

409+
nvme_set_dry_run(ctx_new, argconfig_parse_seen(opts, "dry_run"));
410+
409411
*ctx = ctx_new;
410412
*hdl = hdl_new;
411413
return 0;

0 commit comments

Comments
 (0)