]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
plugins: Add a new DapuStor plugin and the smart-log-add command
authorXiaoyuan Zhang <zhxiaoy2024@gmail.com>
Tue, 6 Aug 2024 07:37:09 +0000 (15:37 +0800)
committerDaniel Wagner <wagi@monom.org>
Tue, 6 Aug 2024 09:56:34 +0000 (11:56 +0200)
Add the DapuStor plugin to support the retrieval and
display of the Vendor Specific SMART logs:
Additional SMART log page (0xCA)
Extended Additional SMART log page (0xCB)

Signed-off-by: Xiaoyuan Zhang <zhxiaoy2024@gmail.com>
plugins/dapustor/dapustor-nvme.c [new file with mode: 0644]
plugins/dapustor/dapustor-nvme.h [new file with mode: 0644]
plugins/meson.build

diff --git a/plugins/dapustor/dapustor-nvme.c b/plugins/dapustor/dapustor-nvme.c
new file mode 100644 (file)
index 0000000..57c59dc
--- /dev/null
@@ -0,0 +1,547 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include <sys/stat.h>
+
+#include "common.h"
+#include "nvme.h"
+#include "libnvme.h"
+#include "plugin.h"
+#include "nvme-print.h"
+
+#include "util/suffix.h"
+
+#define CREATE_CMD
+#include "dapustor-nvme.h"
+
+struct __packed nvme_additional_smart_log_item {
+       __u8                    key;
+       __u8                    _kp[2];
+       __u8                    norm;
+       __u8                    _np;
+       union __packed {
+               __u8            raw[6];
+               struct __packed  wear_level {
+                       __le16  min;
+                       __le16  max;
+                       __le16  avg;
+               } wear_level;
+               struct __packed thermal_throttle {
+                       __u8    pct;
+                       __u32   count;
+               } thermal_throttle;
+               struct __packed  temperature {
+                       __le16  max;
+                       __le16  min;
+                       __le16  cur;
+               } temperature;
+               struct __packed  power_consumption {
+                       __le16  max;
+                       __le16  min;
+                       __le16  avg;
+               } power_consumption;
+               struct __packed  thermal_throttle_time {
+                       __u8    sts;
+                       __u32   time;
+                       __u8    rsv;
+               } thermal_throttle_time;
+       };
+       __u8                    _rp;
+};
+
+struct nvme_additional_smart_log {
+       struct nvme_additional_smart_log_item   program_fail_cnt;
+       struct nvme_additional_smart_log_item   erase_fail_cnt;
+       struct nvme_additional_smart_log_item   wear_leveling_cnt;
+       struct nvme_additional_smart_log_item   e2e_err_cnt;
+       struct nvme_additional_smart_log_item   crc_err_cnt;
+       struct nvme_additional_smart_log_item   timed_workload_media_wear;
+       struct nvme_additional_smart_log_item   timed_workload_host_reads;
+       struct nvme_additional_smart_log_item   timed_workload_timer;
+       struct nvme_additional_smart_log_item   thermal_throttle_status;
+       struct nvme_additional_smart_log_item   retry_buffer_overflow_cnt;
+       struct nvme_additional_smart_log_item   pll_lock_loss_cnt;
+       struct nvme_additional_smart_log_item   nand_bytes_written;
+       struct nvme_additional_smart_log_item   host_bytes_written;
+};
+
+struct nvme_extended_additional_smart_log {
+       struct nvme_additional_smart_log_item   sys_area_life_remain;
+       struct nvme_additional_smart_log_item   nand_bytes_read;
+       struct nvme_additional_smart_log_item   temperature;
+       struct nvme_additional_smart_log_item   power_consumption;
+       struct nvme_additional_smart_log_item   power_on_temperature;
+       struct nvme_additional_smart_log_item   power_loss_protection;
+       struct nvme_additional_smart_log_item   read_fail_count;
+       struct nvme_additional_smart_log_item   thermal_throttle_time;
+       struct nvme_additional_smart_log_item   flash_error_media_count;
+       struct nvme_additional_smart_log_item   lifetime_write_amplification;
+       struct nvme_additional_smart_log_item   firmware_update_count;
+       struct nvme_additional_smart_log_item   dram_cecc_count;
+       struct nvme_additional_smart_log_item   dram_uecc_count;
+       struct nvme_additional_smart_log_item   xor_pass_count;
+       struct nvme_additional_smart_log_item   xor_fail_count;
+       struct nvme_additional_smart_log_item   xor_invoked_count;
+       struct nvme_additional_smart_log_item   inflight_read_io_cmd;
+       struct nvme_additional_smart_log_item   temp_since_born;
+       struct nvme_additional_smart_log_item   temp_since_bootup;
+       struct nvme_additional_smart_log_item   inflight_write_io_cmd;
+};
+
+static void show_dapustor_add_smart_log_jsn(struct nvme_additional_smart_log *smart,
+                                           struct json_object *dev_stats)
+{
+       struct json_object *entry_stats, *multi;
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->program_fail_cnt.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->program_fail_cnt.raw));
+       json_object_add_value_object(dev_stats, "program_fail_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->erase_fail_cnt.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->erase_fail_cnt.raw));
+       json_object_add_value_object(dev_stats, "erase_fail_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->wear_leveling_cnt.norm);
+       multi = json_create_object();
+       json_object_add_value_int(multi, "min",
+                                 le16_to_cpu(smart->wear_leveling_cnt.wear_level.min));
+       json_object_add_value_int(multi, "max",
+                                 le16_to_cpu(smart->wear_leveling_cnt.wear_level.max));
+       json_object_add_value_int(multi, "avg",
+                                 le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg));
+       json_object_add_value_object(entry_stats, "raw", multi);
+       json_object_add_value_object(dev_stats, "wear_leveling", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->e2e_err_cnt.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->e2e_err_cnt.raw));
+       json_object_add_value_object(dev_stats, "end_to_end_error_detection_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->crc_err_cnt.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->crc_err_cnt.raw));
+       json_object_add_value_object(dev_stats, "crc_error_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_media_wear.norm);
+       json_object_add_value_float(entry_stats, "raw",
+               ((long double)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024);
+       json_object_add_value_object(dev_stats, "timed_workload_media_wear", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_host_reads.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->timed_workload_host_reads.raw));
+       json_object_add_value_object(dev_stats, "timed_workload_host_reads", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_timer.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->timed_workload_timer.raw));
+       json_object_add_value_object(dev_stats, "timed_workload_timer", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->thermal_throttle_status.norm);
+       multi = json_create_object();
+       json_object_add_value_int(multi, "pct",
+                                 smart->thermal_throttle_status.thermal_throttle.pct);
+       json_object_add_value_int(multi, "cnt",
+                                 smart->thermal_throttle_status.thermal_throttle.count);
+       json_object_add_value_object(entry_stats, "raw", multi);
+       json_object_add_value_object(dev_stats, "thermal_throttle_status", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->retry_buffer_overflow_cnt.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->retry_buffer_overflow_cnt.raw));
+       json_object_add_value_object(dev_stats, "retry_buffer_overflow_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->pll_lock_loss_cnt.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->pll_lock_loss_cnt.raw));
+       json_object_add_value_object(dev_stats, "pll_lock_loss_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->nand_bytes_written.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->nand_bytes_written.raw));
+       json_object_add_value_object(dev_stats, "nand_bytes_written", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->host_bytes_written.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->host_bytes_written.raw));
+       json_object_add_value_object(dev_stats, "host_bytes_written", entry_stats);
+}
+
+static void show_dapustor_ext_add_smart_log_jsn(struct nvme_extended_additional_smart_log *smart,
+                                               struct json_object *dev_stats)
+{
+       struct json_object *entry_stats, *multi;
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->sys_area_life_remain.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->sys_area_life_remain.raw));
+       json_object_add_value_object(dev_stats, "system_area_life_remaining", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->nand_bytes_read.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->nand_bytes_read.raw));
+       json_object_add_value_object(dev_stats, "nand_bytes_read", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->temperature.norm);
+       multi = json_create_object();
+       json_object_add_value_int(multi, "min", le16_to_cpu(smart->temperature.temperature.min));
+       json_object_add_value_int(multi, "max", le16_to_cpu(smart->temperature.temperature.max));
+       json_object_add_value_int(multi, "cur", le16_to_cpu(smart->temperature.temperature.cur));
+       json_object_add_value_object(entry_stats, "raw", multi);
+       json_object_add_value_object(dev_stats, "temperature", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->power_consumption.norm);
+       multi = json_create_object();
+       json_object_add_value_int(multi, "min",
+                                 le16_to_cpu(smart->power_consumption.power_consumption.min));
+       json_object_add_value_int(multi, "max",
+                                 le16_to_cpu(smart->power_consumption.power_consumption.max));
+       json_object_add_value_int(multi, "avg",
+                                 le16_to_cpu(smart->power_consumption.power_consumption.avg));
+       json_object_add_value_object(entry_stats, "raw", multi);
+       json_object_add_value_object(dev_stats, "power_consumption", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->power_on_temperature.norm);
+       multi = json_create_object();
+       json_object_add_value_int(multi, "min",
+                                 le16_to_cpu(smart->power_on_temperature.temperature.min));
+       json_object_add_value_int(multi, "max",
+                                 le16_to_cpu(smart->power_on_temperature.temperature.max));
+       json_object_add_value_int(multi, "cur",
+                                 le16_to_cpu(smart->power_on_temperature.temperature.cur));
+       json_object_add_value_object(entry_stats, "raw", multi);
+       json_object_add_value_object(dev_stats, "power_on_temperature", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->power_loss_protection.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->power_loss_protection.raw));
+       json_object_add_value_object(dev_stats, "power_loss_protection", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->read_fail_count.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->read_fail_count.raw));
+       json_object_add_value_object(dev_stats, "read_fail_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->thermal_throttle_time.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->thermal_throttle_time.raw));
+       json_object_add_value_object(dev_stats, "thermal_throttle_time", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->flash_error_media_count.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->flash_error_media_count.raw));
+       json_object_add_value_object(dev_stats, "flash_error_media_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized",
+                                 smart->lifetime_write_amplification.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->lifetime_write_amplification.raw));
+       json_object_add_value_object(dev_stats, "lifetime_write_amplification", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->firmware_update_count.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->firmware_update_count.raw));
+       json_object_add_value_object(dev_stats, "firmware_update_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->dram_cecc_count.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->dram_cecc_count.raw));
+       json_object_add_value_object(dev_stats, "dram_cecc_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->dram_uecc_count.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->dram_uecc_count.raw));
+       json_object_add_value_object(dev_stats, "dram_uecc_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->xor_pass_count.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->xor_pass_count.raw));
+       json_object_add_value_object(dev_stats, "xor_pass_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->xor_fail_count.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->xor_fail_count.raw));
+       json_object_add_value_object(dev_stats, "xor_fail_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->xor_invoked_count.norm);
+       json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->xor_invoked_count.raw));
+       json_object_add_value_object(dev_stats, "xor_invoked_count", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->inflight_read_io_cmd.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->inflight_read_io_cmd.raw));
+       json_object_add_value_object(dev_stats, "inflight_read_io_cmd", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->temp_since_born.norm);
+       multi = json_create_object();
+       json_object_add_value_int(multi, "min",
+                                 le16_to_cpu(smart->temp_since_born.temperature.min));
+       json_object_add_value_int(multi, "max",
+                                 le16_to_cpu(smart->temp_since_born.temperature.max));
+       json_object_add_value_int(multi, "cur",
+                                 le16_to_cpu(smart->temp_since_born.temperature.cur));
+       json_object_add_value_object(entry_stats, "raw", multi);
+       json_object_add_value_object(dev_stats, "temp_since_born", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->temp_since_born.norm);
+       multi = json_create_object();
+       json_object_add_value_int(multi, "min",
+                                 le16_to_cpu(smart->temp_since_born.temperature.min));
+       json_object_add_value_int(multi, "max",
+                                 le16_to_cpu(smart->temp_since_born.temperature.max));
+       json_object_add_value_int(multi, "cur",
+                                 le16_to_cpu(smart->temp_since_born.temperature.cur));
+       json_object_add_value_object(entry_stats, "raw", multi);
+       json_object_add_value_object(dev_stats, "temp_since_born", entry_stats);
+
+       entry_stats = json_create_object();
+       json_object_add_value_int(entry_stats, "normalized", smart->inflight_write_io_cmd.norm);
+       json_object_add_value_int(entry_stats, "raw",
+                                 int48_to_long(smart->inflight_write_io_cmd.raw));
+       json_object_add_value_object(dev_stats, "inflight_write_io_cmd", entry_stats);
+}
+
+static void show_dapustor_smart_log_jsn(struct nvme_additional_smart_log *smart,
+                                       struct nvme_extended_additional_smart_log *ext_smart,
+                                       unsigned int nsid, const char *devname)
+{
+       struct json_object *root, *dev_stats;
+
+       root = json_create_object();
+       json_object_add_value_string(root, "Intel Smart log", devname);
+
+       dev_stats = json_create_object();
+       show_dapustor_add_smart_log_jsn(smart, dev_stats);
+       show_dapustor_ext_add_smart_log_jsn(ext_smart, dev_stats);
+       json_object_add_value_object(root, "Device stats", dev_stats);
+
+       json_print_object(root, NULL);
+       json_free_object(root);
+}
+
+static void show_dapustor_add_smart_log(struct nvme_additional_smart_log *smart)
+{
+       printf("program_fail_count              : %3d%%       %"PRIu64"\n",
+               smart->program_fail_cnt.norm,
+               int48_to_long(smart->program_fail_cnt.raw));
+       printf("erase_fail_count                : %3d%%       %"PRIu64"\n",
+               smart->erase_fail_cnt.norm,
+               int48_to_long(smart->erase_fail_cnt.raw));
+       printf("wear_leveling                   : %3d%%       min: %u, max: %u, avg: %u\n",
+               smart->wear_leveling_cnt.norm,
+               le16_to_cpu(smart->wear_leveling_cnt.wear_level.min),
+               le16_to_cpu(smart->wear_leveling_cnt.wear_level.max),
+               le16_to_cpu(smart->wear_leveling_cnt.wear_level.avg));
+       printf("end_to_end_error_detection_count: %3d%%       %"PRIu64"\n",
+               smart->e2e_err_cnt.norm,
+               int48_to_long(smart->e2e_err_cnt.raw));
+       printf("crc_error_count                 : %3d%%       %"PRIu64"\n",
+               smart->crc_err_cnt.norm,
+               int48_to_long(smart->crc_err_cnt.raw));
+       printf("timed_workload_media_wear       : %3d%%       %.3f%%\n",
+               smart->timed_workload_media_wear.norm,
+               ((float)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024);
+       printf("timed_workload_host_reads       : %3d%%       %"PRIu64"%%\n",
+               smart->timed_workload_host_reads.norm,
+               int48_to_long(smart->timed_workload_host_reads.raw));
+       printf("timed_workload_timer            : %3d%%       %"PRIu64" min\n",
+               smart->timed_workload_timer.norm,
+               int48_to_long(smart->timed_workload_timer.raw));
+       printf("thermal_throttle_status         : %3d%%       %u%%, cnt: %u\n",
+               smart->thermal_throttle_status.norm,
+               smart->thermal_throttle_status.thermal_throttle.pct,
+               smart->thermal_throttle_status.thermal_throttle.count);
+       printf("retry_buffer_overflow_count     : %3d%%       %"PRIu64"\n",
+               smart->retry_buffer_overflow_cnt.norm,
+               int48_to_long(smart->retry_buffer_overflow_cnt.raw));
+       printf("pll_lock_loss_count             : %3d%%       %"PRIu64"\n",
+               smart->pll_lock_loss_cnt.norm,
+               int48_to_long(smart->pll_lock_loss_cnt.raw));
+       printf("nand_bytes_written              : %3d%%       sectors: %"PRIu64"\n",
+               smart->nand_bytes_written.norm,
+               int48_to_long(smart->nand_bytes_written.raw));
+       printf("host_bytes_written              : %3d%%       sectors: %"PRIu64"\n",
+               smart->host_bytes_written.norm,
+               int48_to_long(smart->host_bytes_written.raw));
+}
+
+static void show_dapustor_ext_add_smart_log(struct nvme_extended_additional_smart_log *smart)
+{
+       printf("system_area_life_remaining      : %3d%%       %"PRIu64"\n",
+               smart->sys_area_life_remain.norm,
+               int48_to_long(smart->sys_area_life_remain.raw));
+       printf("nand_bytes_read                 : %3d%%       %"PRIu64"\n",
+               smart->nand_bytes_read.norm,
+               int48_to_long(smart->nand_bytes_read.raw));
+       printf("temperature                     : %3d%%       min: %u, max: %u, cur: %u\n",
+               smart->temperature.norm,
+               le16_to_cpu(smart->temperature.temperature.min),
+               le16_to_cpu(smart->temperature.temperature.max),
+               le16_to_cpu(smart->temperature.temperature.cur));
+       printf("power_consumption               : %3d%%       min: %u, max: %u, avg: %u\n",
+               smart->power_consumption.norm,
+               le16_to_cpu(smart->power_consumption.power_consumption.min),
+               le16_to_cpu(smart->power_consumption.power_consumption.max),
+               le16_to_cpu(smart->power_consumption.power_consumption.avg));
+       printf("power_on_temperature            : %3d%%       min: %u, max: %u, cur: %u\n",
+               smart->power_on_temperature.norm,
+               le16_to_cpu(smart->power_on_temperature.temperature.min),
+               le16_to_cpu(smart->power_on_temperature.temperature.max),
+               le16_to_cpu(smart->power_on_temperature.temperature.cur));
+       printf("power_loss_protection           : %3d%%       %"PRIu64"\n",
+               smart->power_loss_protection.norm,
+               int48_to_long(smart->power_loss_protection.raw));
+       printf("read_fail_count                 : %3d%%       %"PRIu64"\n",
+               smart->read_fail_count.norm,
+               int48_to_long(smart->read_fail_count.raw));
+       printf("thermal_throttle_time           : %3d%%       %"PRIu64"\n",
+               smart->thermal_throttle_time.norm,
+               int48_to_long(smart->thermal_throttle_time.raw));
+       printf("flash_error_media_count         : %3d%%       %"PRIu64"\n",
+               smart->flash_error_media_count.norm,
+               int48_to_long(smart->flash_error_media_count.raw));
+       printf("lifetime_write_amplification    : %3d%%       %"PRIu64"\n",
+               smart->lifetime_write_amplification.norm,
+               int48_to_long(smart->lifetime_write_amplification.raw));
+       printf("firmware_update_count           : %3d%%       %"PRIu64"\n",
+               smart->firmware_update_count.norm,
+               int48_to_long(smart->firmware_update_count.raw));
+       printf("dram_cecc_count                 : %3d%%       %"PRIu64"\n",
+               smart->dram_cecc_count.norm,
+               int48_to_long(smart->dram_cecc_count.raw));
+       printf("dram_uecc_count                 : %3d%%       %"PRIu64"\n",
+               smart->dram_uecc_count.norm,
+               int48_to_long(smart->dram_uecc_count.raw));
+       printf("xor_pass_count                  : %3d%%       %"PRIu64"\n",
+               smart->xor_pass_count.norm,
+               int48_to_long(smart->xor_pass_count.raw));
+       printf("xor_fail_count                  : %3d%%       %"PRIu64"\n",
+               smart->xor_fail_count.norm,
+               int48_to_long(smart->xor_fail_count.raw));
+       printf("xor_invoked_count               : %3d%%       %"PRIu64"\n",
+               smart->xor_invoked_count.norm,
+               int48_to_long(smart->xor_invoked_count.raw));
+       printf("inflight_read_io_cmd            : %3d%%       %"PRIu64"\n",
+               smart->inflight_read_io_cmd.norm,
+               int48_to_long(smart->inflight_read_io_cmd.raw));
+       printf("temp_since_born                 : %3d%%       min: %u, max: %u, cur: %u\n",
+               smart->temp_since_born.norm,
+               le16_to_cpu(smart->temp_since_born.temperature.min),
+               le16_to_cpu(smart->temp_since_born.temperature.max),
+               le16_to_cpu(smart->temp_since_born.temperature.cur));
+       printf("temp_since_bootup               : %3d%%       min: %u, max: %u, cur: %u\n",
+               smart->temp_since_bootup.norm,
+               le16_to_cpu(smart->temp_since_bootup.temperature.min),
+               le16_to_cpu(smart->temp_since_bootup.temperature.max),
+               le16_to_cpu(smart->temp_since_bootup.temperature.cur));
+       printf("inflight_write_io_cmd           : %3d%%       %"PRIu64"\n",
+               smart->inflight_write_io_cmd.norm,
+               int48_to_long(smart->inflight_write_io_cmd.raw));
+}
+
+static void show_dapustor_smart_log(struct nvme_additional_smart_log *smart,
+                                   struct nvme_extended_additional_smart_log *ext_smart,
+                                   unsigned int nsid, const char *devname)
+{
+       printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
+               devname, nsid);
+       printf("key                               normalized raw\n");
+       show_dapustor_add_smart_log(smart);
+       show_dapustor_ext_add_smart_log(ext_smart);
+}
+
+static int dapustor_additional_smart_log_data(
+               int dev_fd,
+               struct nvme_additional_smart_log *smart_log,
+               struct nvme_extended_additional_smart_log *ext_smart_log)
+{
+       int err;
+
+       err = nvme_get_log_simple(dev_fd, 0xca, sizeof(*smart_log), smart_log);
+       if (err) {
+               nvme_show_status(err);
+               return err;
+       }
+       err = nvme_get_log_simple(dev_fd, 0xcb, sizeof(*ext_smart_log), ext_smart_log);
+       if (err)
+               nvme_show_status(err);
+       return err;
+}
+
+static int dapustor_additional_smart_log(int argc, char **argv, struct command *cmd,
+                                        struct plugin *plugin)
+{
+       const char *desc = "Get DapuStor vendor specific additional smart log, and show it.";
+       const char *namespace = "(optional) desired namespace";
+       const char *raw = "Dump output in binary format";
+       const char *json = "Dump output in json format";
+
+       struct nvme_additional_smart_log smart_log;
+       struct nvme_extended_additional_smart_log ext_smart_log;
+       struct nvme_dev *dev;
+       int err;
+
+       struct config {
+               uint32_t namespace_id;
+               bool  raw_binary;
+               bool  json;
+       };
+
+       struct config cfg = {
+               .namespace_id = NVME_NSID_ALL,
+       };
+
+       OPT_ARGS(opts) = {
+               OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
+               OPT_FLAG("raw-binary",   'b', &cfg.raw_binary,   raw),
+               OPT_FLAG("json",         'j', &cfg.json,         json),
+               OPT_END()
+       };
+
+       err = parse_and_open(&dev, argc, argv, desc, opts);
+       if (err)
+               return err;
+
+       err = dapustor_additional_smart_log_data(dev_fd(dev), &smart_log, &ext_smart_log);
+       if (!err) {
+               if (cfg.json)
+                       show_dapustor_smart_log_jsn(&smart_log, &ext_smart_log,
+                                                   cfg.namespace_id, dev->name);
+               else if (!cfg.raw_binary)
+                       show_dapustor_smart_log(&smart_log, &ext_smart_log,
+                                               cfg.namespace_id, dev->name);
+               else
+                       d_raw((unsigned char *)&smart_log, sizeof(smart_log));
+       }
+       dev_close(dev);
+       return err;
+}
diff --git a/plugins/dapustor/dapustor-nvme.h b/plugins/dapustor/dapustor-nvme.h
new file mode 100644 (file)
index 0000000..9d0d332
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#undef CMD_INC_FILE
+#define CMD_INC_FILE plugins/dapustor/dapustor-nvme
+
+#if !defined(DAPUSTOR_NVME) || defined(CMD_HEADER_MULTI_READ)
+#define DAPUSTOR_NVME
+
+#include "cmd.h"
+
+PLUGIN(NAME("dapustor", "DapuStor vendor specific extensions", NVME_VERSION),
+       COMMAND_LIST(
+               ENTRY("smart-log-add", "Retrieve DapuStor SMART Log, show it", dapustor_additional_smart_log)
+       )
+);
+
+#endif
+
+#include "define_cmd.h"
index 146fa2a0ad35a40e40af389a0af09baa8658e90e..e82c94d5edbd301a062863bdd7a9699a98a6c2ca 100644 (file)
@@ -3,6 +3,7 @@
 if json_c_dep.found()
   sources += [
     'plugins/amzn/amzn-nvme.c',
+    'plugins/dapustor/dapustor-nvme.c',
     'plugins/dell/dell-nvme.c',
     'plugins/dera/dera-nvme.c',
     'plugins/fdp/fdp.c',