From 5bb5100ae1d7a1d074872dfd6a4735a673b5356d Mon Sep 17 00:00:00 2001 From: Xiaoyuan Zhang Date: Tue, 6 Aug 2024 15:37:09 +0800 Subject: [PATCH] plugins: Add a new DapuStor plugin and the smart-log-add command 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 --- plugins/dapustor/dapustor-nvme.c | 547 +++++++++++++++++++++++++++++++ plugins/dapustor/dapustor-nvme.h | 18 + plugins/meson.build | 1 + 3 files changed, 566 insertions(+) create mode 100644 plugins/dapustor/dapustor-nvme.c create mode 100644 plugins/dapustor/dapustor-nvme.h diff --git a/plugins/dapustor/dapustor-nvme.c b/plugins/dapustor/dapustor-nvme.c new file mode 100644 index 00000000..57c59dc6 --- /dev/null +++ b/plugins/dapustor/dapustor-nvme.c @@ -0,0 +1,547 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 index 00000000..9d0d332d --- /dev/null +++ b/plugins/dapustor/dapustor-nvme.h @@ -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" diff --git a/plugins/meson.build b/plugins/meson.build index 146fa2a0..e82c94d5 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -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', -- 2.50.1