]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
wdc: add vs-device-waf command
authorJeff Lien <jeff.lien@wdc.com>
Tue, 3 May 2022 20:59:28 +0000 (15:59 -0500)
committerJeff Lien <jeff.lien@wdc.com>
Wed, 11 May 2022 21:36:23 +0000 (16:36 -0500)
Signed-off-by: Jeff Lien <jeff.lien@wdc.com>
plugins/wdc/wdc-nvme.c
plugins/wdc/wdc-nvme.h

index f6654a052271926131b127d7115de1097a88d9c7..db7f9fe3af41fa05d929803b1f5cee6cea2ccf9c 100644 (file)
 #define WDC_DRIVE_CAP_OCP_C1_LOG_PAGE          0x0000002000000000
 #define WDC_DRIVE_CAP_OCP_C4_LOG_PAGE          0x0000004000000000
 #define WDC_DRIVE_CAP_OCP_C5_LOG_PAGE          0x0000008000000000
+#define WDC_DRIVE_CAP_DEVICE_WAF            0x0000010000000000
 #define WDC_DRIVE_CAP_SMART_LOG_MASK   (WDC_DRIVE_CAP_C0_LOG_PAGE | WDC_DRIVE_CAP_C1_LOG_PAGE | \
                                          WDC_DRIVE_CAP_CA_LOG_PAGE | WDC_DRIVE_CAP_D0_LOG_PAGE)
 #define WDC_DRIVE_CAP_CLEAR_PCIE_MASK       (WDC_DRIVE_CAP_CLEAR_PCIE | \
@@ -1584,7 +1585,8 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) {
                        capabilities = WDC_DRIVE_CAP_DUI_DATA | WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION |
                                WDC_DRIVE_CAP_CLOUD_LOG_PAGE | WDC_DRIVE_CAP_C0_LOG_PAGE |
                                WDC_DRIVE_CAP_HW_REV_LOG_PAGE | WDC_DRIVE_CAP_INFO |
-                               WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | WDC_DRIVE_CAP_NAND_STATS;
+                               WDC_DRIVE_CAP_VU_FID_CLEAR_PCIE | WDC_DRIVE_CAP_NAND_STATS |
+                                       WDC_DRIVE_CAP_DEVICE_WAF;
                        break;
                case WDC_NVME_SN720_DEV_ID:
                        capabilities = WDC_DRIVE_CAP_DUI_DATA | WDC_DRIVE_CAP_NAND_STATS | WDC_DRIVE_CAP_NS_RESIZE;
@@ -7278,6 +7280,128 @@ out:
        return ret;
 }
 
