From e1882cdfe62685e15e0423c4c1c2d65befaf4e07 Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Fri, 28 Mar 2025 03:13:24 +0900 Subject: [PATCH 1/2] nvme: add dry-run NVME_ARGS default option The option is to show command instead of sending. Signed-off-by: Tokunori Ikegami --- nvme-print.c | 2 +- nvme.c | 20 +++++++++----------- nvme.h | 3 +++ util/logging.c | 19 +++++++++++++++++-- util/logging.h | 1 + 5 files changed, 31 insertions(+), 14 deletions(-) diff --git a/nvme-print.c b/nvme-print.c index 0685cba5d9..717ccd806c 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -19,7 +19,7 @@ #define nvme_print(name, flags, ...) \ do { \ struct print_ops *ops = nvme_print_ops(flags); \ - if (ops && ops->name) \ + if (ops && ops->name && !nvme_cfg.dry_run) \ ops->name(__VA_ARGS__); \ } while (false) diff --git a/nvme.c b/nvme.c index 636ca82ecc..ba90f6f011 100644 --- a/nvme.c +++ b/nvme.c @@ -102,7 +102,6 @@ struct passthru_config { char *metadata; bool raw_binary; bool show_command; - bool dry_run; bool read; bool write; __u8 prefill; @@ -192,6 +191,7 @@ const char *output_format = "Output format: normal|binary"; #endif /* CONFIG_JSONC */ const char *timeout = "timeout value, in milliseconds"; const char *verbose = "Increase output verbosity"; +const char *dry_run = "show command instead of sending"; static const char *app_tag = "app tag for end-to-end PI"; static const char *app_tag_mask = "app tag mask for end-to-end PI"; @@ -201,7 +201,6 @@ static const char *csi = "command set identifier"; static const char *buf_len = "buffer len (if) data is sent or received"; static const char *domainid = "Domain Identifier"; static const char *doper = "directive operation"; -static const char *dry = "show command instead of sending"; static const char *dspec_w_dtype = "directive specification associated with directive type"; static const char *dtype = "directive type"; static const char *endgid = "Endurance Group Identifier (ENDGID)"; @@ -445,6 +444,8 @@ static int parse_args(int argc, char *argv[], const char *desc, log_level = map_log_level(nvme_cfg.verbose, false); nvme_init_default_logging(stderr, log_level, false, false); + set_dry_run(nvme_cfg.dry_run); + return 0; } @@ -8060,7 +8061,6 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char __u16 dspec; __u8 dsmgmt; bool show; - bool dry_run; bool latency; bool force; }; @@ -8085,7 +8085,6 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char .dspec = 0, .dsmgmt = 0, .show = false, - .dry_run = false, .latency = false, .force = false, }; @@ -8110,7 +8109,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char OPT_SHRT("dir-spec", 'S', &cfg.dspec, dspec), OPT_BYTE("dsm", 'D', &cfg.dsmgmt, dsm), OPT_FLAG("show-command", 'V', &cfg.show, show), - OPT_FLAG("dry-run", 'w', &cfg.dry_run, dry), + OPT_FLAG("dry-run", 'w', &nvme_cfg.dry_run, dry_run), OPT_FLAG("latency", 't', &cfg.latency, latency), OPT_FLAG("force", 0, &cfg.force, force)); @@ -8286,7 +8285,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char } } - if (cfg.show || cfg.dry_run) { + if (cfg.show || nvme_cfg.dry_run) { printf("opcode : %02x\n", opcode); printf("nsid : %02x\n", cfg.namespace_id); printf("flags : %02x\n", 0); @@ -8304,7 +8303,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char printf("pif : %02x\n", pif); printf("sts : %02x\n", sts); } - if (cfg.dry_run) + if (nvme_cfg.dry_run) return 0; struct nvme_io_args args = { @@ -9069,7 +9068,6 @@ static int passthru(int argc, char **argv, bool admin, .metadata = "", .raw_binary = false, .show_command = false, - .dry_run = false, .read = false, .write = false, .latency = false, @@ -9095,7 +9093,7 @@ static int passthru(int argc, char **argv, bool admin, OPT_FILE("metadata", 'M', &cfg.metadata, metadata), OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_dump), OPT_FLAG("show-command", 's', &cfg.show_command, show), - OPT_FLAG("dry-run", 'd', &cfg.dry_run, dry), + OPT_FLAG("dry-run", 'd', &nvme_cfg.dry_run, dry_run), OPT_FLAG("read", 'r', &cfg.read, re), OPT_FLAG("write", 'w', &cfg.write, wr), OPT_FLAG("latency", 'T', &cfg.latency, latency)); @@ -9172,7 +9170,7 @@ static int passthru(int argc, char **argv, bool admin, } } - if (cfg.show_command || cfg.dry_run) { + if (cfg.show_command || nvme_cfg.dry_run) { printf("opcode : %02x\n", cfg.opcode); printf("flags : %02x\n", cfg.flags); printf("rsvd1 : %04x\n", cfg.rsvd); @@ -9191,7 +9189,7 @@ static int passthru(int argc, char **argv, bool admin, printf("cdw15 : %08x\n", cfg.cdw15); printf("timeout_ms : %08x\n", nvme_cfg.timeout); } - if (cfg.dry_run) + if (nvme_cfg.dry_run) return 0; gettimeofday(&start_time, NULL); diff --git a/nvme.h b/nvme.h index 363a82d99d..6d14a2f3b7 100644 --- a/nvme.h +++ b/nvme.h @@ -78,6 +78,7 @@ struct nvme_config { char *output_format; int verbose; __u32 timeout; + bool dry_run; }; /* @@ -90,6 +91,7 @@ struct nvme_config { OPT_FMT("output-format", 'o', &nvme_cfg.output_format, output_format), \ ##__VA_ARGS__, \ OPT_UINT("timeout", 't', &nvme_cfg.timeout, timeout), \ + OPT_FLAG("dry-run", 0, &nvme_cfg.dry_run, dry_run), \ OPT_END() \ } @@ -131,6 +133,7 @@ static inline DEFINE_CLEANUP_FUNC( extern const char *output_format; extern const char *timeout; extern const char *verbose; +extern const char *dry_run; extern struct nvme_config nvme_cfg; int validate_output_format(const char *format, nvme_print_flags_t *flags); diff --git a/util/logging.c b/util/logging.c index a855a3dd67..616c615169 100644 --- a/util/logging.c +++ b/util/logging.c @@ -13,6 +13,7 @@ #include "logging.h" int log_level; +static bool dry_run; int map_log_level(int verbose, bool quiet) { @@ -44,6 +45,11 @@ int map_log_level(int verbose, bool quiet) return log_level; } +void set_dry_run(bool enable) +{ + dry_run = enable; +} + static void nvme_show_common(struct nvme_passthru_cmd *cmd) { printf("opcode : %02x\n", cmd->opcode); @@ -93,6 +99,11 @@ int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, struct timeval end; int err; + if (dry_run) { + nvme_show_common(cmd); + return 0; + } + if (log_level >= LOG_DEBUG) gettimeofday(&start, NULL); @@ -116,12 +127,16 @@ int nvme_submit_passthru64(int fd, unsigned long ioctl_cmd, { struct timeval start; struct timeval end; - int err; + int err = 0; + + if (dry_run) { + nvme_show_common((struct nvme_passthru_cmd *)cmd); + return 0; + } if (log_level >= LOG_DEBUG) gettimeofday(&start, NULL); - err = ioctl(fd, ioctl_cmd, cmd); if (log_level >= LOG_DEBUG) { diff --git a/util/logging.h b/util/logging.h index 6899a4f298..5828189079 100644 --- a/util/logging.h +++ b/util/logging.h @@ -20,5 +20,6 @@ extern int log_level; int map_log_level(int verbose, bool quiet); +void set_dry_run(bool enable); #endif // DEBUG_H_ From e1667bd54b2832cd28338fbed78b0e7263bf444d Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Sun, 13 Apr 2025 10:28:41 +0900 Subject: [PATCH 2/2] nvme: move submit_io show-command and dry-run outputs into logging Also latency output moved into logging as same. Signed-off-by: Tokunori Ikegami --- nvme.c | 34 +++------------------------------- util/logging.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ util/logging.h | 2 +- 3 files changed, 52 insertions(+), 32 deletions(-) diff --git a/nvme.c b/nvme.c index ba90f6f011..9dcaa5e770 100644 --- a/nvme.c +++ b/nvme.c @@ -8009,7 +8009,6 @@ unsigned long long elapsed_utime(struct timeval start_time, static int submit_io(int opcode, char *command, const char *desc, int argc, char **argv) { - struct timeval start_time, end_time; void *buffer; _cleanup_free_ void *mbuffer = NULL; int err = 0; @@ -8017,7 +8016,6 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char int flags, pi_size; int mode = 0644; __u16 control = 0, nblocks = 0; - __u32 dsmgmt = 0; unsigned int logical_block_size = 0; unsigned long long buffer_size = 0, mbuffer_size = 0; _cleanup_huge_ struct nvme_mem_huge mh = { 0, }; @@ -8147,7 +8145,6 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char if (cfg.prinfo > 0xf) return err; - dsmgmt = cfg.dsmgmt; control |= (cfg.prinfo << 10); if (cfg.limited_retry) control |= NVME_IO_LR; @@ -8161,7 +8158,6 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char return -EINVAL; } control |= cfg.dtype << 4; - dsmgmt |= ((__u32)cfg.dspec) << 16; } if (opcode & 1) { @@ -8285,27 +8281,6 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char } } - if (cfg.show || nvme_cfg.dry_run) { - printf("opcode : %02x\n", opcode); - printf("nsid : %02x\n", cfg.namespace_id); - printf("flags : %02x\n", 0); - printf("control : %04x\n", control); - printf("nblocks : %04x\n", nblocks); - printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)mbuffer); - printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)buffer); - printf("slba : %"PRIx64"\n", (uint64_t)cfg.start_block); - printf("dsmgmt : %08x\n", dsmgmt); - printf("reftag : %"PRIx64"\n", (uint64_t)cfg.ref_tag); - printf("apptag : %04x\n", cfg.app_tag); - printf("appmask : %04x\n", cfg.app_tag_mask); - printf("storagetagcheck : %04x\n", cfg.storage_tag_check); - printf("storagetag : %"PRIx64"\n", (uint64_t)cfg.storage_tag); - printf("pif : %02x\n", pif); - printf("sts : %02x\n", sts); - } - if (nvme_cfg.dry_run) - return 0; - struct nvme_io_args args = { .args_size = sizeof(args), .fd = dev_fd(dev), @@ -8329,16 +8304,13 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char .timeout = nvme_cfg.timeout, .result = NULL, }; - gettimeofday(&start_time, NULL); - err = nvme_io(&args, opcode); - gettimeofday(&end_time, NULL); - if (cfg.latency) - printf(" latency: %s: %llu us\n", command, elapsed_utime(start_time, end_time)); + + err = nvme_submit_io(&args, opcode, cfg.show, cfg.latency); if (err < 0) { nvme_show_error("submit-io: %s", nvme_strerror(errno)); } else if (err) { nvme_show_status(err); - } else { + } else if (!nvme_cfg.dry_run) { if (!(opcode & 1) && write(dfd, (void *)buffer, buffer_size) < 0) { nvme_show_error("write: %s: failed to write buffer to output file", strerror(errno)); diff --git a/util/logging.c b/util/logging.c index 616c615169..8a7cd162de 100644 --- a/util/logging.c +++ b/util/logging.c @@ -150,3 +150,51 @@ int nvme_submit_passthru64(int fd, unsigned long ioctl_cmd, return err; } + +static void nvme_show_io_command(struct nvme_io_args *args, __u8 opcode) +{ + __u32 dsmgmt = args->dsm; + __u8 dtype = (args->control >> 4) & 0xf; + + if (dtype) + dsmgmt |= ((__u32)args->dspec) << 16; + + printf("opcode : %02x\n", opcode); + printf("nsid : %02x\n", args->nsid); + printf("flags : %02x\n", 0); + printf("control : %04x\n", args->control); + printf("nblocks : %04x\n", args->nlb); + printf("metadata : %"PRIx64"\n", (uint64_t)(uintptr_t)args->metadata); + printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)args->data); + printf("slba : %"PRIx64"\n", (uint64_t)(uintptr_t)args->slba); + printf("dsmgmt : %08x\n", dsmgmt); + printf("reftag : %"PRIx64"\n", (uint64_t)args->reftag_u64); + printf("apptag : %04x\n", args->apptag); + printf("appmask : %04x\n", args->appmask); + printf("storagetagcheck : %04x\n", args->control & NVME_IO_STC ? true : false); + printf("storagetag : %"PRIx64"\n", (uint64_t)args->storage_tag); + printf("pif : %02x\n", args->pif); + printf("sts : %02x\n", args->sts); +} + +int nvme_submit_io(struct nvme_io_args *args, __u8 opcode, bool show, bool latency) +{ + struct timeval start_time; + struct timeval end_time; + int err; + + if (show || dry_run) + nvme_show_io_command(args, opcode); + + if (dry_run) + return 0; + + gettimeofday(&start_time, NULL); + err = nvme_io(args, opcode); + gettimeofday(&end_time, NULL); + + if (latency) + nvme_show_latency(start_time, end_time); + + return err; +} diff --git a/util/logging.h b/util/logging.h index 5828189079..1a25c8f870 100644 --- a/util/logging.h +++ b/util/logging.h @@ -21,5 +21,5 @@ extern int log_level; int map_log_level(int verbose, bool quiet); void set_dry_run(bool enable); - +int nvme_submit_io(struct nvme_io_args *args, __u8 opcode, bool show, bool latency); #endif // DEBUG_H_