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
 

Reply via email to