+static int wdc_vs_device_waf(int argc, char **argv, struct command *command,
+               struct plugin *plugin)
+{
+       const char *desc = "Retrieve Device Write Amplication Factor";
+       const char *namespace_id = "desired namespace id";
+       struct nvme_smart_log smart_log;
+       __u8 *data;
+       int fd;
+       nvme_root_t r;
+       int ret = 0;
+       int fmt = -1;
+       __u64 capabilities = 0;
+       long double  data_units_written = 0,
+                       phys_media_units_written_tlc = 0,
+                       phys_media_units_written_slc = 0;
+       struct json_object *root = NULL;
+       char tlc_waf_str[32] = { 0 },
+                       slc_waf_str[32] = { 0 };
+
+       struct config {
+               char *output_format;
+               __u32 namespace_id;
+       };
+
+       struct config cfg = {
+               .output_format = "normal",
+               .namespace_id = NVME_NSID_ALL,
+       };
+
+       OPT_ARGS(opts) = {
+               OPT_FMT("output-format",      'o', &cfg.output_format,    "Output Format: normal|json"),
+               OPT_UINT("namespace-id",      'n', &cfg.namespace_id,     namespace_id),
+               OPT_END()
+       };
+
+       fd = parse_and_open(argc, argv, desc, opts);
+       if (fd < 0)
+               return fd;
+
+       r = nvme_scan(NULL);
+
+       capabilities = wdc_get_drive_capabilities(r, fd);
+
+       if ((capabilities & WDC_DRIVE_CAP_DEVICE_WAF) == 0) {
+               fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+               ret = -1;
+               goto out;
+       }
+
+       /* get data units written from the smart log page */
+       ret = nvme_get_log_smart(fd, cfg.namespace_id, true, &smart_log);
+       if (!ret) {
+               data_units_written = int128_to_double(smart_log.data_units_written);
+       }
+       else if (ret > 0) {
+               nvme_show_status(ret);
+               ret = -1;
+               goto out;
+       } else {
+               fprintf(stderr, "smart log: %s\n", nvme_strerror(errno));
+               ret = -1;
+               goto out;
+       }
+
+       /* get Physical Media Units Written from C0 log page */
+       data = NULL;
+       ret = nvme_get_smart_cloud_v1_log(fd, &data, 0, cfg.namespace_id);
+
+       if (ret == 0) {
+               phys_media_units_written_tlc = int128_to_double(&data[SCAO_V1_PMUWT]);
+               phys_media_units_written_slc = int128_to_double(&data[SCAO_V1_PMUWS]);
+
+               if (data)
+                       free(data);
+       } else {
+               fprintf(stderr, "ERROR : WDC %s: get smart cloud log failure\n", __func__);
+               ret = -1;
+               goto out;
+       }
+
+       if (strcmp(cfg.output_format, "json"))
+               nvme_show_status(ret);
+
+       fmt = validate_output_format(cfg.output_format);
+       if (fmt < 0) {
+               fprintf(stderr, "ERROR : WDC %s: invalid output format\n", __func__);
+               ret = fmt;
+               goto out;
+       }
+
+       if (data_units_written == 0) {
+               fprintf(stderr, "ERROR : WDC %s: 0 data units written\n", __func__);
+               ret = -1;
+               goto out;
+       }
+
+       if (fmt == NORMAL) {
+               printf("Device Write Amplification Factor TLC : %4.2Lf\n",
+                               (phys_media_units_written_tlc/data_units_written));
+               printf("Device Write Amplification Factor SLC : %4.2Lf\n",
+                               (phys_media_units_written_slc/data_units_written));
+       }
+       else if (fmt == JSON) {
+               root = json_create_object();
+               sprintf(tlc_waf_str, "%4.2Lf", (phys_media_units_written_tlc/data_units_written));
+               sprintf(slc_waf_str, "%4.2Lf", (phys_media_units_written_slc/data_units_written));
+
+               json_object_add_value_string(root, "Device Write Amplification Factor TLC", tlc_waf_str);
+               json_object_add_value_string(root, "Device Write Amplification Factor SLC", slc_waf_str);
+
+               json_print_object(root, NULL);
+               printf("\n");
+
+               json_free_object(root);
+       }
+
+out:
+       nvme_free_tree(r);
+       close(fd);
+       return ret;
+}
+
 static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *command,
                struct plugin *plugin)
 {
@@ -10426,6 +10550,8 @@ static int wdc_capabilities(int argc, char **argv,
             capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE ? "Supported" : "Not Supported");
     printf("vs-hw-rev-log                 : %s\n",
             capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE ? "Supported" : "Not Supported");
+    printf("vs-vs-device_waf              : %s\n",
+                       capabilities & WDC_DRIVE_CAP_DEVICE_WAF ? "Supported" : "Not Supported");
    printf("capabilities                  : Supported\n");
     nvme_free_tree(r);
     close(fd);
index 7b2c2b159cc4c4eecf9e01b0861745823c9844f1..7f93924510da28934ea767bf349d3ff705e9de49 100644 (file)
@@ -4,7 +4,7 @@
 #if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ)
 #define WDC_NVME
 
-#define WDC_PLUGIN_VERSION   "1.16.5"
+#define WDC_PLUGIN_VERSION   "1.16.6"
 #include "cmd.h"
 
 PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),
@@ -43,6 +43,7 @@ PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERS
                ENTRY("cloud-boot-SSD-version", "WDC Get the Cloud Boot SSD Version", wdc_cloud_boot_SSD_version)
                ENTRY("vs-cloud-log", "WDC Get the Cloud Log Page", wdc_vs_cloud_log)
                ENTRY("vs-hw-rev-log", "WDC Get the Hardware Revision Log Page", wdc_vs_hw_rev_log)
+               ENTRY("vs-device-waf", "WDC Calculate Device Write Amplication Factor", wdc_vs_device_waf)
        )
 );