From 4c5a10572392a50cd8708a734376cdb0ca8cc15c Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 2 Jun 2026 13:27:17 +0200 Subject: [PATCH] nvme: do not print status message on default Unix tools should remain silent on success and produce output only when it is part of their functional result. Emitting status messages by default violates the long-established convention that stdout is reserved for machine-consumable data, while diagnostics and optional progress reporting belong on stderr or behind an explicit verbose flag. A core strength of Unix tooling is composability: commands are routinely used in pipelines, shell scripts, automation frameworks, and other programs. Unsolicited status output contaminates stdout, forcing consumers to implement fragile filtering logic and making the tool harder to integrate reliably. The absence of default status messages is therefore not merely a stylistic preference but an interoperability requirement. This follows the traditional Unix principle that "no news is good news": successful execution is indicated by the exit status, not by human-readable confirmation text. Users who need operational visibility can opt into it through verbose or progress-reporting options, while automation and existing workflows continue to receive clean, deterministic output. Signed-off-by: Daniel Wagner --- nvme-print.c | 19 +++++++++ nvme-print.h | 3 ++ nvme.c | 115 +++++++++++++++++++++++++++++---------------------- 3 files changed, 88 insertions(+), 49 deletions(-) diff --git a/nvme-print.c b/nvme-print.c index 2b59971f47..99324f1608 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -1743,6 +1743,25 @@ void nvme_show_message(bool error, const char *msg, ...) va_end(ap); } +void nvme_show_verbose_message(const char *msg, ...) +{ + struct print_ops *ops = nvme_print_ops(NORMAL); + va_list ap; + + if (!nvme_args.verbose) + return; + + va_start(ap, msg); + + if (nvme_is_output_format_json()) + ops = nvme_print_ops(JSON); + + if (ops && ops->show_message) + ops->show_message(true, msg, ap); + + va_end(ap); +} + void nvme_show_perror(const char *msg, ...) { struct print_ops *ops = nvme_print_ops(NORMAL); diff --git a/nvme-print.h b/nvme-print.h index 122e5116fe..70499dfca2 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -17,6 +17,8 @@ typedef struct nvme_effects_log_node { #define nvme_show_error(msg, ...) nvme_show_message(true, msg, ##__VA_ARGS__) #define nvme_show_result(msg, ...) nvme_show_message(false, msg, ##__VA_ARGS__) +#define nvme_show_verbose_result(msg, ...) nvme_show_verbose_message(msg, ##__VA_ARGS__) +#define nvme_show_verbose_info(msg, ...) nvme_show_verbose_message(msg, ##__VA_ARGS__) #define POWER_OF_TWO(exponent) (1 << (exponent)) @@ -373,6 +375,7 @@ const char *nvme_ipmsr_srs_to_string(__u8 srs); void nvme_dev_full_path(libnvme_ns_t n, char *path, size_t len); void nvme_generic_full_path(libnvme_ns_t n, char *path, size_t len); void nvme_show_message(bool error, const char *msg, ...); +void nvme_show_verbose_message(const char *msg, ...); void nvme_show_perror(const char *msg, ...); void nvme_show_error_status(int status, const char *msg, ...); void nvme_show_init(void); diff --git a/nvme.c b/nvme.c index 81acc38c67..ed262b01e9 100644 --- a/nvme.c +++ b/nvme.c @@ -503,6 +503,16 @@ int validate_output_format(const char *format, nvme_print_flags_t *flags) return 0; } +bool nvme_is_output_format_normal(void) +{ + nvme_print_flags_t flags; + + if (validate_output_format(nvme_args.output_format, &flags)) + return false; + + return flags == NORMAL; +} + bool nvme_is_output_format_json(void) { nvme_print_flags_t flags; @@ -2217,8 +2227,8 @@ static int io_mgmt_send(int argc, char **argv, struct command *acmd, struct plug return err; } - printf("io-mgmt-send: Success, mos:%u mo:%u nsid:%d\n", cfg.mos, cfg.mo, - cfg.nsid); + nvme_show_verbose_result("io-mgmt-send: Success, mos:%u mo:%u nsid:%d", + cfg.mos, cfg.mo, cfg.nsid); return err; } @@ -2280,8 +2290,8 @@ static int io_mgmt_recv(int argc, char **argv, struct command *acmd, struct plug return err; } - printf("io-mgmt-recv: Success, mos:%u mo:%u nsid:%d\n", cfg.mos, cfg.mo, - cfg.nsid); + nvme_show_verbose_result("io-mgmt-recv: Success, mos:%u mo:%u nsid:%d", + cfg.mos, cfg.mo, cfg.nsid); if (cfg.file) { dfd = open(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0644); @@ -2942,6 +2952,9 @@ static void ns_mgmt_show_status(struct libnvme_transport_handle *hdl, int err, c return; } + if (!err && !nvme_args.verbose && nvme_is_output_format_normal()) + return; + nvme_show_init(); if (!err) { @@ -4408,8 +4421,8 @@ static int id_domain(int argc, char **argv, struct command *acmd, struct plugin return err; } - printf("NVMe Identify command for Domain List is successful:\n"); - printf("NVMe Identify Domain List:\n"); + nvme_show_verbose_result("NVMe Identify command for Domain List is successful:"); + nvme_show_verbose_result("NVMe Identify Domain List:"); nvme_show_id_domain_list(id_domain, flags); return err; @@ -4502,8 +4515,9 @@ static int virtual_mgmt(int argc, char **argv, struct command *acmd, struct plug return err; } - printf("success, Number of Controller Resources Modified (NRM):%" - PRIu64 "\n", (uint64_t)cmd.result); + nvme_show_verbose_result( + "success, Number of Controller Resources Modified (NRM):%" PRIu64, + (uint64_t)cmd.result); return err; } @@ -5321,7 +5335,7 @@ static int fw_download(int argc, char **argv, struct command *acmd, struct plugi /* end the progress output */ if (cfg.progress) printf("\n"); - printf("Firmware download success\n"); + nvme_show_verbose_result("Firmware download success"); } return err; @@ -5506,11 +5520,12 @@ static int fw_commit(int argc, char **argv, struct command *acmd, struct plugin return err; } - printf("Success committing firmware action:%d slot:%d", - cfg.action, cfg.slot); if (cfg.action == 6 || cfg.action == 7) - printf(" bpid:%d", cfg.bpid); - printf("\n"); + nvme_show_verbose_result("Success committing firmware action:%d slot:%d bpid:%d", + cfg.action, cfg.slot, cfg.bpid); + else + nvme_show_verbose_result("Success committing firmware action:%d slot:%d", + cfg.action, cfg.slot); fw_commit_print_mud(mud_supported, cmd.result); return err; @@ -5541,8 +5556,10 @@ static int subsystem_reset(int argc, char **argv, struct command *acmd, struct p nvme_show_error("Subsystem-reset: NVM Subsystem Reset not supported."); else nvme_show_error("Subsystem-reset: %s", libnvme_strerror(-err)); - } else if (nvme_args.verbose) - printf("resetting subsystem through %s\n", libnvme_transport_handle_get_name(hdl)); + } else { + nvme_show_verbose_info("resetting subsystem through %s", + libnvme_transport_handle_get_name(hdl)); + } return err; } @@ -5569,8 +5586,9 @@ static int reset(int argc, char **argv, struct command *acmd, struct plugin *plu err = libnvme_reset_ctrl(hdl); if (err < 0) nvme_show_error("Reset: %s", libnvme_strerror(-err)); - else if (nvme_args.verbose) - printf("resetting controller %s\n", libnvme_transport_handle_get_name(hdl)); + else + nvme_show_verbose_info("resetting controller %s", + libnvme_transport_handle_get_name(hdl)); return err; } @@ -5604,8 +5622,9 @@ static int ns_rescan(int argc, char **argv, struct command *acmd, struct plugin err = libnvme_rescan_ns(hdl); if (err < 0) nvme_show_error("Namespace Rescan: %s\n", libnvme_strerror(-err)); - else if (nvme_args.verbose) - printf("rescanning namespaces through %s\n", libnvme_transport_handle_get_name(hdl)); + else + nvme_show_verbose_info("rescanning namespaces through %s", + libnvme_transport_handle_get_name(hdl)); return err; } @@ -6898,7 +6917,7 @@ static int format_cmd(int argc, char **argv, struct command *acmd, struct plugin return err; } - printf("Success formatting namespace:%x\n", cfg.namespace_id); + nvme_show_verbose_result("Success formatting namespace:%x", cfg.namespace_id); if (libnvme_transport_handle_is_direct(hdl) && cfg.lbaf != prev_lbaf) { if (libnvme_transport_handle_is_ctrl(hdl)) { if (libnvme_rescan_ns(hdl) < 0) { @@ -7196,7 +7215,7 @@ static int sec_send(int argc, char **argv, struct command *acmd, struct plugin * return err; } - printf("NVME Security Send Command Success\n"); + nvme_show_verbose_result("NVME Security Send Command Success"); return err; } @@ -7394,7 +7413,7 @@ static int write_uncor(int argc, char **argv, struct command *acmd, struct plugi return err; } - printf("NVME Write Uncorrectable Success\n"); + nvme_show_verbose_result("NVME Write Uncorrectable Success"); return err; } @@ -7668,7 +7687,7 @@ static int write_zeroes(int argc, char **argv, return err; } - printf("NVME Write Zeroes Success\n"); + nvme_show_verbose_result("NVME Write Zeroes Success"); if (!cfg.nsz || !nvme_args.verbose) return err; @@ -7792,7 +7811,7 @@ static int dsm(int argc, char **argv, struct command *acmd, struct plugin *plugi return err; } - printf("NVMe DSM: success\n"); + nvme_show_verbose_result("NVMe DSM: success"); return err; } @@ -8010,7 +8029,7 @@ static int copy_cmd(int argc, char **argv, struct command *acmd, struct plugin * return err; } - nvme_show_key_value("NVMe Copy", "success"); + nvme_show_verbose_result("NVMe Copy: success"); return err; } @@ -8060,7 +8079,7 @@ static int flush_cmd(int argc, char **argv, struct command *acmd, struct plugin return err; } - printf("NVMe Flush: success\n"); + nvme_show_verbose_result("NVMe Flush: success"); return err; } @@ -8138,7 +8157,7 @@ static int resv_acquire(int argc, char **argv, struct command *acmd, struct plug return err; } - printf("NVME Reservation Acquire success\n"); + nvme_show_verbose_result("NVME Reservation Acquire success"); return err; } @@ -8220,7 +8239,7 @@ static int resv_register(int argc, char **argv, struct command *acmd, struct plu return err; } - printf("NVME Reservation success\n"); + nvme_show_verbose_result("NVME Reservation success"); return err; } @@ -8297,7 +8316,7 @@ static int resv_release(int argc, char **argv, struct command *acmd, struct plug return err; } - printf("NVME Reservation Release success\n"); + nvme_show_verbose_result("NVME Reservation Release success"); return err; } @@ -8723,7 +8742,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char libnvme_strerror(errno)); err = -EINVAL; } else { - fprintf(stderr, "%s: Success\n", command); + nvme_show_verbose_result("%s: Success", command); } return err; @@ -8849,7 +8868,7 @@ static int verify_cmd(int argc, char **argv, struct command *acmd, struct plugin return err; } - printf("NVME Verify Success\n"); + nvme_show_verbose_result("NVME Verify Success"); return err; } @@ -8935,7 +8954,7 @@ static int sec_recv(int argc, char **argv, struct command *acmd, struct plugin * return err; } - printf("NVME Security Receive Command Success\n"); + nvme_show_verbose_result("NVME Security Receive Command Success"); if (!cfg.raw_binary) d(sec_buf, cfg.size, 16, 1); else if (cfg.size) @@ -9102,7 +9121,7 @@ static int capacity_mgmt(int argc, char **argv, struct command *acmd, struct plu return err; } - printf("Capacity Management Command is Success\n"); + nvme_show_verbose_result("Capacity Management Command is Success"); if (cfg.operation == 1) printf("Created Element Identifier for Endurance Group is: %" @@ -9311,7 +9330,7 @@ static int lockdown_cmd(int argc, char **argv, struct command *acmd, struct plug return err; } - printf("Lockdown Command is Successful\n"); + nvme_show_verbose_result("Lockdown Command is Successful"); return err; } @@ -9564,10 +9583,10 @@ static int passthru(int argc, char **argv, bool admin, return err; } - fprintf(stderr, "%s Command %s is Success and result: 0x%" PRIx64 "\n", - admin ? "Admin" : "IO", - strcmp(cmd_name, "Unknown") ? - cmd_name : "Vendor Specific", (uint64_t)cmd.result); + nvme_show_verbose_result("%s Command %s is Success and result: 0x%" PRIx64, + admin ? "Admin" : "IO", + strcmp(cmd_name, "Unknown") ? + cmd_name : "Vendor Specific", (uint64_t)cmd.result); if (cfg.read) passthru_print_read_output(cfg, data, dfd, mdata, mfd, err); @@ -10338,8 +10357,7 @@ static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *p return err; } - if (nvme_args.verbose) - printf("exporting to %s\n", cfg.keyfile); + nvme_show_verbose_info("exporting to %s", cfg.keyfile); return 0; } else if (cfg.import) { @@ -10350,8 +10368,7 @@ static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *p return err; } - if (nvme_args.verbose) - printf("importing from %s\n", cfg.keyfile); + nvme_show_verbose_info("importing from %s", cfg.keyfile); } else { err = libnvme_revoke_tls_key(ctx, cfg.keyring, cfg.keytype, cfg.revoke); @@ -10361,8 +10378,7 @@ static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *p return err; } - if (nvme_args.verbose) - printf("revoking key\n"); + nvme_show_verbose_info("revoking key"); } if (old_umask != 0 && fd) { @@ -10615,12 +10631,13 @@ static int libnvme_mi(int argc, char **argv, __u8 admin_opcode, const char *desc } result = cmd.result; - printf( - "%s Command is Success and result: 0x%08x (status: 0x%02x, response: 0x%06x)\n", - nvme_cmd_to_string(true, admin_opcode), result, result & 0xff, - result >> 8); + nvme_show_verbose_result( + "%s Command is Success and result: 0x%08x (status: 0x%02x, response: 0x%06x)", + nvme_cmd_to_string(true, admin_opcode), result, + result & 0xff, result >> 8); if (result & 0xff) - printf("status: %s\n", libnvme_mi_status_to_string(result & 0xff)); + nvme_show_verbose_result("status: %s", + libnvme_mi_status_to_string(result & 0xff)); if (!send && strlen(cfg.input_file)) { if (write(fd, (void *)data, cfg.data_len) < 0) perror("failed to write data buffer");