Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package nvme-cli for openSUSE:Factory checked in at 2022-02-23 16:25:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nvme-cli (Old) and /work/SRC/openSUSE:Factory/.nvme-cli.new.1958 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nvme-cli" Wed Feb 23 16:25:57 2022 rev:50 rq:956835 version:2.0~4 Changes: -------- --- /work/SRC/openSUSE:Factory/nvme-cli/nvme-cli.changes 2022-02-13 19:50:35.162139705 +0100 +++ /work/SRC/openSUSE:Factory/.nvme-cli.new.1958/nvme-cli.changes 2022-02-23 16:26:35.667509140 +0100 @@ -1,0 +2,15 @@ +Tue Feb 22 17:45:10 UTC 2022 - Daniel Wagner <daniel.wag...@suse.com> + +- Update to version 2.0-rc4: + * netapp-nvme: free the nsdescs pointer after use + * netapp-nvme: fix ontapdevices segfault in json output + * nvme-print: fix 'nvme list -o json' segfault + * nvme: get_ns_id command fails on nvme device + * wdc: updated products list for telemetry (--type) argument + * docs: fix typo in Data Set Management section + * Fix ctrlist for attach-ns and detach-ns + * netapp-nvme: fix nvme ns desc uuid handling for ontapdevices + * wdc: Fix use-after-free access of cbs_data + * Fixed regression with 'open namespace exclusive' (bsc#1195945) + +------------------------------------------------------------------- Old: ---- nvme-cli-2.0~3.obscpio New: ---- nvme-cli-2.0~4.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nvme-cli.spec ++++++ --- /var/tmp/diff_new_pack.UC4P9z/_old 2022-02-23 16:26:36.387509166 +0100 +++ /var/tmp/diff_new_pack.UC4P9z/_new 2022-02-23 16:26:36.399509167 +0100 @@ -17,7 +17,7 @@ Name: nvme-cli -Version: 2.0~3 +Version: 2.0~4 Release: 0 Summary: NVM Express user space tools License: GPL-2.0-only @@ -31,7 +31,7 @@ BuildRequires: gcc-c++ BuildRequires: libhugetlbfs-devel BuildRequires: libjson-c-devel -BuildRequires: libnvme-devel >= 1.0~3 +BuildRequires: libnvme-devel >= 1.0~4 BuildRequires: libuuid-devel BuildRequires: make BuildRequires: meson >= 0.47.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.UC4P9z/_old 2022-02-23 16:26:36.435509167 +0100 +++ /var/tmp/diff_new_pack.UC4P9z/_new 2022-02-23 16:26:36.435509167 +0100 @@ -5,7 +5,7 @@ <param name="filename">nvme-cli</param> <!-- <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param> --> <param name="versionformat">@PARENT_TAG@</param> - <param name="revision">v2.0-rc3</param> + <param name="revision">v2.0-rc4</param> <param name="match-tag">v[02].[0-9]*</param> <param name="versionrewrite-pattern">v([^+]*)-rc([0-9]+)</param> <param name="versionrewrite-replacement">\1~\2</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.UC4P9z/_old 2022-02-23 16:26:36.455509169 +0100 +++ /var/tmp/diff_new_pack.UC4P9z/_new 2022-02-23 16:26:36.459509168 +0100 @@ -1,7 +1,7 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/linux-nvme/nvme-cli.git</param> - <param name="changesrevision">f02a78a4599b4fbee9ca82fb887f2736c5a67bb8</param> + <param name="changesrevision">59263bbcd3e4f5eaffe7d200c4cad2a361008e48</param> </service> </servicedata> (No newline at EOF) ++++++ nvme-cli-2.0~3.obscpio -> nvme-cli-2.0~4.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/Documentation/cmds-main.txt new/nvme-cli-2.0~4/Documentation/cmds-main.txt --- old/nvme-cli-2.0~3/Documentation/cmds-main.txt 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/Documentation/cmds-main.txt 2022-02-22 18:25:01.000000000 +0100 @@ -10,7 +10,7 @@ linknvme:nvme-flush[1]:: Submit flush -linknvme:nvme-dms[1]:: +linknvme:nvme-dsm[1]:: Submit Data Set Management linknvme:nvme-format[1]:: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/meson_options.txt new/nvme-cli-2.0~4/meson_options.txt --- old/nvme-cli-2.0~3/meson_options.txt 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/meson_options.txt 2022-02-22 18:25:01.000000000 +0100 @@ -4,4 +4,4 @@ option('htmldir', type : 'string', value : '', description : 'directory for HTML documentation') option('docs', type : 'combo', choices : ['false', 'html', 'man', 'all'], description : 'install documentation') -option('docs-build', type : 'boolean', value : 'false', description : 'build documentation') +option('docs-build', type : 'boolean', value : false, description : 'build documentation') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/nvme-print.c new/nvme-cli-2.0~4/nvme-print.c --- old/nvme-cli-2.0~3/nvme-print.c 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/nvme-print.c 2022-02-22 18:25:01.000000000 +0100 @@ -523,7 +523,7 @@ json_object_add_value_int(fwsi, "Active Firmware Slot (afi)", fw_log->afi); for (i = 0; i < 7; i++) { - if (fw_log->frs[i]) { + if (fw_log->frs[i][0]) { snprintf(fmt, sizeof(fmt), "Firmware Rev Slot %d", i + 1); frs = (__le64 *)&fw_log->frs[i]; @@ -5683,7 +5683,7 @@ printf("Firmware Log for device:%s\n", devname); printf("afi : %#x\n", fw_log->afi); for (i = 0; i < 7; i++) { - if (fw_log->frs[i]) { + if (fw_log->frs[i][0]) { frs = (__le64 *)&fw_log->frs[i]; printf("frs%d : %#016"PRIx64" (%s)\n", i + 1, le64_to_cpu(*frs), @@ -7206,8 +7206,8 @@ json_array_add_value_object(jdevices, json_list_item(n)); } - json_object_add_value_object(jroot, "devices", jdevices); } + json_object_add_value_array(jroot, "devices", jdevices); json_print_object(jroot, NULL); printf("\n"); json_free_object(jroot); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/nvme.c new/nvme-cli-2.0~4/nvme.c --- old/nvme-cli-2.0~3/nvme.c 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/nvme.c 2022-02-22 18:25:01.000000000 +0100 @@ -267,35 +267,29 @@ int parse_and_open(int argc, char **argv, const char *desc, const struct argconfig_commandline_options *opts) { - const struct argconfig_commandline_options *s; - int flags = O_RDONLY; int ret; ret = argconfig_parse(argc, argv, desc, opts); if (ret) return ret; - for (s = opts; s && s->option; s++) { - if (!strcmp(s->option, "force")) { - if (*(int *)s->default_value) - flags |= O_EXCL; - break; - } - } + ret = get_dev(argc, argv, O_RDONLY); + if (ret < 0) + argconfig_print_help(desc, opts); - ret = get_dev(argc, argv, flags); - if (ret < 0) { - if (errno == EBUSY) { - fprintf(stderr, "Failed to open %s.\n" \ - "Namespace is currently busy.\n" \ - "Use the force [--force] option to ignore that.\n", - basename(argv[optind])); - } else - argconfig_print_help(desc, opts); - } return ret; } +int open_exclusive(int argc, char **argv, int ignore_exclusive) +{ + int flags = O_RDONLY; + + if (!ignore_exclusive) + flags |= O_EXCL; + + return get_dev(argc, argv, flags); +} + enum nvme_print_flags validate_output_format(const char *format) { if (!format) @@ -2174,7 +2168,7 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, struct command *cmd) { - int err, num, fd, list[2048]; + int err, num, fd, i, list[2048]; struct nvme_ctrl_list cntlist; __u16 ctrlist[2048]; @@ -2220,6 +2214,9 @@ goto close_fd; } + for (i = 0; i < num; i++) + ctrlist[i] = (__u16)list[i]; + nvme_init_ctrl_list(&cntlist, num, ctrlist); if (attach) @@ -3259,7 +3256,7 @@ goto ret; err = nvme_get_nsid(fd, &nsid); - if (err <= 0) { + if (err < 0) { fprintf(stderr, "get namespace ID: %s\n", nvme_strerror(errno)); err = errno; goto close_fd; @@ -4098,7 +4095,6 @@ const char *ause_desc = "Allow unrestricted sanitize exit."; const char *sanact_desc = "Sanitize action."; const char *ovrpat_desc = "Overwrite pattern."; - const char *force_desc = "The \"I know what I'm doing\" flag, skip confirmation before sending command"; int fd, err; struct config { @@ -4108,7 +4104,6 @@ int ause; __u8 sanact; __u32 ovrpat; - int force; }; struct config cfg = { @@ -4118,7 +4113,6 @@ .ause = 0, .sanact = 0, .ovrpat = 0, - .force = 0, }; OPT_ARGS(opts) = { @@ -4128,7 +4122,6 @@ OPT_FLAG("ause", 'u', &cfg.ause, ause_desc), OPT_BYTE("sanact", 'a', &cfg.sanact, sanact_desc), OPT_UINT("ovrpat", 'p', &cfg.ovrpat, ovrpat_desc), - OPT_FLAG("force", 0, &cfg.force, force_desc), OPT_END() }; @@ -4521,9 +4514,25 @@ OPT_END() }; - err = fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = argconfig_parse(argc, argv, desc, opts); + if (err) + goto ret; + + err = fd = open_exclusive(argc, argv, cfg.force); + if (fd < 0) { + if (errno == EBUSY) { + fprintf(stderr, "Failed to open %s.\n", + basename(argv[optind])); + fprintf(stderr, + "Namespace is currently busy.\n"); + if (!cfg.force) + fprintf(stderr, + "Use the force [--force] option to ignore that.\n"); + } else { + argconfig_print_help(desc, opts); + } goto ret; + } if (cfg.lbaf != 0xff && cfg.bs !=0) { fprintf(stderr, @@ -4641,7 +4650,7 @@ nvme_show_relatives(devicename); fprintf(stderr, "WARNING: Format may irrevocably delete this device's data.\n" "You have 10 seconds to press Ctrl-C to cancel this operation.\n\n" - "Use the force [--force|-f] option to suppress this warning.\n"); + "Use the force [--force] option to suppress this warning.\n"); sleep(10); fprintf(stderr, "Sending format operation ... \n"); } @@ -5179,27 +5188,23 @@ const char *namespace_id = "desired namespace"; const char *start_block = "64-bit LBA of first block to access"; const char *block_count = "number of blocks (zeroes based) on device to access"; - const char *force_desc = "The \"I know what I'm doing\" flag, skip confirmation before sending command"; struct config { __u64 start_block; __u32 namespace_id; __u16 block_count; - int force; }; struct config cfg = { .start_block = 0, .namespace_id = 0, .block_count = 0, - .force = 0, }; OPT_ARGS(opts) = { OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id), OPT_SUFFIX("start-block", 's', &cfg.start_block, start_block), OPT_SHRT("block-count", 'c', &cfg.block_count, block_count), - OPT_FLAG("force", 0, &cfg.force, force_desc), OPT_END() }; @@ -5258,7 +5263,6 @@ const char *deac = "Set DEAC bit, requesting controller to deallocate specified logical blocks"; const char *storage_tag_check = "This bit specifies the Storage Tag field shall be checked as "\ "part of end-to-end data protection processing"; - const char *force = "The \"I know what I'm doing\" flag, open device even it is already used"; struct config { __u64 start_block; @@ -5273,7 +5277,6 @@ int limited_retry; int force_unit_access; int storage_tag_check; - int force; }; struct config cfg = { @@ -5285,7 +5288,6 @@ .app_tag = 0, .storage_tag = 0, .storage_tag_check = 0, - .force = 0, }; OPT_ARGS(opts) = { @@ -5301,7 +5303,6 @@ OPT_SHRT("app-tag", 'a', &cfg.app_tag, app_tag), OPT_SUFFIX("storage-tag", 'S', &cfg.storage_tag, storage_tag), OPT_FLAG("storage-tag-check", 'C', &cfg.storage_tag_check, storage_tag_check), - OPT_FLAG("force", 0, &cfg.force, force), OPT_END() }; @@ -6061,7 +6062,7 @@ "checked as part of end-to-end data protection processing"; const char *storage_tag = "storage tag, CDW2 and CDW3 (00:47) bits "\ "(for end to end PI)"; - const char *force = "The \"I know what I'm doing\" flag, open device even it is already in use"; + const char *force = "The \"I know what I'm doing\" flag, do not enforce exclusive access for write"; struct config { __u32 namespace_id; @@ -6092,17 +6093,17 @@ .namespace_id = 0, .start_block = 0, .block_count = 0, - .data_size = 0, + .data_size = 0, .metadata_size = 0, - .ref_tag = 0, - .data = "", - .metadata = "", - .prinfo = 0, + .ref_tag = 0, + .data = "", + .metadata = "", + .prinfo = 0, .app_tag_mask = 0, - .app_tag = 0, + .app_tag = 0, .storage_tag_check = 0, .storage_tag = 0, - .force = 0, + .force = 0, }; OPT_ARGS(opts) = { @@ -6127,16 +6128,28 @@ OPT_FLAG("show-command", 'v', &cfg.show, show), OPT_FLAG("dry-run", 'w', &cfg.dry_run, dry), OPT_FLAG("latency", 't', &cfg.latency, latency), - OPT_FLAG("force", 0, &cfg.force, force), + OPT_FLAG("force", 0, &cfg.force, force), OPT_END() }; - if (opcode != nvme_cmd_write) - cfg.force = 1; - - err = fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - goto ret; + if (opcode != nvme_cmd_write) { + err = fd = parse_and_open(argc, argv, desc, opts); + if (fd < 0) + goto ret; + } else { + err = fd = open_exclusive(argc, argv, cfg.force); + if (errno == EBUSY) { + fprintf(stderr, "Failed to open %s.\n", + basename(argv[optind])); + fprintf(stderr, + "Namespace is currently busy.\n"); + if (!cfg.force) + fprintf(stderr, + "Use the force [--force] option to ignore that.\n"); + } else { + argconfig_print_help(desc, opts); + } + } if (!cfg.namespace_id) { err = nvme_get_nsid(fd, &cfg.namespace_id); @@ -6373,7 +6386,7 @@ const char *start_block = "64-bit LBA of first block to access"; const char *block_count = "number of blocks (zeroes based) on device to access"; const char *limited_retry = "limit media access attempts"; - const char *force = "force device to commit cached data before performing the verify operation"; + const char *force_unit_access = "force device to commit cached data before performing the verify operation"; const char *prinfo = "PI and check field"; const char *ref_tag = "reference tag (for end to end PI)"; const char *app_tag_mask = "app tag mask (for end to end PI)"; @@ -6416,7 +6429,7 @@ OPT_SUFFIX("start-block", 's', &cfg.start_block, start_block), OPT_SHRT("block-count", 'c', &cfg.block_count, block_count), OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry), - OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force), + OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access), OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo), OPT_UINT("ref-tag", 'r', &cfg.ref_tag, ref_tag), OPT_SHRT("app-tag", 'a', &cfg.app_tag, app_tag), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/plugins/intel/intel-nvme.c new/nvme-cli-2.0~4/plugins/intel/intel-nvme.c --- old/nvme-cli-2.0~3/plugins/intel/intel-nvme.c 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/plugins/intel/intel-nvme.c 2022-02-22 18:25:01.000000000 +0100 @@ -656,12 +656,11 @@ /* * For 4.0-4.5 revision. */ +#define LATENCY_STATS_V4_BASE_BITS 6 +#define LATENCY_STATS_V4_BASE_VAL (1 << LATENCY_STATS_V4_BASE_BITS) + static int lat_stats_log_scale(int i) { - static const int LATENCY_STATS_V4_BASE_BITS = 6; - static const int LATENCY_STATS_V4_BASE_VAL = ( - 1 << LATENCY_STATS_V4_BASE_BITS); - // if (i < 128) if (i < (LATENCY_STATS_V4_BASE_VAL << 1)) return i; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/plugins/micron/micron-nvme.c new/nvme-cli-2.0~4/plugins/micron/micron-nvme.c --- old/nvme-cli-2.0~3/plugins/micron/micron-nvme.c 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/plugins/micron/micron-nvme.c 2022-02-22 18:25:01.000000000 +0100 @@ -41,7 +41,7 @@ /* Plugin version major_number.minor_number.patch */ static const char *__version_major = "1"; static const char *__version_minor = "0"; -static const char *__version_patch = "7"; +static const char *__version_patch = "8"; /* supported models of micron plugin; new models should be added at the end * before UNKNOWN_MODEL. Make sure M5410 is first in the list ! @@ -117,6 +117,7 @@ } if (vendor_id == MICRON_VENDOR_ID) { switch (device_id) { + case 0x5196: case 0x51A0: case 0x51A1: case 0x51A2: @@ -1187,8 +1188,8 @@ { "Normalized Bad System NAND Block Count", 2, 2}, { "Raw Bad System NAND Block Count", 6, 6}, { "Endurance Estimate", 16, 16}, - { "Thermal Throttling Count", 1, 1}, { "Thermal Throttling Status", 1, 1}, + { "Thermal Throttling Count", 1, 1}, { "Unaligned I/O", 8, 8}, { "Physical Media Units Read", 16, 16}, { "Reserved", 279, 0}, @@ -1661,7 +1662,7 @@ WriteData((__u8*)&effects, sizeof(effects), dir, "command_effects_log.bin", "effects log"); } - + /* get persistent event log */ (void)nvme_get_log_persistent_event(fd, NVME_PEVENT_LOG_RELEASE_CTX, sizeof(pevent_log), &pevent_log); @@ -2204,11 +2205,320 @@ return err; } -static int micron_error_reason(int argc, char **argv, struct command *cmd, +#define MICRON_FID_LATENCY_MONITOR 0xD0 +#define MICRON_LOG_LATENCY_MONITOR 0xD1 + +static int micron_latency_stats_track(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - printf("This command is not implemented for the drive\n"); - return 0; + int err = 0; + __u32 result = 0; + const char *desc = "Enable, Disable or Get cmd latency monitoring stats"; + const char *option = "enable or disable or status, default is status"; + const char *command = "commands to monitor for - all|read|write|trim," + " default is all i.e, enabled for all commands"; + const char *thrtime = "The threshold value to use for latency monitoring in" + " milliseconds, default is 800ms"; + + int fd = 0; + int fid = MICRON_FID_LATENCY_MONITOR; + eDriveModel model = UNKNOWN_MODEL; + uint32_t command_mask = 0x7; /* 1:read 2:write 4:trim 7:all */ + uint32_t timing_mask = 0x08080800; /* R[31-24]:W[23:16]:T[15:8]:0 */ + uint32_t enable = 2; + struct { + char *option; + char *command; + uint32_t threshold; + } opt = { + .option = "status", + .command = "all", + .threshold = 0 + }; + + OPT_ARGS(opts) = { + OPT_STRING("option", 'o', "option", &opt.option, option), + OPT_STRING("command", 'c', "command", &opt.command, command), + OPT_UINT("threshold", 't', &opt.threshold, thrtime), + OPT_END() + }; + + + if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) { + return -1; + } + + if (!strcmp(opt.option, "enable")) { + enable = 1; + } else if (!strcmp(opt.option, "disable")) { + enable = 0; + } else if (strcmp(opt.option, "status")) { + printf("Invalid control option %s specified\n", opt.option); + return -1; + } + + struct nvme_get_features_args g_args = { + .args_size = sizeof(g_args), + .fd = fd, + .fid = fid, + .nsid = 0, + .sel = 0, + .cdw11 = 0, + .uuidx = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + + err = nvme_get_features(&g_args); + if (err != 0) { + printf("Failed to retrieve latency monitoring feature status\n"); + return err; + } + + /* If it is to retrieve the status only */ + if (enable == 2) { + printf("Latency Tracking Statistics is currently %s", + (result & 0xFFFF0000) ? "enabled" : "disabled"); + if ((result & 7) == 7) { + printf(" for All commands\n"); + } else if ((result & 7) > 0) { + printf(" for"); + if (result & 1) { + printf(" Read"); + } + if (result & 2) { + printf(" Write"); + } + if (result & 4) { + printf(" Trim"); + } + printf(" commands\n"); + } else if (result == 0) { + printf("\n"); + } + return err; + } + + /* read and validate threshold values if enable option is specified */ + if (enable == 1) { + if (opt.threshold > 2550) { + printf("The maximum threshold value cannot be more than 2550 ms\n"); + return -1; + } + /* timing mask is in terms of 10ms units, so min allowed is 10ms */ + else if ((opt.threshold % 10) != 0) { + printf("The threshold value should be multiple of 10 ms\n"); + return -1; + } + opt.threshold /= 10; + } + + /* read-in command(s) to be monitored */ + if (!strcmp(opt.command, "read")) { + command_mask = 0x1; + timing_mask = (opt.threshold << 24); + } else if (!strcmp(opt.command, "write")) { + command_mask = 0x2; + timing_mask = (opt.threshold << 16); + } else if (!strcmp(opt.command, "read")) { + command_mask = 0x4; + timing_mask = (opt.threshold << 8); + } else if (strcmp(opt.command, "all")) { + printf("Invalid command %s specified for option %s\n", + opt.command, opt.option); + return -1; + } + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = MICRON_FID_LATENCY_MONITOR, + .nsid = 0, + .cdw11 = enable, + .cdw12 = command_mask, + .save = 1, + .uuidx = 0, + .cdw13 = timing_mask, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (err == 0) { + printf("Successfully %sed latency monitoring for %s commands\n", + opt.option, opt.command); + } else { + printf("Failed to %s latency monitoring for %s commands\n", + opt.option, opt.command); + } + + close(fd); + return err; +} + + +static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ +#define LATENCY_LOG_ENTRIES 16 + struct latency_log_entry { + uint64_t timestamp; + uint32_t latency; + uint32_t cmdtag; + union { + struct { + uint32_t opcode:8; + uint32_t fuse:2; + uint32_t rsvd1:4; + uint32_t psdt:2; + uint32_t cid:16; + }; + uint32_t dw0; + }; + uint32_t nsid; + uint32_t slba_low; + uint32_t slba_high; + union { + struct { + uint32_t nlb:16; + uint32_t rsvd2:9; + uint32_t deac:1; + uint32_t prinfo:4; + uint32_t fua:1; + uint32_t lr:1; + }; + uint32_t dw12; + }; + uint32_t dsm; + uint32_t rfu[6]; + } log[LATENCY_LOG_ENTRIES]; + eDriveModel model = UNKNOWN_MODEL; + int err = -1; + int fd = -1; + const char *desc = "Display Latency tracking log information"; + OPT_ARGS(opts) = { + OPT_END() + }; + + if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + return err; + memset(&log, 0, sizeof(log)); + err = nvme_get_log_simple(fd, 0xD1, sizeof(log), &log); + if (err) { + if (err < 0) + printf("Unable to retrieve latency stats log the drive\n"); + return err; + } + /* print header and each log entry */ + printf("Timestamp, Latency, CmdTag, Opcode, Fuse, Psdt,Cid, Nsid," + "Slba_L, Slba_H, Nlb, DEAC, PRINFO, FUA,LR\n"); + for (int i = 0; i < LATENCY_LOG_ENTRIES; i++) { + printf("%"PRIu64",%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n", + log[i].timestamp,log[i].latency, log[i].cmdtag, log[i].opcode, + log[i].fuse, log[i].psdt, log[i].cid, log[i].nsid, + log[i].slba_low, log[i].slba_high, log[i].nlb, + log[i].deac, log[i].prinfo, log[i].fua, log[i].lr); + } + printf("\n"); + return err; +} + +static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "display command latency statistics"; + const char *command = "command to display stats - all|read|write|trim" + "default is all"; + int err = 0; + int fd = -1; + eDriveModel model = UNKNOWN_MODEL; + #define LATENCY_BUCKET_COUNT 32 + struct micron_latency_stats { + uint64_t version; /* major << 32 | minior */ + uint64_t all_cmds[LATENCY_BUCKET_COUNT]; + uint64_t read_cmds[LATENCY_BUCKET_COUNT]; + uint64_t write_cmds[LATENCY_BUCKET_COUNT]; + uint64_t trim_cmds[LATENCY_BUCKET_COUNT]; + uint32_t reserved[765]; /* round up to 4K */ + } log; + + struct latency_thresholds { + uint32_t start; + uint32_t end; + char *unit; + } thresholds[LATENCY_BUCKET_COUNT] = { + {0, 50, "us"}, {50, 100, "us"}, {100, 150, "us"}, {150, 200, "us"}, + {200, 300, "us"}, {300, 400, "us"}, {400, 500, "us"}, {500, 600, "us"}, + {600, 700, "us"}, {700, 800, "us"}, {800, 900, "us"}, {900, 1000, "us"}, + {1, 5, "ms"}, {5, 10, "ms"}, {10, 20, "ms"}, {20, 50, "ms"}, {50, 100, "ms"}, + {100, 200, "ms"}, {200, 300, "ms"}, {300, 400, "ms"}, {400, 500, "ms"}, + {500, 600, "ms"}, {600, 700, "ms"}, {700, 800, "ms"}, {800, 900, "ms"}, + {900, 1000, "ms"}, {1, 2, "s"}, {2, 3, "s"}, {3, 4, "s"}, {4, 5, "s"}, + {5,8, "s"}, + {8, INT_MAX, "s"}, + }; + + struct { + char *command; + } opt = { + .command="all" + }; + + uint64_t *cmd_stats = &log.all_cmds[0]; + char *cmd_str = "All"; + + OPT_ARGS(opts) = { + OPT_STRING("command", 'c', "command", &opt.command, command), + OPT_END() + }; + + if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + return err; + if (!strcmp(opt.command, "read")) { + cmd_stats = &log.read_cmds[0]; + cmd_str = "Read"; + } else if (!strcmp(opt.command, "write")) { + cmd_stats = &log.write_cmds[0]; + cmd_str = "Write"; + } else if (!strcmp(opt.command, "trim")) { + cmd_stats = &log.trim_cmds[0]; + cmd_str = "Trim"; + } else if (strcmp(opt.command, "all")) { + printf("Invalid command option %s to display latency stats\n", opt.command); + return -1; + } + + memset(&log, 0, sizeof(log)); + err = nvme_get_log_simple(fd, 0xD0, sizeof(log), &log); + if (err) { + if (err < 0) + printf("Unable to retrieve latency stats log the drive\n"); + return err; + } + printf("Micron IO %s Command Latency Statistics\n" + "Major Revision : %d\nMinor Revision : %d\n", + cmd_str, (int)(log.version >> 32), (int)(log.version & 0xFFFFFFFF)); + printf("=============================================\n"); + printf("Bucket Start End Command Count\n"); + printf("=============================================\n"); + + for (int b = 0; b < LATENCY_BUCKET_COUNT; b++) { + int bucket = b + 1; + char start[32] = { 0 }; + char end[32] = { 0 }; + sprintf(start, "%u%s", thresholds[b].start, thresholds[b].unit); + if (thresholds[b].end == INT_MAX) + sprintf(end, "INF"); + else + sprintf(end, "%u%s", thresholds[b].end, thresholds[b].unit); + printf("%2d %8s %8s %8"PRIu64"\n", + bucket, start, end, cmd_stats[b]); + } + return err; } static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *cmd, @@ -2303,7 +2613,6 @@ return err; } - //err = nvme_set_feature(fd, 1, fid, cdw11, 0, opt.save, 0, 0, &result); err = nvme_set_features_simple(fd, fid, 1, 0, 0, &result); if (err == 0) err = (int)result; return err; @@ -2394,7 +2703,6 @@ printf("Failed to disable controller telemetry option\n"); } } else if (!strcmp(opt.option, "status")) { - ; struct nvme_get_features_args args = { .args_size = sizeof(args), .fd = fd, @@ -2580,7 +2888,7 @@ printf("Preparing log package. This will take a few seconds...\n"); - // trim spaces out of serial number string */ + /* trim spaces out of serial number string */ int i, j = 0; for (i = 0; i < sizeof(ctrl.sn); i++) { if (isblank((int)ctrl.sn[i])) @@ -2603,7 +2911,7 @@ GetSmartlogData(fd, strCtrlDirName); GetErrorlogData(fd, ctrl.elpe, strCtrlDirName); GetGenericLogs(fd, strCtrlDirName); - // pull if telemetry log data is supported + /* pull if telemetry log data is supported */ if ((ctrl.lpa & 0x8) == 0x8) GetTelemetryData(fd, strCtrlDirName); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/plugins/micron/micron-nvme.h new/nvme-cli-2.0~4/plugins/micron/micron-nvme.h --- old/nvme-cli-2.0~3/plugins/micron/micron-nvme.h 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/plugins/micron/micron-nvme.h 2022-02-22 18:25:01.000000000 +0100 @@ -21,7 +21,9 @@ ENTRY("cloud-SSD-plugin-version", "Display plugin version info", micron_cloud_ssd_plugin_version) ENTRY("log-page-directory", "Retrieve log page directory", micron_logpage_dir) ENTRY("vs-fw-activate-history", "Display FW activation history", micron_fw_activation_history) - ENTRY("vs-error-reason-identifier", "Retrieve Error reason", micron_error_reason) + ENTRY("latency-tracking", "Latency monitoring feature control", micron_latency_stats_track) + ENTRY("latency-stats", "Latency information for tracked commands", micron_latency_stats_info) + ENTRY("latency-logs", "Latency log details tracked by drive", micron_latency_stats_logs) ENTRY("vs-smart-add-log", "Retrieve extended SMART data", micron_ocp_smart_health_logs) ENTRY("clear-fw-activate-history", "Clear FW activation history", micron_clr_fw_activation_history) ENTRY("vs-smbus-option", "Enable/Disable SMBUS on the drive", micron_smbus_option) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/plugins/netapp/netapp-nvme.c new/nvme-cli-2.0~4/plugins/netapp/netapp-nvme.c --- old/nvme-cli-2.0~3/plugins/netapp/netapp-nvme.c 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/plugins/netapp/netapp-nvme.c 2022-02-22 18:25:01.000000000 +0100 @@ -67,7 +67,7 @@ unsigned nsid; struct nvme_id_ctrl ctrl; struct nvme_id_ns ns; - struct nvme_ns_id_desc nsdesc; + uuid_t uuid; unsigned char log_data[ONTAP_C2_LOG_SIZE]; char dev[265]; }; @@ -115,15 +115,6 @@ sprintf(size, "%.2f%sB", nsze, s_suffix); } -static void netapp_uuid_to_str(char *str, void *data) -{ - uuid_t uuid; - struct nvme_ns_id_desc *desc = data; - - memcpy(uuid, data + sizeof(*desc), 16); - uuid_unparse_lower(uuid, str); -} - static void ontap_labels_to_str(char *dst, char *src, int count) { int i; @@ -334,13 +325,13 @@ } else if (format == NJSON) { /* prepare for json output */ root = json_create_object(); - json_devices = json_create_object(); + json_devices = json_create_array(); } for (i = 0; i < count; i++) { netapp_get_ns_size(size, &lba, &devices[i].ns); - netapp_uuid_to_str(uuid_str, &devices[i].nsdesc); + uuid_unparse_lower(devices[i].uuid, uuid_str); netapp_get_ontap_labels(vsname, nspath, devices[i].log_data); if (format == NJSON) { @@ -357,6 +348,8 @@ /* complete the json output */ json_object_add_value_array(root, "ONTAPdevices", json_devices); json_print_object(root, NULL); + printf("\n"); + json_free_object(root); } } @@ -421,6 +414,7 @@ const char *dev) { int err; + void *nsdescs; err = nvme_identify_ctrl(fd, &item->ctrl); if (err) { @@ -442,13 +436,21 @@ return 0; } - err = nvme_identify_ns_descs(fd, item->nsid, &item->nsdesc); + if (posix_memalign(&nsdescs, getpagesize(), 0x1000)) { + fprintf(stderr, "Cannot allocate controller list payload\n"); + return 0; + } + + err = nvme_identify_ns_descs(fd, item->nsid, nsdescs); if (err) { fprintf(stderr, "Unable to identify namespace descriptor for %s (%s)\n", dev, strerror(err)); return 0; } + memcpy(item->uuid, nsdescs + sizeof(struct nvme_ns_id_desc), sizeof(item->uuid)); + free(nsdescs); + err = nvme_get_ontap_c2_log(fd, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE); if (err) { fprintf(stderr, "Unable to get log page data for %s (%s)\n", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/plugins/wdc/wdc-nvme.c new/nvme-cli-2.0~4/plugins/wdc/wdc-nvme.c --- old/nvme-cli-2.0~3/plugins/wdc/wdc-nvme.c 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/plugins/wdc/wdc-nvme.c 2022-02-22 18:25:01.000000000 +0100 @@ -167,6 +167,7 @@ #define WDC_CUSTOMER_ID_0x1004 0x1004 #define WDC_CUSTOMER_ID_0x1008 0x1008 #define WDC_CUSTOMER_ID_0x1304 0x1304 +#define WDC_INVALID_CUSTOMER_ID -1 #define WDC_ALL_PAGE_MASK 0xFFFF #define WDC_C0_PAGE_MASK 0x0001 @@ -667,6 +668,7 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out); static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, FILE *out, int data_id, int cdw14, int cdw15); static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **cbs_data); +static __u32 wdc_get_fw_cust_id(nvme_root_t r, int fd); /* Drive log data size */ struct wdc_log_size { @@ -1209,8 +1211,7 @@ int ret; uint32_t read_device_id = -1, read_vendor_id = -1; __u64 capabilities = 0; - __u8 *data; - __u32 *cust_id; + __u32 cust_id; ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); if (ret < 0) @@ -1285,6 +1286,10 @@ WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID | WDC_DRIVE_CAP_LOG_PAGE_DIR); + /* verify the 0xC3 log page is supported */ + if (wdc_nvme_check_supported_log_page(r, fd, WDC_LATENCY_MON_OPCODE) == true) + capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; + /* verify the 0xCA log page is supported */ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; @@ -1293,15 +1298,14 @@ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; } - cust_id = (__u32*)data; - - if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) || - (*cust_id == WDC_CUSTOMER_ID_0x1005) || (*cust_id == WDC_CUSTOMER_ID_0x1304)) + if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || + (cust_id == WDC_CUSTOMER_ID_0x1005) || (cust_id == WDC_CUSTOMER_ID_0x1304)) capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | WDC_DRIVE_CAP_INFO | WDC_DRIVE_CAP_CLOUD_SSD_VERSION); else @@ -1417,8 +1421,7 @@ int ret; uint32_t read_vendor_id; __u64 capabilities = 0; - __u8 *data; - __u32 *cust_id; + __u32 cust_id; ret = wdc_get_vendor_id(fd, &read_vendor_id); if (ret < 0) @@ -1429,10 +1432,6 @@ capabilities = (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | WDC_DRIVE_CAP_CLEAR_PCIE | WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP); - /* verify the 0xC3 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_LATENCY_MON_OPCODE) == true) - capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; - /* verify the 0xCA log page is supported */ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; @@ -1462,15 +1461,14 @@ if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; } - cust_id = (__u32*)data; - - if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) || - (*cust_id == WDC_CUSTOMER_ID_0x1005) || (*cust_id == WDC_CUSTOMER_ID_0x1304)) + if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || + (cust_id == WDC_CUSTOMER_ID_0x1005) || (cust_id == WDC_CUSTOMER_ID_0x1304)) capabilities |= (WDC_DRIVE_CAP_VU_FID_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE); else capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_CLEAR_PCIE); @@ -1750,10 +1748,14 @@ length = sizeof(struct wdc_c2_log_page_header); hdr_ptr = (struct wdc_c2_log_page_header *)data; sph = (struct wdc_c2_log_subpage_header *)(data + length); - found = wdc_get_dev_mng_log_entry(hdr_ptr->length, log_id, hdr_ptr, &sph); - + found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph); if (found) { - *cbs_data = (void *)&sph->data; + *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8)); + if (*cbs_data == NULL) { + fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); + goto end; + } + memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length)); } else { /* not found with uuid = 1 try with uuid = 0 */ uuid_ix = 0; @@ -1779,9 +1781,15 @@ hdr_ptr = (struct wdc_c2_log_page_header *)data; sph = (struct wdc_c2_log_subpage_header *)(data + length); - found = wdc_get_dev_mng_log_entry(hdr_ptr->length, log_id, hdr_ptr, &sph); + found = wdc_get_dev_mng_log_entry(le32_to_cpu(hdr_ptr->length), log_id, hdr_ptr, &sph); if (found) { - *cbs_data = (void *)&sph->data; + *cbs_data = calloc(le32_to_cpu(sph->length), sizeof(__u8)); + if (*cbs_data == NULL) { + fprintf(stderr, "ERROR : WDC : calloc : %s\n", strerror(errno)); + goto end; + } + memcpy((void *)*cbs_data, (void *)&sph->data, le32_to_cpu(sph->length)); + } else { /* WD version not found */ fprintf(stderr, "ERROR : WDC : Unable to find correct version of page 0x%x, entry id = %d\n", lid, log_id); @@ -1815,6 +1823,7 @@ d((__u8 *)cbs_data->data, le32_to_cpu(cbs_data->length), 16, 1); } #endif + free(cbs_data); } else fprintf(stderr, "ERROR : WDC : cbs_data ptr = NULL\n"); } else @@ -1831,6 +1840,8 @@ if (get_dev_mgment_cbs_data(r, fd, log_id, (void *)&cbs_data)) { if (cbs_data != NULL) { memcpy((void *)ret_data, (void *)cbs_data, 4); + free(cbs_data); + return true; } } @@ -2944,7 +2955,7 @@ char *data_area = "Data area to retrieve up to. Currently only supported on the SN340, SN640, SN730, and SN840 devices."; char *file_size = "Output file size. Currently only supported on the SN340 device."; char *offset = "Output file data offset. Currently only supported on the SN340 device."; - char *type = "Telemetry type - NONE, HOST, or CONTROLLER. Currently only supported on the SN640 and SN840 devices."; + char *type = "Telemetry type - NONE, HOST, or CONTROLLER. Currently only supported on the SN530, SN640, SN730, SN740, SN810, SN840 and ZN350 devices."; char *verbose = "Display more debug messages."; char f[PATH_MAX] = {0}; char fileSuffix[PATH_MAX] = {0}; @@ -4969,7 +4980,7 @@ int fmt = -1; int i = 0; __u8 *data; - __u32 *cust_id; + __u32 cust_id; uint32_t device_id, read_vendor_id; if (!wdc_check_device(r, fd)) @@ -4996,14 +5007,13 @@ case WDC_NVME_SN650_DEV_ID_3: case WDC_NVME_SN650_DEV_ID_4: case WDC_NVME_SN655_DEV_ID: - if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&data)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; } - cust_id = (__u32*)data; - - if ((*cust_id == WDC_CUSTOMER_ID_0x1004) || (*cust_id == WDC_CUSTOMER_ID_0x1008) || (*cust_id == WDC_CUSTOMER_ID_0x1005)) + if ((cust_id == WDC_CUSTOMER_ID_0x1004) || (cust_id == WDC_CUSTOMER_ID_0x1008) || (cust_id == WDC_CUSTOMER_ID_0x1005)) { if (uuid_index == 0) { @@ -5276,7 +5286,6 @@ __u8 *data; struct wdc_ssd_ca_perf_stats *perf; uint32_t read_device_id, read_vendor_id; - __u32 *cust_id_ptr; __u32 cust_id; if (!wdc_check_device(r, fd)) @@ -5293,13 +5302,13 @@ return -1; } - if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id_ptr)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + /* get the FW customer id */ + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; } - cust_id = *cust_id_ptr; - ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); switch (read_device_id) { @@ -6065,12 +6074,28 @@ return ret; } +static __u32 wdc_get_fw_cust_id(nvme_root_t r, int fd) +{ + + __u32 cust_id = WDC_INVALID_CUSTOMER_ID; + __u32 *cust_id_ptr = NULL; + + if (!(get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id_ptr))) { + fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + } else { + cust_id = *cust_id_ptr; + } + + free(cust_id_ptr); + return cust_id; +} + static int wdc_get_fw_act_history_C2(nvme_root_t r, int fd, char *format) { int ret = 0; int fmt = -1; __u8 *data; - __u32 *cust_id; + __u32 cust_id; struct wdc_fw_act_history_log_format_c2 *fw_act_history_log; __u32 tot_entries = 0, num_entries = 0; __u32 vendor_id = 0, device_id = 0; @@ -6106,14 +6131,15 @@ if (tot_entries > 0) { /* get the FW customer id */ - if (!get_dev_mgment_cbs_data(r, fd, WDC_C2_CUSTOMER_ID_ID, (void*)&cust_id)) { - fprintf(stderr, "%s: ERROR : WDC : 0xC2 Log Page entry ID 0x%x not found\n", __func__, WDC_C2_CUSTOMER_ID_ID); + cust_id = wdc_get_fw_cust_id(r, fd); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); ret = -1; goto freeData; } num_entries = (tot_entries < WDC_MAX_NUM_ACT_HIST_ENTRIES) ? tot_entries : WDC_MAX_NUM_ACT_HIST_ENTRIES; - ret = wdc_print_fw_act_history_log(data, num_entries, fmt, *cust_id, vendor_id); + ret = wdc_print_fw_act_history_log(data, num_entries, fmt, cust_id, vendor_id); } else { fprintf(stderr, "INFO : WDC : No FW Activate History entries found.\n"); ret = 0; @@ -7500,6 +7526,8 @@ json_free_object(root); } else fprintf(stderr, "%s: ERROR : WDC : Invalid format, format = %s\n", __func__, cfg.output_format); + + free(cbs_data); } else fprintf(stderr, "%s: ERROR : WDC : NULL_data ptr\n", __func__); } else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/subprojects/libnvme.wrap new/nvme-cli-2.0~4/subprojects/libnvme.wrap --- old/nvme-cli-2.0~3/subprojects/libnvme.wrap 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/subprojects/libnvme.wrap 2022-02-22 18:25:01.000000000 +0100 @@ -1,6 +1,6 @@ [wrap-git] url = https://github.com/linux-nvme/libnvme.git -revision = c434d43faee6e6e93ac5ad603ef94a77299fa178 +revision = 3a1bc6c6226d240b544058065382e2546018caa8 [provide] libnvme = libnvme_dep diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvme-cli-2.0~3/util/parser.c new/nvme-cli-2.0~4/util/parser.c --- old/nvme-cli-2.0~3/util/parser.c 2022-02-11 14:02:53.000000000 +0100 +++ new/nvme-cli-2.0~4/util/parser.c 2022-02-22 18:25:01.000000000 +0100 @@ -16,9 +16,9 @@ /** * match_one: - Determines if a string matches a simple pattern - * @s: the string to examine for presence of the pattern - * @p: the string containing the pattern - * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match + * @s: the string to examine for presence of the pattern + * @p: the string containing the pattern + * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match * locations. * * Description: Determines if the pattern @p is present in string @s. Can only @@ -94,12 +94,12 @@ /** * match_token: - Find a token (and optional args) in a string - * @s: the string to examine for token/argument pairs - * @table: match_table_t describing the set of allowed option tokens and the - * arguments that may be associated with them. Must be terminated with a - * &struct match_token whose pattern is set to the NULL pointer. - * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match - * locations. + * @s: the string to examine for token/argument pairs + * @table: match_table_t describing the set of allowed option tokens and the + * arguments that may be associated with them. Must be terminated with a + * &struct match_token whose pattern is set to the NULL pointer. + * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match + * locations. * * Description: Detects which if any of a set of token strings has been passed * to it. Tokens can include up to MAX_OPT_ARGS instances of basic c-style @@ -118,9 +118,9 @@ /** * match_number: scan a number in the given base from a substring_t - * @s: substring to be scanned - * @result: resulting integer on success - * @base: base to use when converting string + * @s: substring to be scanned + * @result: resulting integer on success + * @base: base to use when converting string * * Description: Given a &substring_t and a base, attempts to parse the substring * as a number in that base. On success, sets @result to the integer represented @@ -154,8 +154,8 @@ /** * match_int: - scan a decimal representation of an integer from a substring_t - * @s: substring_t to be scanned - * @result: resulting integer on success + * @s: substring_t to be scanned + * @result: resulting integer on success * * Description: Attempts to parse the &substring_t @s as a decimal integer. On * success, sets @result to the integer represented by the string and returns 0. @@ -168,8 +168,8 @@ /** * match_octal: - scan an octal representation of an integer from a substring_t - * @s: substring_t to be scanned - * @result: resulting integer on success + * @s: substring_t to be scanned + * @result: resulting integer on success * * Description: Attempts to parse the &substring_t @s as an octal integer. On * success, sets @result to the integer represented by the string and returns @@ -182,8 +182,8 @@ /** * match_hex: - scan a hex representation of an integer from a substring_t - * @s: substring_t to be scanned - * @result: resulting integer on success + * @s: substring_t to be scanned + * @result: resulting integer on success * * Description: Attempts to parse the &substring_t @s as a hexadecimal integer. * On success, sets @result to the integer represented by the string and @@ -196,8 +196,8 @@ /** * match_wildcard: - parse if a string matches given wildcard pattern - * @pattern: wildcard pattern - * @str: the string to be parsed + * @pattern: wildcard pattern + * @str: the string to be parsed * * Description: Parse the string @str to check if matches wildcard * pattern @pattern. The pattern may contain two type wildcardes: @@ -246,9 +246,9 @@ /** * match_strlcpy: - Copy the characters from a substring_t to a sized buffer - * @dest: where to copy to - * @src: &substring_t to copy - * @size: size of destination buffer + * @dest: where to copy to + * @src: &substring_t to copy + * @size: size of destination buffer * * Description: Copy the characters in &substring_t @src to the * c-style string @dest. Copy no more than @size - 1 characters, plus ++++++ nvme-cli.obsinfo ++++++ --- /var/tmp/diff_new_pack.UC4P9z/_old 2022-02-23 16:26:36.815509181 +0100 +++ /var/tmp/diff_new_pack.UC4P9z/_new 2022-02-23 16:26:36.815509181 +0100 @@ -1,5 +1,5 @@ name: nvme-cli -version: 2.0~3 -mtime: 1644584573 -commit: f02a78a4599b4fbee9ca82fb887f2736c5a67bb8 +version: 2.0~4 +mtime: 1645550701 +commit: 59263bbcd3e4f5eaffe7d200c4cad2a361008e48