diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-11-05 18:23:26 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2022-11-05 18:23:26 +0000 |
commit | fab3f41b7b3f080c215157a026ee6bc7efbfe968 (patch) | |
tree | f0fafb0805c3eb11eb2a278f9f8058376c8f0f2b /plugins | |
parent | Adding upstream version 2.1.2. (diff) | |
download | nvme-cli-fab3f41b7b3f080c215157a026ee6bc7efbfe968.tar.xz nvme-cli-fab3f41b7b3f080c215157a026ee6bc7efbfe968.zip |
Adding upstream version 2.2.1.upstream/2.2.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plugins')
38 files changed, 3803 insertions, 1706 deletions
diff --git a/plugins/dera/dera-nvme.c b/plugins/dera/dera-nvme.c index 1390be0..9408e50 100644 --- a/plugins/dera/dera-nvme.c +++ b/plugins/dera/dera-nvme.c @@ -117,20 +117,21 @@ static int nvme_dera_get_device_status(int fd, enum dera_device_status *result) static int get_status(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int fd, err; struct nvme_dera_smart_info_log log; enum dera_device_status state = DEVICE_STATUS_FATAL_ERROR; char *desc = "Get the Dera device status"; + struct nvme_dev *dev; + int err; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - err = nvme_get_log_simple(fd, 0xc0, sizeof(log), &log); + err = nvme_get_log_simple(dev_fd(dev), 0xc0, sizeof(log), &log); if (err) { goto exit; } @@ -153,7 +154,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin "Runtime Low", }; - err = nvme_dera_get_device_status(fd, &state); + err = nvme_dera_get_device_status(dev_fd(dev), &state); if (!err){ if (state > 0 && state < 4){ printf("device_status : %s %d%% completed\n", dev_status[state], log.rebuild_percent); @@ -205,7 +206,7 @@ exit: if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } diff --git a/plugins/innogrit/innogrit-nvme.c b/plugins/innogrit/innogrit-nvme.c index 220a5a7..b5d40dd 100644 --- a/plugins/innogrit/innogrit-nvme.c +++ b/plugins/innogrit/innogrit-nvme.c @@ -5,6 +5,7 @@ #include <errno.h> #include <unistd.h> #include <sys/stat.h> +#include <time.h> #include "common.h" #include "nvme.h" @@ -20,10 +21,11 @@ static int innogrit_smart_log_additional(int argc, char **argv, struct plugin *plugin) { struct nvme_smart_log smart_log = { 0 }; - int fd, i, iindex; struct vsc_smart_log *pvsc_smart = (struct vsc_smart_log *)smart_log.rsvd232; const char *desc = "Retrieve additional SMART log for the given device "; const char *namespace = "(optional) desired namespace"; + struct nvme_dev *dev; + int err, i, iindex; struct config { __u32 namespace_id; @@ -38,12 +40,12 @@ static int innogrit_smart_log_additional(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - nvme_get_log_smart(fd, cfg.namespace_id, false, &smart_log); - nvme_show_smart_log(&smart_log, cfg.namespace_id, devicename, NORMAL); + nvme_get_log_smart(dev_fd(dev), cfg.namespace_id, false, &smart_log); + nvme_show_smart_log(&smart_log, cfg.namespace_id, dev->name, NORMAL); printf("DW0[0-1] Defect Cnt : %u\n", pvsc_smart->defect_cnt); printf("DW0[2-3] Slc Spb Cnt : %u\n", pvsc_smart->slc_spb_cnt); @@ -69,11 +71,15 @@ static int innogrit_smart_log_additional(int argc, char **argv, printf("DW17 weight_ec : %u\n", pvsc_smart->weight_ec); printf("DW18 slc_cap_mb : %u\n", pvsc_smart->slc_cap_mb); printf("DW19-20 nand_page_write_cnt : %llu\n", pvsc_smart->nand_page_write_cnt); - - iindex = 21; - for (i = 0; i < (sizeof(pvsc_smart->reserved2)/4); i++) { - if (pvsc_smart->reserved2[i] != 0) - printf("DW%-37d : %u\n", iindex, pvsc_smart->reserved2[i]); + printf("DW21 program_error_cnt : %u\n", pvsc_smart->program_error_cnt); + printf("DW22 erase_error_cnt : %u\n", pvsc_smart->erase_error_cnt); + printf("DW23[0] flash_type : %u\n", pvsc_smart->flash_type); + printf("DW24 hs_crc_err_cnt : %u\n", pvsc_smart->hs_crc_err_cnt); + printf("DW25 ddr_ecc_err_cnt : %u\n", pvsc_smart->ddr_ecc_err_cnt); + iindex = 26; + for (i = 0; i < (sizeof(pvsc_smart->reserved3)/4); i++) { + if (pvsc_smart->reserved3[i] != 0) + printf("DW%-37d : %u\n", iindex, pvsc_smart->reserved3[i]); iindex++; } @@ -163,9 +169,10 @@ static int innogrit_vsc_geteventlog(int argc, char **argv, unsigned int isize, icheck_stopvalue, iend; unsigned char bSortLog = false, bget_nextlog = true; struct evlg_flush_hdr *pevlog = (struct evlg_flush_hdr *)data; - int fd, ret = -1; const char *desc = "Recrieve event log for the given device "; const char *clean_opt = "(optional) 1 for clean event log"; + struct nvme_dev *dev; + int ret = -1; struct config { __u32 clean_flg; @@ -180,9 +187,9 @@ static int innogrit_vsc_geteventlog(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; if (getcwd(currentdir, 128) == NULL) @@ -211,8 +218,10 @@ static int innogrit_vsc_geteventlog(int argc, char **argv, icount++; memset(data, 0, 4096); - ret = nvme_vucmd(fd, NVME_VSC_GET_EVENT_LOG, 0, 0, (SRB_SIGNATURE >> 32), - (SRB_SIGNATURE & 0xFFFFFFFF), (char *)data, 4096); + ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET_EVENT_LOG, 0, 0, + (SRB_SIGNATURE >> 32), + (SRB_SIGNATURE & 0xFFFFFFFF), + (char *)data, 4096); if (ret == -1) return ret; @@ -277,10 +286,13 @@ static int innogrit_vsc_geteventlog(int argc, char **argv, if (cfg.clean_flg == 1) { printf("Clean eventlog\n"); - nvme_vucmd(fd, NVME_VSC_CLEAN_EVENT_LOG, 0, 0, (SRB_SIGNATURE >> 32), - (SRB_SIGNATURE & 0xFFFFFFFF), (char *)NULL, 0); + nvme_vucmd(dev_fd(dev), NVME_VSC_CLEAN_EVENT_LOG, 0, 0, + (SRB_SIGNATURE >> 32), + (SRB_SIGNATURE & 0xFFFFFFFF), (char *)NULL, 0); } + dev_close(dev); + return ret; } @@ -296,16 +308,17 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, unsigned char busevsc = false; unsigned int ipackcount, ipackindex; char fwvera[32]; - int fd, ret = -1; const char *desc = "Recrieve cdump data for the given device "; + struct nvme_dev *dev; + int ret = -1; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; if (getcwd(currentdir, 128) == NULL) return -1; @@ -315,8 +328,9 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, ipackindex = 0; memset(data, 0, 4096); - if (nvme_vucmd(fd, NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00, (SRB_SIGNATURE >> 32), - (SRB_SIGNATURE & 0xFFFFFFFF), (char *)data, 4096) == 0) { + if (nvme_vucmd(dev_fd(dev), NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00, + (SRB_SIGNATURE >> 32), (SRB_SIGNATURE & 0xFFFFFFFF), + (char *)data, 4096) == 0) { memcpy(&cdumpinfo, &data[3072], sizeof(cdumpinfo)); if (cdumpinfo.sig == 0x5a5b5c5d) { busevsc = true; @@ -337,7 +351,9 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, if (busevsc == false) { memset(data, 0, 4096); - ret = nvme_get_nsid_log(fd, true, 0x07, NVME_NSID_ALL, 4096, data); + ret = nvme_get_nsid_log(dev_fd(dev), true, 0x07, + NVME_NSID_ALL, + 4096, data); if (ret != 0) return ret; @@ -360,10 +376,15 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, for (icur = 0; icur < itotal; icur += 4096) { memset(data, 0, 4096); if (busevsc) - ret = nvme_vucmd(fd, NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00, (SRB_SIGNATURE >> 32), - (SRB_SIGNATURE & 0xFFFFFFFF), (char *)data, 4096); + ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, + VSC_FN_GET_CDUMP, 0x00, + (SRB_SIGNATURE >> 32), + (SRB_SIGNATURE & 0xFFFFFFFF), + (char *)data, 4096); else - ret = nvme_get_nsid_log(fd, true, 0x07, NVME_NSID_ALL, 4096, data); + ret = nvme_get_nsid_log(dev_fd(dev), true, + 0x07, + NVME_NSID_ALL, 4096, data); if (ret != 0) return ret; @@ -379,10 +400,16 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, if (ipackindex != ipackcount) { memset(data, 0, 4096); if (busevsc) - ret = nvme_vucmd(fd, NVME_VSC_GET, VSC_FN_GET_CDUMP, 0x00, (SRB_SIGNATURE >> 32), - (SRB_SIGNATURE & 0xFFFFFFFF), (char *)data, 4096); + ret = nvme_vucmd(dev_fd(dev), NVME_VSC_GET, + VSC_FN_GET_CDUMP, 0x00, + (SRB_SIGNATURE >> 32), + (SRB_SIGNATURE & 0xFFFFFFFF), + (char *)data, 4096); else - ret = nvme_get_nsid_log(fd, true, 0x07, NVME_NSID_ALL, 4096, data); + ret = nvme_get_nsid_log(dev_fd(dev), true, + 0x07, + NVME_NSID_ALL, 4096, + data); if (ret != 0) return ret; @@ -398,5 +425,6 @@ static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command, } printf("\n"); + dev_close(dev); return ret; } diff --git a/plugins/innogrit/typedef.h b/plugins/innogrit/typedef.h index d4ea269..a97a008 100644 --- a/plugins/innogrit/typedef.h +++ b/plugins/innogrit/typedef.h @@ -56,7 +56,13 @@ struct vsc_smart_log { unsigned int weight_ec; unsigned int slc_cap_mb; unsigned long long nand_page_write_cnt; - unsigned int reserved2[49]; + unsigned int program_error_cnt; + unsigned int erase_error_cnt; + u_char flash_type; + u_char reserved2[3]; + unsigned int hs_crc_err_cnt; + unsigned int ddr_ecc_err_cnt; + unsigned int reserved3[44]; }; #pragma pack(pop) diff --git a/plugins/intel/intel-nvme.c b/plugins/intel/intel-nvme.c index 1bf6627..f660b84 100644 --- a/plugins/intel/intel-nvme.c +++ b/plugins/intel/intel-nvme.c @@ -344,7 +344,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, const char *json= "Dump output in json format"; struct nvme_additional_smart_log smart_log; - int err, fd; + struct nvme_dev *dev; + int err; struct config { __u32 namespace_id; @@ -363,22 +364,25 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - err = nvme_get_log_simple(fd, 0xca, sizeof(smart_log), &smart_log); + err = nvme_get_log_simple(dev_fd(dev), 0xca, sizeof(smart_log), + &smart_log); if (!err) { if (cfg.json) - show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, devicename); + show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, + dev->name); else if (!cfg.raw_binary) - show_intel_smart_log(&smart_log, cfg.namespace_id, devicename); + show_intel_smart_log(&smart_log, cfg.namespace_id, + dev->name); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -386,9 +390,9 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu { const char *desc = "Get Intel Marketing Name log and show it."; const char *raw = "dump output in binary format"; - + struct nvme_dev *dev; char log[512]; - int err, fd; + int err; struct config { bool raw_binary; @@ -402,11 +406,11 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - err = nvme_get_log_simple(fd, 0xdd, sizeof(log), log); + err = nvme_get_log_simple(dev_fd(dev), 0xdd, sizeof(log), log); if (!err) { if (!cfg.raw_binary) printf("Intel Marketing Name Log:\n%s\n", log); @@ -414,7 +418,7 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu d_raw((unsigned char *)&log, sizeof(log)); } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -447,7 +451,8 @@ static void show_temp_stats(struct intel_temp_stats *stats) static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct intel_temp_stats stats; - int err, fd; + struct nvme_dev *dev; + int err; const char *desc = "Get Temperature Statistics log and show it."; const char *raw = "dump output in binary format"; @@ -463,11 +468,11 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - err = nvme_get_log_simple(fd, 0xc5, sizeof(stats), &stats); + err = nvme_get_log_simple(dev_fd(dev), 0xc5, sizeof(stats), &stats); if (!err) { if (!cfg.raw_binary) show_temp_stats(&stats); @@ -475,7 +480,7 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct d_raw((unsigned char *)&stats, sizeof(stats)); } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -1024,9 +1029,9 @@ static void show_lat_stats(int write) static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - - int err, fd; __u8 data[NAND_LAT_STATS_LEN]; + struct nvme_dev *dev; + int err; const char *desc = "Get Intel Latency Statistics log and show it."; const char *raw = "Dump output in binary format"; @@ -1049,15 +1054,15 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; /* For optate, latency stats are deleted every time their LID is pulled. * Therefore, we query the longest lat_stats log page first. */ - err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, - sizeof(data), &data); + err = nvme_get_log_simple(dev_fd(dev), cfg.write ? 0xc2 : 0xc1, + sizeof(data), &data); media_version[0] = (data[1] << 8) | data[0]; media_version[1] = (data[3] << 8) | data[2]; @@ -1071,7 +1076,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct struct nvme_get_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = 0xf7, .nsid = 0, .sel = 0, @@ -1123,7 +1128,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct } close_fd: - close(fd); + dev_close(dev); return err; } @@ -1338,13 +1343,14 @@ static int get_internal_log(int argc, char **argv, struct command *command, { __u8 buf[0x2000]; char f[0x100]; - int err, fd, output, i, j, count = 0, core_num = 1; + int err, output, i, j, count = 0, core_num = 1; struct nvme_passthru_cmd cmd; struct intel_cd_log cdlog; struct intel_vu_log *intel = malloc(sizeof(struct intel_vu_log)); struct intel_vu_nlog *intel_nlog = (struct intel_vu_nlog *)buf; struct intel_assert_dump *ad = (struct intel_assert_dump *) intel->reserved; struct intel_event_header *ehdr = (struct intel_event_header *)intel->reserved; + struct nvme_dev *dev; const char *desc = "Get Intel Firmware Log and save it."; const char *log = "Log type: 0, 1, or 2 for nlog, event log, and assert log, respectively."; @@ -1380,10 +1386,10 @@ static int get_internal_log(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { free(intel); - return fd; + return err; } if (cfg.log > 2 || cfg.core > 4 || cfg.lnum > 255) { @@ -1392,7 +1398,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, } if (!cfg.file) { - err = setup_file(f, cfg.file, fd, cfg.log); + err = setup_file(f, cfg.file, dev_fd(dev), cfg.log); if (err) goto out_free; cfg.file = f; @@ -1410,7 +1416,8 @@ static int get_internal_log(int argc, char **argv, struct command *command, goto out_free; } - err = read_header(&cmd, buf, fd, cdlog.u.entireDword, cfg.namespace_id); + err = read_header(&cmd, buf, dev_fd(dev), cdlog.u.entireDword, + cfg.namespace_id); if (err) goto out; memcpy(intel, buf, sizeof(*intel)); @@ -1419,7 +1426,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, if ((intel->ver.major < 1 && intel->ver.minor < 1) || (intel->ver.major <= 1 && intel->ver.minor <= 1 && cfg.log == 0)) { cmd.addr = (unsigned long)(void *)buf; - err = get_internal_log_old(buf, output, fd, &cmd); + err = get_internal_log_old(buf, output, dev_fd(dev), &cmd); goto out; } @@ -1463,7 +1470,9 @@ static int get_internal_log(int argc, char **argv, struct command *command, cmd.cdw10 = 0x400; cmd.data_len = min(0x400, ad[i].assertsize) * 4; err = read_entire_cmd(&cmd, ad[i].assertsize, - 0x400, output, fd, buf); + 0x400, output, + dev_fd(dev), + buf); if (err) goto out; @@ -1472,8 +1481,9 @@ static int get_internal_log(int argc, char **argv, struct command *command, if (count > 1) cdlog.u.fields.selectNlog = i; - err = read_header(&cmd, buf, fd, cdlog.u.entireDword, - cfg.namespace_id); + err = read_header(&cmd, buf, dev_fd(dev), + cdlog.u.entireDword, + cfg.namespace_id); if (err) goto out; err = write_header(buf, output, sizeof(*intel_nlog)); @@ -1485,7 +1495,9 @@ static int get_internal_log(int argc, char **argv, struct command *command, cmd.cdw10 = 0x400; cmd.data_len = min(0x1000, intel_nlog->nlogbytesize); err = read_entire_cmd(&cmd, intel_nlog->nlogbytesize / 4, - 0x400, output, fd, buf); + 0x400, output, + dev_fd(dev), + buf); if (err) goto out; } else if (cfg.log == 1) { @@ -1493,7 +1505,9 @@ static int get_internal_log(int argc, char **argv, struct command *command, cmd.cdw10 = 0x400; cmd.data_len = 0x400; err = read_entire_cmd(&cmd, ehdr->edumps[j].coresize, - 0x400, output, fd, buf); + 0x400, output, + dev_fd(dev), + buf); if (err) goto out; } @@ -1511,14 +1525,13 @@ out: close(output); out_free: free(intel); - close(fd); + dev_close(dev); return err; } static int enable_lat_stats_tracking(int argc, char **argv, struct command *command, struct plugin *plugin) { - int err, fd; const char *desc = ( "Enable/Disable Intel Latency Statistics Tracking.\n" "No argument prints current status."); @@ -1531,8 +1544,10 @@ static int enable_lat_stats_tracking(int argc, char **argv, const __u32 cdw12 = 0x0; const __u32 data_len = 32; const __u32 save = 0; - __u32 result; + struct nvme_dev *dev; void *buf = NULL; + __u32 result; + int err; struct config { bool enable, disable; @@ -1549,7 +1564,7 @@ static int enable_lat_stats_tracking(int argc, char **argv, {NULL} }; - fd = parse_and_open(argc, argv, desc, command_line_options); + err = parse_and_open(&dev, argc, argv, desc, command_line_options); enum Option { None = -1, @@ -1564,12 +1579,12 @@ static int enable_lat_stats_tracking(int argc, char **argv, else if (cfg.enable || cfg.disable) option = cfg.enable; - if (fd < 0) - return fd; + if (err) + return err; struct nvme_get_features_args args_get = { .args_size = sizeof(args_get), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = nsid, .sel = sel, @@ -1583,7 +1598,7 @@ static int enable_lat_stats_tracking(int argc, char **argv, struct nvme_set_features_args args_set = { .args_size = sizeof(args_set), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = nsid, .cdw11 = option, @@ -1606,7 +1621,7 @@ static int enable_lat_stats_tracking(int argc, char **argv, fid, result); } else { printf("Could not read feature id 0xE2.\n"); - close(fd); + dev_close(dev); return err; } break; @@ -1627,14 +1642,13 @@ static int enable_lat_stats_tracking(int argc, char **argv, printf("%d not supported.\n", option); return EINVAL; } - close(fd); - return fd; + dev_close(dev); + return err; } static int set_lat_stats_thresholds(int argc, char **argv, struct command *command, struct plugin *plugin) { - int err, fd, num; const char *desc = "Write Intel Bucket Thresholds for Latency Statistics Tracking"; const char *bucket_thresholds = "Bucket Threshold List, comma separated list: 0, 10, 20 ..."; const char *write = "Set write bucket Thresholds for latency tracking (read default)"; @@ -1643,7 +1657,9 @@ static int set_lat_stats_thresholds(int argc, char **argv, const __u8 fid = 0xf7; const __u32 cdw12 = 0x0; const __u32 save = 0; + struct nvme_dev *dev; __u32 result; + int err, num; struct config { bool write; @@ -1662,21 +1678,21 @@ static int set_lat_stats_thresholds(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); + err = parse_and_open(&dev, argc, argv, desc, opts); - if (fd < 0) - return fd; + if (err) + return err; /* Query maj and minor version first to figure out the amount of * valid buckets a user is allowed to modify. Read or write doesn't * matter */ - err = nvme_get_log_simple(fd, 0xc2, - sizeof(media_version), media_version); + err = nvme_get_log_simple(dev_fd(dev), 0xc2, + sizeof(media_version), media_version); if (err) { fprintf(stderr, "Querying media version failed. "); nvme_show_status(err); - goto close_fd; + goto close_dev; } if (media_version[0] == 1000) { @@ -1686,13 +1702,13 @@ static int set_lat_stats_thresholds(int argc, char **argv, sizeof(thresholds)); if (num == -1) { fprintf(stderr, "ERROR: Bucket list is malformed\n"); - goto close_fd; + goto close_dev; } struct nvme_set_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = nsid, .cdw11 = cfg.write ? 0x1 : 0x0, @@ -1717,8 +1733,8 @@ static int set_lat_stats_thresholds(int argc, char **argv, fprintf(stderr, "Unsupported command\n"); } -close_fd: - close(fd); +close_dev: + dev_close(dev); return err; } diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c index a6a8ddf..6fdd675 100644 --- a/plugins/memblaze/memblaze-nvme.c +++ b/plugins/memblaze/memblaze-nvme.c @@ -453,15 +453,16 @@ int parse_params(char *str, int number, ...) static int mb_get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_memblaze_smart_log smart_log; - int err, fd; char *desc = "Get Memblaze vendor specific additional smart log (optionally, "\ "for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; + struct nvme_dev *dev; struct config { __u32 namespace_id; bool raw_binary; }; + int err; struct config cfg = { .namespace_id = NVME_NSID_ALL, @@ -473,22 +474,24 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id, - sizeof(smart_log), &smart_log); + err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, + sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) - err = show_memblaze_smart_log(fd, cfg.namespace_id, devicename, &smart_log); + err = show_memblaze_smart_log(dev_fd(dev), + cfg.namespace_id, + dev->name, &smart_log); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -505,20 +508,22 @@ static char *mb_feature_to_string(int feature) static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Get Memblaze power management ststus\n (value 0 - 25w, 1 - 20w, 2 - 15w)"; - int err, fd; __u32 result; __u32 feature_id = MB_FEAT_POWER_MGMT; + struct nvme_dev *dev; + int err; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; struct nvme_get_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = feature_id, .nsid = 0, .sel = 0, @@ -539,7 +544,7 @@ static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd nvme_select_to_string(0), result); } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -548,8 +553,9 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd const char *desc = "Set Memblaze power management status\n (value 0 - 25w, 1 - 20w, 2 - 15w)"; const char *value = "new value of feature (required)"; const char *save = "specifies that the controller shall save the attribute"; - int err, fd; + struct nvme_dev *dev; __u32 result; + int err; struct config { __u32 feature_id; @@ -569,12 +575,13 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; struct nvme_set_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = cfg.feature_id, .nsid = 0, .cdw11 = cfg.value, @@ -597,7 +604,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -611,9 +618,10 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s " p1 value: 0 is disable, 1 is enable\n"\ " p2 value: 1 .. 5000 ms"; const char *param = "input parameters"; - int err, fd; - __u32 result; int param1 = 0, param2 = 0; + struct nvme_dev *dev; + __u32 result; + int err; struct config { __u32 feature_id; @@ -632,24 +640,25 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; if (parse_params(cfg.param, 2, ¶m1, ¶m2)) { printf("setfeature: invalid formats %s\n", cfg.param); - close(fd); + dev_close(dev); return EINVAL; } if ((param1 == 1) && (param2 < P2MIN || param2 > P2MAX)) { printf("setfeature: invalid high io latency threshold %d\n", param2); - close(fd); + dev_close(dev); return EINVAL; } cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2; struct nvme_set_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = cfg.feature_id, .nsid = 0, .cdw11 = cfg.value, @@ -672,7 +681,7 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -774,25 +783,29 @@ static int glp_high_latency(FILE *fdi, char *buf, int buflen, int print) static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Get Memblaze high latency log"; - int err, fd; char buf[LOG_PAGE_SIZE]; + struct nvme_dev *dev; FILE *fdi = NULL; + int err; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; fdi = fopen(FID_C3_LOG_FILENAME, "w+"); glp_high_latency_show_bar(fdi, DO_PRINT_FLAG); - err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf); + err = nvme_get_log_simple(dev_fd(dev), GLP_ID_VU_GET_HIGH_LATENCY_LOG, + sizeof(buf), &buf); while (1) { if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE, DO_PRINT_FLAG)) break; - err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf); + err = nvme_get_log_simple(dev_fd(dev), GLP_ID_VU_GET_HIGH_LATENCY_LOG, + sizeof(buf), &buf); if ( err) { nvme_show_status(err); break; @@ -800,7 +813,7 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd, } if (NULL != fdi) fclose(fdi); - close(fd); + dev_close(dev); return err; } @@ -829,7 +842,8 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str const char *select = "FW Select (e.g., --select=OOB, EEP, ALL)"; int xfer = 4096; void *fw_buf; - int fd, selectNo,fw_fd,fw_size,err,offset = 0; + int selectNo,fw_fd,fw_size,err,offset = 0; + struct nvme_dev *dev; struct stat sb; int i; @@ -849,9 +863,9 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; if (strlen(cfg.select) != 3) { fprintf(stderr, "Invalid select flag\n"); @@ -912,7 +926,7 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str struct nvme_fw_download_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .offset = offset, .data_len = xfer, .data = fw_buf, @@ -932,7 +946,7 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str offset += xfer; } - err = memblaze_fw_commit(fd,selectNo); + err = memblaze_fw_commit(dev_fd(dev), selectNo); if(err == 0x10B || err == 0x20B) { err = 0; @@ -944,7 +958,7 @@ out_free: out_close: close(fw_fd); out: - close(fd); + dev_close(dev); return err; } @@ -1051,10 +1065,10 @@ int io_latency_histogram(char *file, char *buf, int print, int logid) static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, struct plugin *plugin) { char stats[LOG_PAGE_SIZE]; - int err = 0; - int fd; char f1[] = FID_C1_LOG_FILENAME; char f2[] = FID_C2_LOG_FILENAME; + struct nvme_dev *dev; + int err; const char *desc = "Get Latency Statistics log and show it."; const char *write = "Get write statistics (read default)"; @@ -1071,17 +1085,19 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, sizeof(stats), &stats); + err = nvme_get_log_simple(dev_fd(dev), cfg.write ? 0xc2 : 0xc1, + sizeof(stats), &stats); if (!err) io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG, cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM); else nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -1089,8 +1105,9 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st #define FID 0x68 static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err, fd; char *desc = "Clear Memblaze devices error log."; + struct nvme_dev *dev; + int err; //const char *value = "new value of feature (required)"; //const char *save = "specifies that the controller shall save the attribute"; @@ -1112,13 +1129,13 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; struct nvme_set_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = cfg.feature_id, .nsid = 0, .cdw11 = cfg.value, @@ -1154,14 +1171,13 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, printf("NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); }; */ - close(fd); + dev_close(dev); return err; } static int mb_set_lat_stats(int argc, char **argv, struct command *command, struct plugin *plugin) { - int err, fd; const char *desc = ( "Enable/Disable Latency Statistics Tracking.\n" "No argument prints current status."); @@ -1174,8 +1190,10 @@ static int mb_set_lat_stats(int argc, char **argv, const __u32 cdw12 = 0x0; const __u32 data_len = 32; const __u32 save = 0; - __u32 result; + struct nvme_dev *dev; void *buf = NULL; + __u32 result; + int err; struct config { bool enable, disable; @@ -1192,7 +1210,7 @@ static int mb_set_lat_stats(int argc, char **argv, {NULL} }; - fd = parse_and_open(argc, argv, desc, command_line_options); + err = parse_and_open(&dev, argc, argv, desc, command_line_options); enum Option { None = -1, @@ -1208,7 +1226,7 @@ static int mb_set_lat_stats(int argc, char **argv, struct nvme_get_features_args args_get = { .args_size = sizeof(args_get), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = nsid, .sel = sel, @@ -1222,7 +1240,7 @@ static int mb_set_lat_stats(int argc, char **argv, struct nvme_set_features_args args_set = { .args_size = sizeof(args_set), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = nsid, .cdw11 = option, @@ -1236,8 +1254,8 @@ static int mb_set_lat_stats(int argc, char **argv, .result = &result, }; - if (fd < 0) - return fd; + if (err) + return err; switch (option) { case None: err = nvme_get_features(&args_get); @@ -1247,7 +1265,7 @@ static int mb_set_lat_stats(int argc, char **argv, fid, result); } else { printf("Could not read feature id 0xE2.\n"); - close(fd); + dev_close(dev); return err; } break; @@ -1268,7 +1286,7 @@ static int mb_set_lat_stats(int argc, char **argv, printf("%d not supported.\n", option); err = EINVAL; } - close(fd); + dev_close(dev); return err; } diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c index 1c3c51d..e6f3a8c 100644 --- a/plugins/micron/micron-nvme.c +++ b/plugins/micron/micron-nvme.c @@ -453,13 +453,15 @@ exit_status: /* * Plugin Commands */ -static int micron_parse_options(int argc, char **argv, const char *desc, - const struct argconfig_commandline_options *opts, eDriveModel *modelp) +static int micron_parse_options(struct nvme_dev **dev, int argc, char **argv, + const char *desc, + const struct argconfig_commandline_options *opts, + eDriveModel *modelp) { int idx = 0; - int fd = parse_and_open(argc, argv, desc, opts); + int err = parse_and_open(dev, argc, argv, desc, opts); - if (fd < 0) { + if (err) { perror("open"); return -1; } @@ -469,7 +471,7 @@ static int micron_parse_options(int argc, char **argv, const char *desc, *modelp = GetDriveModel(idx); } - return fd; + return 0; } static int micron_fw_commit(int fd, int select) @@ -496,7 +498,8 @@ static int micron_selective_download(int argc, char **argv, const char *select = "FW Select (e.g., --select=ALL)"; int xfer = 4096; void *fw_buf; - int fd, selectNo, fw_fd, fw_size, err, offset = 0; + int selectNo, fw_fd, fw_size, err, offset = 0; + struct nvme_dev *dev; struct stat sb; struct config { @@ -515,13 +518,13 @@ static int micron_selective_download(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; if (strlen(cfg.select) != 3) { fprintf(stderr, "Invalid select flag\n"); - close(fd); + dev_close(dev); return EINVAL; } @@ -537,14 +540,14 @@ static int micron_selective_download(int argc, char **argv, selectNo = 26; } else { fprintf(stderr, "Invalid select flag\n"); - close(fd); + dev_close(dev); return EINVAL; } fw_fd = open(cfg.fw, O_RDONLY); if (fw_fd < 0) { fprintf(stderr, "no firmware file provided\n"); - close(fd); + dev_close(dev); return EINVAL; } @@ -578,7 +581,7 @@ static int micron_selective_download(int argc, char **argv, struct nvme_fw_download_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .offset = offset, .data_len = xfer, .data = fw_buf, @@ -598,7 +601,7 @@ static int micron_selective_download(int argc, char **argv, offset += xfer; } - err = micron_fw_commit(fd, selectNo); + err = micron_fw_commit(dev_fd(dev), selectNo); if (err == 0x10B || err == 0x20B) { err = 0; @@ -610,7 +613,7 @@ out_free: free(fw_buf); out: close(fw_fd); - close(fd); + dev_close(dev); return err; } @@ -625,10 +628,10 @@ static int micron_smbus_option(int argc, char **argv, "temperature (default) for enable option, 0 (current), " "1 (default), 2 (saved) for status options"; const char *save = "1 - persistent, 0 - non-persistent (default)"; - int err = 0; - int fd = 0; int fid = MICRON_FEATURE_SMBUS_OPTION; eDriveModel model = UNKNOWN_MODEL; + struct nvme_dev *dev; + int err = 0; struct { char *option; @@ -649,18 +652,20 @@ static int micron_smbus_option(int argc, char **argv, OPT_END() }; - if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) return err; if (model != M5407 && model != M5411) { printf ("This option is not supported for specified drive\n"); - close(fd); + dev_close(dev); return err; } if (!strcmp(opt.option, "enable")) { cdw11 = opt.value << 1 | 1; - err = nvme_set_features_simple(fd, fid, 1, cdw11, opt.save, &result); + err = nvme_set_features_simple(dev_fd(dev), fid, 1, cdw11, opt.save, + &result); if (err == 0) { printf("successfully enabled SMBus on drive\n"); } else { @@ -670,7 +675,7 @@ static int micron_smbus_option(int argc, char **argv, else if (!strcmp(opt.option, "status")) { struct nvme_get_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = 1, .sel = opt.value, @@ -692,7 +697,8 @@ static int micron_smbus_option(int argc, char **argv, } else if (!strcmp(opt.option, "disable")) { cdw11 = opt.value << 1 | 0; - err = nvme_set_features_simple(fd, fid, 1, cdw11, opt.save, &result); + err = nvme_set_features_simple(dev_fd(dev), fid, 1, cdw11, opt.save, + &result); if (err == 0) { printf("Successfully disabled SMBus on drive\n"); } else { @@ -701,11 +707,11 @@ static int micron_smbus_option(int argc, char **argv, } else { printf("Invalid option %s, valid values are enable, disable or status\n", opt.option); - close(fd); + dev_close(dev); return -1; } - close(fd); + close(dev_fd(dev)); return err; } @@ -727,15 +733,15 @@ static int micron_temp_stats(int argc, char **argv, struct command *cmd, bool is_json = false; struct json_object *root; struct json_object *logPages; - int fd; + struct nvme_dev *dev; OPT_ARGS(opts) = { OPT_FMT("format", 'f', &cfg.fmt, fmt), OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { printf("\nDevice not found \n");; return -1; } @@ -743,7 +749,7 @@ static int micron_temp_stats(int argc, char **argv, struct command *cmd, if (strcmp(cfg.fmt, "json") == 0) is_json = true; - err = nvme_get_log_smart(fd, 0xffffffff, false, &smart_log); + err = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); if (!err) { temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); temperature = temperature ? temperature - 273 : 0; @@ -778,15 +784,16 @@ static int micron_temp_stats(int argc, char **argv, struct command *cmd, } } } - close(fd); + dev_close(dev); return err; } static int micron_pcie_stats(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int i, fd, err = 0, bus = 0, domain = 0, device = 0, function = 0, ctrlIdx; + int i, err = 0, bus = 0, domain = 0, device = 0, function = 0, ctrlIdx; char strTempFile[1024], strTempFile2[1024], command[1024]; + struct nvme_dev *dev; char *businfo = NULL; char *devicename = NULL; char tdevice[NAME_MAX] = { 0 }; @@ -875,8 +882,8 @@ static int micron_pcie_stats(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { printf("\nDevice not found \n");; return -1; } @@ -896,7 +903,7 @@ static int micron_pcie_stats(int argc, char **argv, admin_cmd.addr = (__u64)(uintptr_t)&pcie_error_counters; admin_cmd.data_len = sizeof(pcie_error_counters); admin_cmd.cdw10 = 1; - err = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); if (!err) { counters = true; correctable_errors = 10; @@ -1017,8 +1024,7 @@ print_stats: } out: - if (fd > 0) - close(fd); + dev_close(dev); return err; } @@ -1028,6 +1034,7 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, { int err = -EINVAL, bus = 0, domain = 0, device = 0, function = 0; char strTempFile[1024], strTempFile2[1024], command[1024]; + struct nvme_dev *dev; char *businfo = NULL; char *devicename = NULL; char tdevice[PATH_MAX] = { 0 }; @@ -1035,7 +1042,6 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, eDriveModel model = UNKNOWN_MODEL; struct nvme_passthru_cmd admin_cmd = { 0 }; char correctable[8] = { 0 }; - int fd = -1; FILE *fp; char *res; const char *desc = "Clear PCIe Device Correctable Errors"; @@ -1045,12 +1051,14 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, OPT_END() }; - if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) return err; /* For M51CX models, PCIe errors are cleared using 0xC3 feature */ if (model == M51CX) { - err = nvme_set_features_simple(fd, fid, 0, (1 << 31), false, &result); + err = nvme_set_features_simple(dev_fd(dev), fid, 0, (1 << 31), false, + &result); if (err == 0 && (err = (int)result) == 0) { printf("Device correctable errors are cleared!\n"); goto out; @@ -1059,7 +1067,7 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, admin_cmd.opcode = 0xD6; admin_cmd.addr = 0; admin_cmd.cdw10 = 0; - err = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); if (err == 0) { printf("Device correctable error counters are cleared!\n"); goto out; @@ -1134,7 +1142,7 @@ static int micron_clear_pcie_correctable_errors(int argc, char **argv, printf("Device correctable errors detected: %s\n", correctable); err = 0; out: - close(fd); + dev_close(dev); return err; } @@ -1490,7 +1498,8 @@ static int micron_nand_stats(int argc, char **argv, unsigned int logFB[FB_log_size/sizeof(int)] = { 0 }; eDriveModel eModel = UNKNOWN_MODEL; struct nvme_id_ctrl ctrl; - int fd, err, ctrlIdx; + struct nvme_dev *dev; + int err, ctrlIdx; __u8 nsze; bool has_d0_log = true; bool has_fb_log = false; @@ -1508,8 +1517,8 @@ static int micron_nand_stats(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { printf("\nDevice not found \n");; return -1; } @@ -1517,7 +1526,7 @@ static int micron_nand_stats(int argc, char **argv, if (strcmp(cfg.fmt, "normal") == 0) is_json = false; - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (err) { printf("Error %d retrieving controller identification data\n", err); goto out; @@ -1532,12 +1541,12 @@ static int micron_nand_stats(int argc, char **argv, goto out; } - err = nvme_get_log_simple(fd, 0xD0, D0_log_size, extSmartLog); + err = nvme_get_log_simple(dev_fd(dev), 0xD0, D0_log_size, extSmartLog); has_d0_log = (0 == err); /* should check for firmware version if this log is supported or not */ if (eModel == M5407 || eModel == M5410) { - err = nvme_get_log_simple(fd, 0xFB, FB_log_size, logFB); + err = nvme_get_log_simple(dev_fd(dev), 0xFB, FB_log_size, logFB); has_fb_log = (0 == err); } @@ -1555,7 +1564,7 @@ static int micron_nand_stats(int argc, char **argv, err = -ENOTTY; } out: - close(fd); + dev_close(dev); if (err > 0) nvme_show_status(err); @@ -1595,7 +1604,8 @@ static int micron_smart_ext_log(int argc, char **argv, const char *desc = "Retrieve extended SMART logs for the given device "; unsigned int extSmartLog[E1_log_size/sizeof(int)] = { 0 }; eDriveModel eModel = UNKNOWN_MODEL; - int fd = 0, err = 0, ctrlIdx = 0; + int err = 0, ctrlIdx = 0; + struct nvme_dev *dev; bool is_json = true; struct format { char *fmt; @@ -1609,8 +1619,8 @@ static int micron_smart_ext_log(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { printf("\nDevice not found \n");; return -1; } @@ -1623,13 +1633,13 @@ static int micron_smart_ext_log(int argc, char **argv, err = -1; goto out; } - err = nvme_get_log_simple(fd, 0xE1, E1_log_size, extSmartLog); + err = nvme_get_log_simple(dev_fd(dev), 0xE1, E1_log_size, extSmartLog); if (!err) { print_ext_smart_logs_e1((__u8 *)extSmartLog, is_json); } out: - close(fd); + dev_close(dev); if (err > 0) nvme_show_status(err); return err; @@ -2005,7 +2015,6 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Get drive HW information"; - int fd, err = 0; struct nvme_id_ctrl ctrl = { 0 }; struct nvme_passthru_cmd admin_cmd = { 0 }; struct fb_drive_info { @@ -2018,9 +2027,11 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, eDriveModel model = UNKNOWN_MODEL; bool is_json = false; struct json_object *root, *driveInfo; + struct nvme_dev *dev; struct format { char *fmt; }; + int err = 0; const char *fmt = "output format normal"; struct format cfg = { @@ -2032,12 +2043,13 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, OPT_END() }; - if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) return err; if (model == UNKNOWN_MODEL) { fprintf(stderr, "ERROR : Unsupported drive for vs-drive-info cmd"); - close(fd); + dev_close(dev); return -1; } @@ -2049,17 +2061,17 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, admin_cmd.addr = (__u64) (uintptr_t) &dinfo; admin_cmd.data_len = (__u32)sizeof(dinfo); admin_cmd.cdw12 = 3; - err = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + err = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); if (err) { fprintf(stderr, "ERROR : drive-info opcode failed with 0x%x\n", err); - close(fd); + dev_close(dev); return -1; } } else { - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (err) { fprintf(stderr, "ERROR : identify_ctrl() failed with 0x%x\n", err); - close(fd); + dev_close(dev); return -1; } dinfo.hw_ver_major = ctrl.vs[820]; @@ -2103,7 +2115,7 @@ static int micron_drive_info(int argc, char **argv, struct command *cmd, } } - close(fd); + dev_close(dev); return 0; } @@ -2242,10 +2254,11 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c int count = 0; unsigned int logC2[C2_log_size/sizeof(int)] = { 0 }; eDriveModel eModel = UNKNOWN_MODEL; - int fd, err; + struct nvme_dev *dev; struct format { char *fmt; }; + int err; const char *fmt = "output format normal"; struct format cfg = { @@ -2257,13 +2270,13 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c OPT_END() }; - if ((fd = micron_parse_options(argc, argv, desc, opts, &eModel)) < 0) { + err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); + if (err < 0) return -1; - } if (strcmp(cfg.fmt, "normal") != 0) { fprintf (stderr, "only normal format is supported currently\n"); - close(fd); + dev_close(dev); return -1; } @@ -2274,7 +2287,7 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c goto out; } - err = nvme_get_log_simple(fd, 0xC2, C2_log_size, logC2); + err = nvme_get_log_simple(dev_fd(dev), 0xC2, C2_log_size, logC2); if (err) { fprintf(stderr, "Failed to retrieve fw activation history log, error: %x\n", err); goto out; @@ -2308,7 +2321,7 @@ static int micron_fw_activation_history(int argc, char **argv, struct command *c } } out: - close(fd); + dev_close(dev); return err; } @@ -2327,12 +2340,12 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd 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 nvme_dev *dev; struct { char *option; char *command; @@ -2351,9 +2364,9 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd }; - if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) { + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) return -1; - } if (!strcmp(opt.option, "enable")) { enable = 1; @@ -2361,13 +2374,13 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd enable = 0; } else if (strcmp(opt.option, "status")) { printf("Invalid control option %s specified\n", opt.option); - close(fd); + dev_close(dev); return -1; } struct nvme_get_features_args g_args = { .args_size = sizeof(g_args), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = 0, .sel = 0, @@ -2382,7 +2395,7 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd err = nvme_get_features(&g_args); if (err != 0) { printf("Failed to retrieve latency monitoring feature status\n"); - close(fd); + dev_close(dev); return err; } @@ -2407,7 +2420,7 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd } else if (result == 0) { printf("\n"); } - close(fd); + dev_close(dev); return err; } @@ -2415,13 +2428,13 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd if (enable == 1) { if (opt.threshold > 2550) { printf("The maximum threshold value cannot be more than 2550 ms\n"); - close(fd); + dev_close(dev); 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"); - close(fd); + dev_close(dev); return -1; } opt.threshold /= 10; @@ -2440,13 +2453,13 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd } else if (strcmp(opt.command, "all")) { printf("Invalid command %s specified for option %s\n", opt.command, opt.option); - close(fd); + dev_close(dev); return -1; } struct nvme_set_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = MICRON_FID_LATENCY_MONITOR, .nsid = 0, .cdw11 = enable, @@ -2469,7 +2482,7 @@ static int micron_latency_stats_track(int argc, char **argv, struct command *cmd opt.option, opt.command, opt.threshold == 0 ? 800 : opt.threshold * 10); } - close(fd); + dev_close(dev); return err; } @@ -2510,21 +2523,22 @@ static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd, uint32_t rfu[6]; } log[LATENCY_LOG_ENTRIES]; eDriveModel model = UNKNOWN_MODEL; + struct nvme_dev *dev; 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) + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err) return err; memset(&log, 0, sizeof(log)); - err = nvme_get_log_simple(fd, 0xD1, sizeof(log), &log); + err = nvme_get_log_simple(dev_fd(dev), 0xD1, sizeof(log), &log); if (err) { if (err < 0) printf("Unable to retrieve latency stats log the drive\n"); - close(fd); + dev_close(dev); return err; } /* print header and each log entry */ @@ -2538,7 +2552,7 @@ static int micron_latency_stats_logs(int argc, char **argv, struct command *cmd, log[i].deac, log[i].prinfo, log[i].fua, log[i].lr); } printf("\n"); - close(fd); + dev_close(dev); return err; } @@ -2549,7 +2563,7 @@ static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, const char *command = "command to display stats - all|read|write|trim" "default is all"; int err = 0; - int fd = -1; + struct nvme_dev *dev; eDriveModel model = UNKNOWN_MODEL; #define LATENCY_BUCKET_COUNT 32 #define LATENCY_BUCKET_RSVD 32 @@ -2592,7 +2606,8 @@ static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, OPT_END() }; - if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) return err; if (!strcmp(opt.command, "read")) { cmd_stats = &log.read_cmds[0]; @@ -2605,16 +2620,16 @@ static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, cmd_str = "Trim"; } else if (strcmp(opt.command, "all")) { printf("Invalid command option %s to display latency stats\n", opt.command); - close(fd); + dev_close(dev); return -1; } memset(&log, 0, sizeof(log)); - err = nvme_get_log_simple(fd, 0xD0, sizeof(log), &log); + err = nvme_get_log_simple(dev_fd(dev), 0xD0, sizeof(log), &log); if (err) { if (err < 0) printf("Unable to retrieve latency stats log the drive\n"); - close(fd); + dev_close(dev); return err; } printf("Micron IO %s Command Latency Statistics\n" @@ -2636,7 +2651,7 @@ static int micron_latency_stats_info(int argc, char **argv, struct command *cmd, printf("%2d %8s %8s %8"PRIu64"\n", bucket, start, end, cmd_stats[b]); } - close(fd); + dev_close(dev); return err; } @@ -2648,7 +2663,7 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c unsigned int logFB[FB_log_size/sizeof(int)] = { 0 }; struct nvme_id_ctrl ctrl; eDriveModel eModel = UNKNOWN_MODEL; - int fd, err = 0; + struct nvme_dev *dev; bool is_json = true; struct format { char *fmt; @@ -2657,15 +2672,16 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c struct format cfg = { .fmt = "json", }; + int err = 0; OPT_ARGS(opts) = { OPT_FMT("format", 'f', &cfg.fmt, fmt), OPT_END() }; - if ((fd = micron_parse_options(argc, argv, desc, opts, &eModel)) < 0) { + err = micron_parse_options(&dev, argc, argv, desc, opts, &eModel); + if (err < 0) return -1; - } if (strcmp(cfg.fmt, "normal") == 0) is_json = false; @@ -2675,9 +2691,9 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c __u8 spec = (eModel == M5410) ? 0 : 1; __u8 nsze; - if ((err = nvme_identify_ctrl(fd, &ctrl)) == 0) - err = nvme_get_log_simple(fd, 0xFB, - FB_log_size, logFB); + if ((err = nvme_identify_ctrl(dev_fd(dev), &ctrl)) == 0) + err = nvme_get_log_simple(dev_fd(dev), 0xFB, + FB_log_size, logFB); if (err) { if (err < 0) printf("Unable to retrieve smart log 0xFB for the drive\n"); @@ -2698,14 +2714,14 @@ static int micron_ocp_smart_health_logs(int argc, char **argv, struct command *c goto out; } - err = nvme_get_log_simple(fd, 0xC0, C0_log_size, logC0); + err = nvme_get_log_simple(dev_fd(dev), 0xC0, C0_log_size, logC0); if (err == 0) { print_smart_cloud_health_log((__u8 *)logC0, is_json); } else if (err < 0) { printf("Unable to retrieve extended smart log 0xC0 for the drive\n"); } out: - close(fd); + dev_close(dev); if (err > 0) nvme_show_status(err); return err; @@ -2715,28 +2731,30 @@ static int micron_clr_fw_activation_history(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Clear FW activation history"; - int fd, err = 0; __u32 result = 0; __u8 fid = MICRON_FEATURE_CLEAR_FW_ACTIVATION_HISTORY; eDriveModel model = UNKNOWN_MODEL; + struct nvme_dev *dev; OPT_ARGS(opts) = { OPT_END() }; + int err = 0; - if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) return err; if (model != M51CX) { printf ("This option is not supported for specified drive\n"); - close(fd); + dev_close(dev); return err; } - err = nvme_set_features_simple(fd, fid, 1 << 31, 0, 0, &result); + err = nvme_set_features_simple(dev_fd(dev), fid, 1 << 31, 0, 0, &result); if (err == 0) err = (int)result; else printf ("Failed to clear fw activation history, error = 0x%x\n", err); - close(fd); + dev_close(dev); return err; } @@ -2750,10 +2768,10 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, const char *select = "select/save values: enable/disable options" "1 - save (persistent), 0 - non-persistent and for " "status options: 0 - current, 1 - default, 2-saved"; - int fd = 0; int fid = MICRON_FEATURE_TELEMETRY_CONTROL_OPTION; eDriveModel model = UNKNOWN_MODEL; struct nvme_id_ctrl ctrl = { 0 }; + struct nvme_dev *dev; struct { char *option; @@ -2769,21 +2787,21 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, OPT_END() }; - if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) { + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) return -1; - } - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); if ((ctrl.lpa & 0x8) != 0x8) { printf("drive doesn't support host/controller generated telemetry logs\n"); - close(fd); + dev_close(dev); return err; } if (!strcmp(opt.option, "enable")) { struct nvme_set_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = 1, .cdw11 = 1, @@ -2805,7 +2823,7 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, } else if (!strcmp(opt.option, "disable")) { struct nvme_set_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = 1, .cdw11 = 0, @@ -2827,7 +2845,7 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, } else if (!strcmp(opt.option, "status")) { struct nvme_get_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = fid, .nsid = 1, .sel = opt.select & 0x3, @@ -2847,11 +2865,11 @@ static int micron_telemetry_cntrl_option(int argc, char **argv, } } else { printf("invalid option %s, valid values are enable,disable or status\n", opt.option); - close(fd); + dev_close(dev); return -1; } - close(fd); + dev_close(dev); return err; } @@ -2945,7 +2963,7 @@ static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) if (hdr.log_size == sizeof(hdr)) { buffer = (uint8_t *)malloc(sizeof(hdr)); if (buffer == NULL) { - fprintf(stderr, "malloc of %lu bytes failed for log: 0x%X\n", + fprintf(stderr, "malloc of %zu bytes failed for log: 0x%X\n", sizeof(hdr), id); return -ENOMEM; } @@ -2953,7 +2971,7 @@ static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) } else if (hdr.log_size < hdr.max_size) { buffer = (uint8_t *)malloc(sizeof(hdr) + hdr.log_size); if (buffer == NULL) { - fprintf(stderr, "malloc of %lu bytes failed for log: 0x%X\n", + fprintf(stderr, "malloc of %zu bytes failed for log: 0x%X\n", hdr.log_size + sizeof(hdr), id); return -ENOMEM; } @@ -2971,7 +2989,7 @@ static int get_common_log(int fd, uint8_t id, uint8_t **buf, int *size) */ buffer = (uint8_t *)malloc(hdr.max_size + sizeof(hdr)); if (buffer == NULL) { - fprintf(stderr, "malloc of %lu bytes failed for log: 0x%X\n", + fprintf(stderr, "malloc of %zu bytes failed for log: 0x%X\n", hdr.max_size + sizeof(hdr), id); return -ENOMEM; } @@ -3010,7 +3028,6 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, struct plugin *plugin) { int err = -EINVAL; - int fd = 0; int ctrlIdx, telemetry_option = 0; char strOSDirName[1024]; char strCtrlDirName[1024]; @@ -3021,6 +3038,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, char sn[20] = { 0 }; char msg[256] = { 0 }; int c_logs_index = 8; /* should be current size of aVendorLogs */ + struct nvme_dev *dev; struct { unsigned char ucLogPage; const char *strFileName; @@ -3104,10 +3122,9 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; /* if telemetry type is specified, check for data area */ if (strlen(cfg.type) != 0) { @@ -3143,7 +3160,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, goto out; } - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (err) goto out; @@ -3151,11 +3168,12 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (telemetry_option) { if ((ctrl.lpa & 0x8) != 0x8) { printf("telemetry option is not supported for specified drive\n"); - close(fd); + dev_close(dev); goto out; } int logSize = 0; __u8 *buffer = NULL; const char *dir = "."; - err = micron_telemetry_log(fd, cfg.log, &buffer, &logSize, cfg.data_area); + err = micron_telemetry_log(dev_fd(dev), cfg.log, &buffer, &logSize, + cfg.data_area); if (err == 0 && logSize > 0 && buffer != NULL) { sprintf(msg, "telemetry log: 0x%X", cfg.log); WriteData(buffer, logSize, dir, cfg.package, msg); @@ -3184,16 +3202,16 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, GetDriveInfo(strOSDirName, ctrlIdx, &ctrl); for (int i = 1; i <= ctrl.nn; i++) - GetNSIDDInfo(fd, strCtrlDirName, i); + GetNSIDDInfo(dev_fd(dev), strCtrlDirName, i); - GetSmartlogData(fd, strCtrlDirName); - GetErrorlogData(fd, ctrl.elpe, strCtrlDirName); - GetGenericLogs(fd, strCtrlDirName); + GetSmartlogData(dev_fd(dev), strCtrlDirName); + GetErrorlogData(dev_fd(dev), ctrl.elpe, strCtrlDirName); + GetGenericLogs(dev_fd(dev), strCtrlDirName); /* pull if telemetry log data is supported */ if ((ctrl.lpa & 0x8) == 0x8) - GetTelemetryData(fd, strCtrlDirName); + GetTelemetryData(dev_fd(dev), strCtrlDirName); - GetFeatureSettings(fd, strCtrlDirName); + GetFeatureSettings(dev_fd(dev), strCtrlDirName); if (eModel != M5410 && eModel != M5407) { memcpy(&aVendorLogs[c_logs_index], aM51XXLogs, sizeof(aM51XXLogs)); @@ -3221,15 +3239,18 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, case 0xE4: case 0xE8: case 0xEA: - err = get_common_log(fd, aVendorLogs[i].ucLogPage, &dataBuffer, &bSize); + err = get_common_log(dev_fd(dev), aVendorLogs[i].ucLogPage, + &dataBuffer, &bSize); break; case 0xC1: case 0xC2: case 0xC4: - err = GetLogPageSize(fd, aVendorLogs[i].ucLogPage, &bSize); + err = GetLogPageSize(dev_fd(dev), aVendorLogs[i].ucLogPage, + &bSize); if (err == 0 && bSize > 0) - err = GetCommonLogPage(fd, aVendorLogs[i].ucLogPage, &dataBuffer, bSize); + err = GetCommonLogPage(dev_fd(dev), aVendorLogs[i].ucLogPage, + &dataBuffer, bSize); break; case 0xE6: @@ -3248,9 +3269,12 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, if (bSize != 0 && (dataBuffer = (unsigned char *)malloc(bSize)) != NULL) { memset(dataBuffer, 0, bSize); if (eModel == M5410 || eModel == M5407) - err = NVMEGetLogPage(fd, aVendorLogs[i].ucLogPage, dataBuffer, bSize); + err = NVMEGetLogPage(dev_fd(dev), + aVendorLogs[i].ucLogPage, dataBuffer, + bSize); else - err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage, + err = nvme_get_log_simple(dev_fd(dev), + aVendorLogs[i].ucLogPage, bSize, dataBuffer); } break; @@ -3260,7 +3284,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, case 0xFC: case 0xFD: if (eModel == M51BX) { - (void)NVMEResetLog(fd, aVendorLogs[i].ucLogPage, + (void)NVMEResetLog(dev_fd(dev), aVendorLogs[i].ucLogPage, aVendorLogs[i].nLogSize, aVendorLogs[i].nMaxSize); } /* fallthrough */ @@ -3271,13 +3295,14 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, break; } memset(dataBuffer, 0, bSize); - err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage, + err = nvme_get_log_simple(dev_fd(dev), aVendorLogs[i].ucLogPage, bSize, dataBuffer); maxSize = aVendorLogs[i].nMaxSize - bSize; while (err == 0 && maxSize > 0 && ((unsigned int *)dataBuffer)[0] != 0xdeadbeef) { sprintf(msg, "log 0x%x", aVendorLogs[i].ucLogPage); WriteData(dataBuffer, bSize, strCtrlDirName, aVendorLogs[i].strFileName, msg); - err = nvme_get_log_simple(fd, aVendorLogs[i].ucLogPage, + err = nvme_get_log_simple(dev_fd(dev), + aVendorLogs[i].ucLogPage, bSize, dataBuffer); if (err || (((unsigned int *)dataBuffer)[0] == 0xdeadbeef)) break; @@ -3299,7 +3324,7 @@ static int micron_internal_logs(int argc, char **argv, struct command *cmd, err = ZipAndRemoveDir(strMainDirName, cfg.package); out: - close(fd); + dev_close(dev); return err; } @@ -3308,17 +3333,18 @@ static int micron_logpage_dir(int argc, char **argv, struct command *cmd, struct plugin *plugin) { int err = -1; - int fd = -1; const char *desc = "List the supported log pages"; eDriveModel model = UNKNOWN_MODEL; char logbuf[MIN_LOG_SIZE]; + struct nvme_dev *dev; int i; OPT_ARGS(opts) = { OPT_END() }; - if ((fd = micron_parse_options(argc, argv, desc, opts, &model)) < 0) + err = micron_parse_options(&dev, argc, argv, desc, opts, &model); + if (err < 0) return err; struct nvme_supported_logs { @@ -3359,7 +3385,7 @@ static int micron_logpage_dir(int argc, char **argv, struct command *cmd, printf("Supported log page list\nLog ID : Description\n"); for (i = 0; i < sizeof(log_list)/sizeof(log_list[0]); i++) { - err = nvme_get_log_simple(fd, log_list[i].log_id, + err = nvme_get_log_simple(dev_fd(dev), log_list[i].log_id, MIN_LOG_SIZE, &logbuf[0]); if (err) continue; printf("%02Xh : %s\n", log_list[i].log_id, log_list[i].desc); diff --git a/plugins/netapp/netapp-nvme.c b/plugins/netapp/netapp-nvme.c index b6bd3f6..f5cb073 100644 --- a/plugins/netapp/netapp-nvme.c +++ b/plugins/netapp/netapp-nvme.c @@ -22,7 +22,6 @@ #include <unistd.h> #include <errno.h> #include <string.h> -#include <uuid/uuid.h> #include "common.h" #include "nvme.h" @@ -68,7 +67,7 @@ struct ontapdevice_info { unsigned nsid; struct nvme_id_ctrl ctrl; struct nvme_id_ns ns; - uuid_t uuid; + unsigned char uuid[NVME_UUID_LEN]; unsigned char log_data[ONTAP_C2_LOG_SIZE]; char dev[265]; }; @@ -334,7 +333,7 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices, for (i = 0; i < count; i++) { netapp_get_ns_size(size, &lba, &devices[i].ns); - uuid_unparse_lower(devices[i].uuid, uuid_str); + nvme_uuid_to_string(devices[i].uuid, uuid_str); netapp_get_ontap_labels(vsname, nspath, devices[i].log_data); if (format == NJSON) { diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c index 52c28a8..5cbf6cb 100644 --- a/plugins/ocp/ocp-nvme.c +++ b/plugins/ocp/ocp-nvme.c @@ -13,12 +13,14 @@ #include <limits.h> #include <fcntl.h> #include <unistd.h> +#include <time.h> #include "common.h" #include "nvme.h" #include "libnvme.h" #include "plugin.h" #include "linux/types.h" +#include "util/types.h" #include "nvme-print.h" #define CREATE_CMD @@ -122,18 +124,6 @@ struct __attribute__((__packed__)) ssd_latency_monitor_log { __u8 log_page_guid[0x10]; /* 0x1F0 */ }; -static long double int128_to_double(__u8 *data) -{ - int i; - long double result = 0; - - for (i = 0; i < 16; i++) { - result *= 256; - result += data[15 - i]; - } - return result; -} - static int convert_ts(time_t time, char *ts_buf) { struct tm gmTimeInfo; @@ -208,10 +198,10 @@ static void ocp_print_C0_log_normal(void *data) (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); printf(" NUSE - Namespace utilization %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); - printf(" PLP start count %.0Lf\n", - int128_to_double(&log_data[SCAO_PSC])); - printf(" Endurance estimate %.0Lf\n", - int128_to_double(&log_data[SCAO_EEST])); + printf(" PLP start count %s\n", + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PSC]))); + printf(" Endurance estimate %s\n", + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_EEST]))); smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); printf(" Log page version %"PRIu16"\n",smart_log_ver); printf(" Log page GUID 0x"); @@ -300,10 +290,10 @@ static void ocp_print_C0_log_json(void *data) (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); json_object_add_value_uint64(root, "NUSE - Namespace utilization", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); - json_object_add_value_uint(root, "PLP start count", - int128_to_double(&log_data[SCAO_PSC])); - json_object_add_value_uint64(root, "Endurance estimate", - int128_to_double(&log_data[SCAO_EEST])); + json_object_add_value_uint128(root, "PLP start count", + le128_to_cpu(&log_data[SCAO_PSC])); + json_object_add_value_uint128(root, "Endurance estimate", + le128_to_cpu(&log_data[SCAO_EEST])); smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); json_object_add_value_uint(root, "Log page version", smart_log_ver); char guid[40]; @@ -401,7 +391,7 @@ static int ocp_smart_add_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Retrieve latency monitor log data."; - int fd; + struct nvme_dev *dev; int ret = 0; struct config { @@ -417,22 +407,23 @@ static int ocp_smart_add_log(int argc, char **argv, struct command *cmd, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; - ret = get_c0_log_page(fd, cfg.output_format); + ret = get_c0_log_page(dev_fd(dev), cfg.output_format); if (ret) fprintf(stderr, "ERROR : OCP : Failure reading the C0 Log Page, ret = %d\n", ret); - close(fd); + dev_close(dev); return ret; } -static int ocp_print_C3_log_normal(struct ssd_latency_monitor_log *log_data) +static int ocp_print_C3_log_normal(struct nvme_dev *dev, + struct ssd_latency_monitor_log *log_data) { printf("-Latency Monitor/C3 Log Page Data- \n"); - printf(" Controller : %s\n", devicename); + printf(" Controller : %s\n", dev->name); int i, j; int pos = 0; char ts_buf[128]; @@ -662,7 +653,7 @@ static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_data) json_free_object(root); } -static int get_c3_log_page(int fd, char *format) +static int get_c3_log_page(struct nvme_dev *dev, char *format) { int ret = 0; int fmt = -1; @@ -682,8 +673,8 @@ static int get_c3_log_page(int fd, char *format) } memset(data, 0, sizeof (__u8) * C3_LATENCY_MON_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, C3_LATENCY_MON_OPCODE, - C3_LATENCY_MON_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), C3_LATENCY_MON_OPCODE, + C3_LATENCY_MON_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, @@ -725,7 +716,7 @@ static int get_c3_log_page(int fd, char *format) switch (fmt) { case NORMAL: - ocp_print_C3_log_normal(log_data); + ocp_print_C3_log_normal(dev, log_data); break; case JSON: ocp_print_C3_log_json(log_data); @@ -745,7 +736,7 @@ static int ocp_latency_monitor_log(int argc, char **argv, struct command *comman struct plugin *plugin) { const char *desc = "Retrieve latency monitor log data."; - int fd; + struct nvme_dev *dev; int ret = 0; struct config { @@ -762,15 +753,15 @@ static int ocp_latency_monitor_log(int argc, char **argv, struct command *comman OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; - ret = get_c3_log_page(fd, cfg.output_format); + ret = get_c3_log_page(dev, cfg.output_format); if (ret) fprintf(stderr, "ERROR : OCP : Failure reading the C3 Log Page, ret = %d\n", ret); - close(fd); + dev_close(dev); return ret; } diff --git a/plugins/scaleflux/sfx-nvme.c b/plugins/scaleflux/sfx-nvme.c index 0740e43..a776664 100644 --- a/plugins/scaleflux/sfx-nvme.c +++ b/plugins/scaleflux/sfx-nvme.c @@ -398,17 +398,18 @@ static void show_sfx_smart_log(struct nvme_additional_smart_log *smart, static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_additional_smart_log smart_log; - int err, fd; char *desc = "Get ScaleFlux vendor specific additional smart log (optionally, "\ "for the specified namespace), 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_dev *dev; struct config { __u32 namespace_id; bool raw_binary; bool json; }; + int err; struct config cfg = { .namespace_id = 0xffffffff, @@ -422,24 +423,25 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - return fd; - } + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id, - sizeof(smart_log), (void *)&smart_log); + err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, + sizeof(smart_log), (void *)&smart_log); if (!err) { if (cfg.json) - show_sfx_smart_log_jsn(&smart_log, cfg.namespace_id, devicename); + show_sfx_smart_log_jsn(&smart_log, cfg.namespace_id, + dev->name); else if (!cfg.raw_binary) - show_sfx_smart_log(&smart_log, cfg.namespace_id, devicename); + show_sfx_smart_log(&smart_log, cfg.namespace_id, + dev->name); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -609,22 +611,23 @@ static void show_lat_stats_myrtle(struct sfx_lat_stats_myrtle *stats, int write) for (i = 0; i < 64; i++) printf("Bucket %2d: %u\n", i, stats->bucket_19[i]); - printf("\nAverage latency statistics %lld\n", stats->average); + printf("\nAverage latency statistics %" PRIu64 "\n", + (uint64_t)stats->average); } static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct sfx_lat_stats stats; - int err, fd; - char *desc = "Get ScaleFlux Latency Statistics log and show it."; const char *raw = "dump output in binary format"; const char *write = "Get write statistics (read default)"; + struct nvme_dev *dev; struct config { bool raw_binary; bool write; }; + int err; struct config cfg = { }; @@ -635,12 +638,12 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - return fd; - } + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - err = nvme_get_log_simple(fd, cfg.write ? 0xc3 : 0xc1, sizeof(stats), (void *)&stats); + err = nvme_get_log_simple(dev_fd(dev), cfg.write ? 0xc3 : 0xc1, + sizeof(stats), (void *)&stats); if (!err) { if ((stats.ver.maj == VANDA_MAJOR_IDX) && (stats.ver.min == VANDA_MINOR_IDX)) { if (!cfg.raw_binary) { @@ -660,7 +663,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct } } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -764,9 +767,9 @@ static void bd_table_show(unsigned char *bd_table, __u64 table_size) */ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int fd; - unsigned char *data_buf; const __u64 buf_size = 256*4096*sizeof(unsigned char); + unsigned char *data_buf; + struct nvme_dev *dev; int err = 0; char *desc = "Get bad block table of sfx block device."; @@ -775,19 +778,18 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - return fd; - } + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; data_buf = malloc(buf_size); if (!data_buf) { fprintf(stderr, "malloc fail, errno %d\r\n", errno); - close(fd); + dev_close(dev); return -1; } - err = get_bb_table(fd, 0xffffffff, data_buf, buf_size); + err = get_bb_table(dev_fd(dev), 0xffffffff, data_buf, buf_size); if (err < 0) { perror("get-bad-block"); } else if (err != 0) { @@ -798,7 +800,7 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct } free(data_buf); - close(fd); + dev_close(dev); return 0; } @@ -819,25 +821,25 @@ static void show_cap_info(struct sfx_freespace_ctx *ctx) static int query_cap_info(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct sfx_freespace_ctx ctx = { 0 }; - int err = 0, fd; char *desc = "query current capacity info"; const char *raw = "dump output in binary format"; + struct nvme_dev *dev; struct config { bool raw_binary; }; struct config cfg; + int err = 0; OPT_ARGS(opts) = { OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw), OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - return fd; - } + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - if (nvme_query_cap(fd, 0xffffffff, sizeof(ctx), &ctx)) { + if (nvme_query_cap(dev_fd(dev), 0xffffffff, sizeof(ctx), &ctx)) { perror("sfx-query-cap"); err = -1; } @@ -849,7 +851,7 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu d_raw((unsigned char *)&ctx, sizeof(ctx)); } } - close(fd); + dev_close(dev); return err; } @@ -939,14 +941,15 @@ static int sfx_confirm_change(const char *str) static int change_cap(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err = -1, fd; char *desc = "dynamic change capacity"; const char *cap_gb = "cap size in GB"; const char *cap_byte = "cap size in byte"; const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command"; + struct nvme_dev *dev; __u64 cap_in_4k = 0; __u64 cap_in_sec = 0; int shrink = 0; + int err = -1; struct config { __u64 cap_in_byte; @@ -967,10 +970,9 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - return fd; - } + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; cap_in_sec = IDEMA_CAP(cfg.capacity_in_gb); cap_in_4k = cap_in_sec >> 3; @@ -979,27 +981,27 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin printf("%dG %"PRIu64"B %"PRIu64" 4K\n", cfg.capacity_in_gb, (uint64_t)cfg.cap_in_byte, (uint64_t)cap_in_4k); - if (change_sanity_check(fd, cap_in_4k, &shrink)) { + if (change_sanity_check(dev_fd(dev), cap_in_4k, &shrink)) { printf("ScaleFlux change-capacity: fail\n"); - close(fd); + dev_close(dev); return err; } if (!cfg.force && shrink && !sfx_confirm_change("Changing Cap may irrevocably delete this device's data")) { - close(fd); + dev_close(dev); return 0; } - err = nvme_change_cap(fd, 0xffffffff, cap_in_4k); + err = nvme_change_cap(dev_fd(dev), 0xffffffff, cap_in_4k); if (err < 0) perror("sfx-change-cap"); else if (err != 0) nvme_show_status(err); else { printf("ScaleFlux change-capacity: success\n"); - ioctl(fd, BLKRRPART); + ioctl(dev_fd(dev), BLKRRPART); } - close(fd); + dev_close(dev); return err; } @@ -1051,7 +1053,6 @@ char *sfx_feature_to_string(int feature) static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err = 0, fd; char *desc = "ScaleFlux internal set features\n" "feature id 1: ATOMIC\n" "value 0: Disable atomic write\n" @@ -1060,8 +1061,9 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl const char *feature_id = "hex feature name (required)"; const char *namespace_id = "desired namespace"; const char *force = "The \"I know what I'm doing\" flag, skip confirmation before sending command"; - + struct nvme_dev *dev; struct nvme_id_ns ns; + int err = 0; struct config { __u32 namespace_id; @@ -1084,37 +1086,37 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - return fd; - } + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - close(fd); + dev_close(dev); return EINVAL; } if (cfg.feature_id == SFX_FEAT_CLR_CARD) { /*Warning for clean card*/ if (!cfg.force && !sfx_confirm_change("Going to clean device's data, confirm umount fs and try again")) { - close(fd); + dev_close(dev); return 0; } else { - return sfx_clean_card(fd); + return sfx_clean_card(dev_fd(dev)); } } if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value != 0) { if (cfg.namespace_id != 0xffffffff) { - err = nvme_identify_ns(fd, cfg.namespace_id, &ns); + err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id, + &ns); if (err) { if (err < 0) perror("identify-namespace"); else nvme_show_status(err); - close(fd); + dev_close(dev); return err; } /* @@ -1122,29 +1124,31 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl */ if ((ns.flbas & 0xf) != 1) { printf("Please change-sector size to 4K, then retry\n"); - close(fd); + dev_close(dev); return EFAULT; } } } else if (cfg.feature_id == SFX_FEAT_UP_P_CAP) { if (cfg.value <= 0) { fprintf(stderr, "Invalid Param\n"); - close(fd); + dev_close(dev); return EINVAL; } /*Warning for change pacp by GB*/ if (!cfg.force && !sfx_confirm_change("Changing physical capacity may irrevocably delete this device's data")) { - close(fd); + dev_close(dev); return 0; } } - err = nvme_sfx_set_features(fd, cfg.namespace_id, cfg.feature_id, cfg.value); + err = nvme_sfx_set_features(dev_fd(dev), cfg.namespace_id, + cfg.feature_id, + cfg.value); if (err < 0) { perror("ScaleFlux-set-feature"); - close(fd); + dev_close(dev); return errno; } else if (!err) { printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id, @@ -1152,18 +1156,19 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err = 0, fd; char *desc = "ScaleFlux internal set features\n" "feature id 1: ATOMIC"; const char *feature_id = "hex feature name (required)"; const char *namespace_id = "desired namespace"; + struct nvme_dev *dev; __u32 result = 0; + int err = 0; struct config { __u32 namespace_id; @@ -1180,21 +1185,21 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - return fd; - } + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - close(fd); + dev_close(dev); return EINVAL; } - err = nvme_sfx_get_features(fd, cfg.namespace_id, cfg.feature_id, &result); + err = nvme_sfx_get_features(dev_fd(dev), cfg.namespace_id, + cfg.feature_id, &result); if (err < 0) { perror("ScaleFlux-get-feature"); - close(fd); + dev_close(dev); return errno; } else if (!err) { printf("ScaleFlux get-feature:%02x (%s), value:%d\n", cfg.feature_id, @@ -1202,7 +1207,7 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } diff --git a/plugins/seagate/seagate-diag.h b/plugins/seagate/seagate-diag.h index 139901d..39f0d39 100644 --- a/plugins/seagate/seagate-diag.h +++ b/plugins/seagate/seagate-diag.h @@ -18,6 +18,8 @@ * * \file seagate-diag.h * \brief This file defines the functions and macros to make building a nvme-cli seagate plug-in. + * + * Author: Debabrata Bardhan <debabrata.bardhan@seagate.com> */ @@ -25,19 +27,66 @@ #define SEAGATE_NVME_H #define SEAGATE_PLUGIN_VERSION_MAJOR 1 -#define SEAGATE_PLUGIN_VERSION_MINOR 1 +#define SEAGATE_PLUGIN_VERSION_MINOR 2 + +#define SEAGATE_OCP_PLUGIN_VERSION_MAJOR 1 +#define SEAGATE_OCP_PLUGIN_VERSION_MINOR 0 #define PERSIST_FILE_SIZE (2764800) #define ONE_MB (1048576) /* (1024 * 1024) */ #define PERSIST_CHUNK (65536) /* (1024 * 64) */ #define FOUR_KB (4096) +#define STX_NUM_LEGACY_DRV (123) + + +const char* stx_jag_pan_mn[STX_NUM_LEGACY_DRV] = {"ST1000KN0002", "ST1000KN0012", "ST2000KN0002", + "ST2000KN0012", "ST4000KN0002", "XP1600HE10002", + "XP1600HE10012", "XP1600HE30002", "XP1600HE30012", + "XP1920LE10002", "XP1920LE10012", "XP1920LE30002", + "XP1920LE30012", "XP3200HE10002", "XP3200HE10012", + "XP3840LE10002", "XP3840LE10012", "XP400HE30002", + "XP400HE30012", "XP400HE30022", "XP400HE30032", + "XP480LE30002", "XP480LE30012", "XP480LE30022", + "XP480LE30032", "XP800HE10002", "XP800HE10012", + "XP800HE30002", "XP800HE30012", "XP800HE30022", + "XP800HE30032", "XP960LE10002", "XP960LE10012", + "XP960LE30002", "XP960LE30012", "XP960LE30022", + "XP960LE30032", "XP256LE30011", "XP256LE30021", + "XP7680LE80002", "XP7680LE80003", "XP15360LE80003", + "XP30720LE80003", "XP7200-1A2048", "XP7200-1A4096", + "XP7201-2A2048", "XP7201-2A4096", "XP7200-1A8192", + "ST1000HM0021", "ST1000HM0031", "ST1000HM0061", + "ST1000HM0071", "ST1000HM0081", "ST1200HM0001", + "ST1600HM0031", "ST1800HM0001", "ST1800HM0011", + "ST2000HM0011", "ST2000HM0031", "ST400HM0061", + "ST400HM0071", "ST500HM0021", "ST500HM0031", + "ST500HM0061", "ST500HM0071", "ST500HM0081", + "ST800HM0061", "ST800HM0071", "ST1600HM0011", + "ST1600KN0001", "ST1600KN0011", "ST1920HM0001", + "ST1920KN0001", "ST1920KN0011", "ST400HM0021", + "ST400KN0001", "ST400KN0011", "ST480HM0001", + "ST480KN0001", "ST480KN0011", "ST800HM0021", + "ST800KN0001", "ST800KN0011", "ST960HM0001", + "ST960KN0001", "ST960KN0011", "XF1441-1AA251024", + "XF1441-1AA252048", "XF1441-1AA25512", "XF1441-1AB251024", + "XF1441-1AB252048", "XF1441-1AB25512", "XF1441-1BA251024", + "XF1441-1BA252048", "XF1441-1BA25512", "XF1441-1BB251024", + "XF1441-1BB252048", "XF1441-1BB25512", "ST400HM0031", + "ST400KN0021", "ST400KN0031", "ST480HM0011", + "ST480KN0021", "ST480KN0031", "ST800HM0031", + "ST800KN0021", "ST800KN0031", "ST960HM0011", + "ST960KN0021", "ST960KN0031", "XM1441-1AA111024", + "XM1441-1AA112048", "XM1441-1AA11512", "XM1441-1AA801024", + "XM1441-1AA80512", "XM1441-1AB111024", "XM1441-1AB112048", + "XM1441-1BA111024", "XM1441-1BA112048", "XM1441-1BA11512", + "XM1441-1BA801024", "XM1441-1BA80512", "XM1441-1BB112048"}; /*************************** *Supported Log-Pages from FW ***************************/ -typedef struct log_page_map_entry { +typedef struct __attribute__((__packed__)) log_page_map_entry { __u32 LogPageID; __u32 LogPageSignature; __u32 LogPageVersion; @@ -45,7 +94,7 @@ typedef struct log_page_map_entry { #define MAX_SUPPORTED_LOG_PAGE_ENTRIES ((4096 - sizeof(__u32)) / sizeof(log_page_map_entry)) -typedef struct log_page_map { +typedef struct __attribute__((__packed__)) log_page_map { __u32 NumLogPages; log_page_map_entry LogPageEntry[ MAX_SUPPORTED_LOG_PAGE_ENTRIES ]; } log_page_map; @@ -55,7 +104,6 @@ typedef struct log_page_map { /*************************** * Extended-SMART Information ***************************/ -#pragma pack(1) #define NUMBER_EXTENDED_SMART_ATTRIBUTES 42 typedef enum _EXTENDED_SMART_VERSION_ @@ -65,7 +113,7 @@ typedef enum _EXTENDED_SMART_VERSION_ EXTENDED_SMART_VERSION_VENDOR1, } EXTENDED_SMART_VERSION; -typedef struct _SmartVendorSpecific +typedef struct __attribute__((__packed__)) _SmartVendorSpecific { __u8 AttributeNumber; __u16 SmartStatus; @@ -75,22 +123,22 @@ typedef struct _SmartVendorSpecific __u8 RawHigh[3]; } SmartVendorSpecific; -typedef struct _EXTENDED_SMART_INFO_T +typedef struct __attribute__((__packed__)) _EXTENDED_SMART_INFO_T { __u16 Version; SmartVendorSpecific vendorData[NUMBER_EXTENDED_SMART_ATTRIBUTES]; __u8 vendor_specific_reserved[6]; } EXTENDED_SMART_INFO_T; -typedef struct vendor_smart_attribute_data +typedef struct __attribute__((__packed__)) vendor_smart_attribute_data { - __u8 AttributeNumber; /* 00 */ - __u8 Rsvd[3]; /* 01 -03 */ - __u32 LSDword; /* 04-07 */ - __u32 MSDword; /* 08 - 11 */ + __u8 AttributeNumber; + __u8 Rsvd[3]; + __u32 LSDword; + __u32 MSDword; } vendor_smart_attribute_data; -struct nvme_temetry_log_hdr +struct __attribute__((__packed__)) nvme_temetry_log_hdr { __u8 log_id; __u8 rsvd1[4]; @@ -104,38 +152,75 @@ struct nvme_temetry_log_hdr __u8 reason_identifier[128]; }; -typedef struct _U128 +typedef struct __attribute__((__packed__)) _U128 { __u64 LS__u64; __u64 MS__u64; } U128; -typedef struct _vendor_log_page_CF_Attr +typedef struct __attribute__((__packed__)) _vendor_log_page_CF_Attr { - __u16 SuperCapCurrentTemperature; /* 00-01 */ - __u16 SuperCapMaximumTemperature; /* 02-03 */ - __u8 SuperCapStatus; /* 04 */ - __u8 Reserved5to7[3]; /* 05-07 */ - U128 DataUnitsReadToDramNamespace; /* 08-23 */ - U128 DataUnitsWrittenToDramNamespace; /* 24-39 */ - __u64 DramCorrectableErrorCount; /* 40-47 */ - __u64 DramUncorrectableErrorCount; /* 48-55 */ -}vendor_log_page_CF_Attr; - -typedef struct _vendor_log_page_CF + __u16 SuperCapCurrentTemperature; + __u16 SuperCapMaximumTemperature; + __u8 SuperCapStatus; + __u8 Reserved5to7[3]; + U128 DataUnitsReadToDramNamespace; + U128 DataUnitsWrittenToDramNamespace; + __u64 DramCorrectableErrorCount; + __u64 DramUncorrectableErrorCount; +} vendor_log_page_CF_Attr; + +typedef struct __attribute__((__packed__)) _vendor_log_page_CF { vendor_log_page_CF_Attr AttrCF; __u8 Vendor_Specific_Reserved[ 456 ]; /* 56-511 */ -}vendor_log_page_CF; +} vendor_log_page_CF; + +typedef struct __attribute__((__packed__)) _STX_EXT_SMART_LOG_PAGE_C0 +{ + U128 phyMediaUnitsWrt; + U128 phyMediaUnitsRd; + __u64 badUsrNandBlocks; + __u64 badSysNandBlocks; + __u64 xorRecoveryCnt; + __u64 ucRdEc; + __u64 softEccEc; + __u64 etoeCrrCnt; + __u64 sysDataUsed : 8; + __u64 refreshCount : 56; + __u64 usrDataEraseCnt; + __u16 thermalThrottling; + __u8 dssdSpecVerErrata; + __u16 dssdSpecVerPoint; + __u16 dssdSpecVerMinor; + __u8 dssdSpecVerMajor; + __u64 pcieCorrEc; + __u32 incompleteShutdowns; + __u32 rsvd_116_119; + __u8 freeBlocks; + __u8 rsvd_121_127[7]; + __u16 capHealth; + __u8 nvmeErrataVer; + __u8 rsvd_131_135[5]; + __u64 unalignedIO; + __u64 secVerNum; + __u64 totalNUSE; + U128 plpStartCnt; + U128 enduranceEstimate; + __u64 pcieLinkRetCnt; + __u64 powStateChangeCnt; + __u8 rsvd_208_493[286]; + __u16 logPageVer; + U128 logPageGUID; +} STX_EXT_SMART_LOG_PAGE_C0; -#pragma pack() /* EOF Extended-SMART Information*/ /************************** * PCIE ERROR INFORMATION **************************/ -typedef struct pcie_error_log_page +typedef struct __attribute__((__packed__)) pcie_error_log_page { __u32 Version; __u32 BadDllpErrCnt; @@ -159,53 +244,86 @@ typedef struct pcie_error_log_page } pcie_error_log_page; /*EOF PCIE ERROR INFORMATION */ +/************************************** +* FW Activation History Log INFORMATION +***************************************/ + +typedef struct __attribute__((__packed__)) _stx_fw_activ_his_ele +{ + __u8 entryVerNum; + __u8 entryLen; + __u16 rev02_03; + __u16 fwActivCnt; + __u64 timeStamp; + __u64 rev14_21; + __u64 powCycleCnt; + __u8 previousFW[8]; + __u8 newFW[8]; + __u8 slotNum; + __u8 commitActionType; + __u16 result; + __u8 rev50_63[14]; +} stx_fw_activ_his_ele; + +typedef struct __attribute__((__packed__)) _stx_fw_activ_history_log_page +{ + __u8 logID; + __u8 rev01_03[3]; + __u32 numValidFwActHisEnt; + stx_fw_activ_his_ele fwActHisEnt[20]; + __u8 rev1288_4077[2790]; + __u16 logPageVer; + __u8 logPageGUID[16]; +} stx_fw_activ_history_log_page; + +/* FW Activation History Log INFORMATION */ + + typedef enum { - VS_ATTR_SOFT_READ_ERROR_RATE, /* 0 OFFSET : 02 -13 bytes */ - VS_ATTR_REALLOCATED_SECTOR_COUNT, /* 1 OFFSET : 14 -25 bytes */ - VS_ATTR_POWER_ON_HOURS, /* 2 OFFSET : 26 -37 bytes */ + VS_ATTR_SOFT_READ_ERROR_RATE, /* 0 OFFSET : 02 -13 bytes */ + VS_ATTR_REALLOCATED_SECTOR_COUNT, /* 1 OFFSET : 14 -25 bytes */ + VS_ATTR_POWER_ON_HOURS, /* 2 OFFSET : 26 -37 bytes */ VS_ATTR_POWER_FAIL_EVENT_COUNT, /* 3 OFFSET : 38 -49 bytes */ VS_ATTR_DEVICE_POWER_CYCLE_COUNT, /* 4 OFFSET : 50 -61 bytes */ - VS_ATTR_GB_ERASED, /* 5 OFFSET : 62 -73 bytes */ + VS_ATTR_GB_ERASED, /* 5 OFFSET : 62 -73 bytes */ VS_ATTR_LIFETIME_DEVSLEEP_EXIT_COUNT, /* 6 OFFSET : 74 -85 bytes */ - VS_ATTR_LIFETIME_ENTERING_PS4_COUNT, /* 7 OFFSET : 86 -97 bytes */ - VS_ATTR_LIFETIME_ENTERING_PS3_COUNT, /* 8 OFFSET : 98 -109 bytes */ - VS_ATTR_RETIRED_BLOCK_COUNT, /* 9 OFFSET : 110 -121 bytes */ - VS_ATTR_PROGRAM_FAILURE_COUNT, /* 10 OFFSET : 122 -133 bytes */ - VS_ATTR_ERASE_FAIL_COUNT, /* 11 OFFSET : 134 -145 bytes */ - VS_ATTR_AVG_ERASE_COUNT, /* 12 OFFSET : 146 -157 bytes */ - VS_ATTR_UNEXPECTED_POWER_LOSS_COUNT, /* 13 OFFSET : 158 -169 bytes */ - VS_ATTR_WEAR_RANGE_DELTA, /* 14 OFFSET : 170 -181 bytes */ - VS_ATTR_SATA_INTERFACE_DOWNSHIFT_COUNT, /* 15 OFFSET : 182 -193 bytes */ - VS_ATTR_END_TO_END_CRC_ERROR_COUNT, /* 16 OFFSET : 194 -205 bytes */ - VS_ATTR_MAX_LIFE_TEMPERATURE, /* 17 OFFSET : 206 -217 bytes */ - VS_ATTR_UNCORRECTABLE_RAISE_ERRORS, /* 18 OFFSET : 218 -229 bytes */ - VS_ATTR_DRIVE_LIFE_PROTECTION_STATUS, /* 19 OFFSET : 230 -241 bytes */ - VS_ATTR_REMAINING_SSD_LIFE, /* 20 OFFSET : 242 -253 bytes */ - VS_ATTR_LIFETIME_WRITES_TO_FLASH, /* 21 OFFSET : 254 -265 bytes */ - VS_ATTR_LIFETIME_WRITES_FROM_HOST, /* 22 OFFSET : 266 -277 bytes */ - VS_ATTR_LIFETIME_READS_TO_HOST, /* 23 OFFSET : 278 -289 bytes */ - VS_ATTR_FREE_SPACE, /* 24 OFFSET : 290 -301 bytes */ - VS_ATTR_TRIM_COUNT_LSB, /* 25 OFFSET : 302 -313 bytes */ - VS_ATTR_TRIM_COUNT_MSB, /* 26 OFFSET : 314 -325 bytes */ - VS_ATTR_OP_PERCENTAGE, /* 27 OFFSET : 326 -337 bytes */ - VS_ATTR_RAISE_ECC_CORRECTABLE_ERROR_COUNT, /* 28 OFFSET : 338 -349 bytes */ - VS_ATTR_UNCORRECTABLE_ECC_ERRORS , /* 29 OFFSET : 350 -361 bytes */ - VS_ATTR_LIFETIME_WRITES0_TO_FLASH, /* 30 362-372 */ - VS_ATTR_LIFETIME_WRITES1_TO_FLASH, /* 31 374-385 */ - VS_ATTR_LIFETIME_WRITES0_FROM_HOST, /* 32 386-397 */ - VS_ATTR_LIFETIME_WRITES1_FROM_HOST, /* 33 398-409 */ - VS_ATTR_LIFETIME_READ0_FROM_HOST, /* 34 410-421 */ - VS_ATTR_LIFETIME_READ1_FROM_HOST, /* 35 422-433 */ - VS_ATTR_PCIE_PHY_CRC_ERROR, /* 36 434-445 */ - VS_ATTR_BAD_BLOCK_COUNT_SYSTEM, /* 37 446-457 */ - VS_ATTR_BAD_BLOCK_COUNT_USER, /* 38 458-469 */ - VS_ATTR_THERMAL_THROTTLING_STATUS, /* 39 470-481 */ - VS_ATTR_POWER_CONSUMPTION, /* 40 482-493 */ - VS_ATTR_MAX_SOC_LIFE_TEMPERATURE, /* 41 494-505 */ - - VS_MAX_ATTR_NUMBER, - + VS_ATTR_LIFETIME_ENTERING_PS4_COUNT, /* 7 OFFSET : 86 -97 bytes */ + VS_ATTR_LIFETIME_ENTERING_PS3_COUNT, /* 8 OFFSET : 98 -109 bytes */ + VS_ATTR_RETIRED_BLOCK_COUNT, /* 9 OFFSET : 110 -121 bytes */ + VS_ATTR_PROGRAM_FAILURE_COUNT, /* 10 OFFSET : 122 -133 bytes */ + VS_ATTR_ERASE_FAIL_COUNT, /* 11 OFFSET : 134 -145 bytes */ + VS_ATTR_AVG_ERASE_COUNT, /* 12 OFFSET : 146 -157 bytes */ + VS_ATTR_UNEXPECTED_POWER_LOSS_COUNT, /* 13 OFFSET : 158 -169 bytes */ + VS_ATTR_WEAR_RANGE_DELTA, /* 14 OFFSET : 170 -181 bytes */ + VS_ATTR_SATA_INTERFACE_DOWNSHIFT_COUNT, /* 15 OFFSET : 182 -193 bytes */ + VS_ATTR_END_TO_END_CRC_ERROR_COUNT, /* 16 OFFSET : 194 -205 bytes */ + VS_ATTR_MAX_LIFE_TEMPERATURE, /* 17 OFFSET : 206 -217 bytes */ + VS_ATTR_UNCORRECTABLE_RAISE_ERRORS, /* 18 OFFSET : 218 -229 bytes */ + VS_ATTR_DRIVE_LIFE_PROTECTION_STATUS, /* 19 OFFSET : 230 -241 bytes */ + VS_ATTR_REMAINING_SSD_LIFE, /* 20 OFFSET : 242 -253 bytes */ + VS_ATTR_LIFETIME_WRITES_TO_FLASH, /* 21 OFFSET : 254 -265 bytes */ + VS_ATTR_LIFETIME_WRITES_FROM_HOST, /* 22 OFFSET : 266 -277 bytes */ + VS_ATTR_LIFETIME_READS_TO_HOST, /* 23 OFFSET : 278 -289 bytes */ + VS_ATTR_FREE_SPACE, /* 24 OFFSET : 290 -301 bytes */ + VS_ATTR_TRIM_COUNT_LSB, /* 25 OFFSET : 302 -313 bytes */ + VS_ATTR_TRIM_COUNT_MSB, /* 26 OFFSET : 314 -325 bytes */ + VS_ATTR_OP_PERCENTAGE, /* 27 OFFSET : 326 -337 bytes */ + VS_ATTR_RAISE_ECC_CORRECTABLE_ERROR_COUNT, /* 28 OFFSET : 338 -349 bytes */ + VS_ATTR_UNCORRECTABLE_ECC_ERRORS , /* 29 OFFSET : 350 -361 bytes */ + VS_ATTR_LIFETIME_WRITES0_TO_FLASH, /* 30 OFFSET : 362-372 bytes */ + VS_ATTR_LIFETIME_WRITES1_TO_FLASH, /* 31 OFFSET : 374-385 bytes */ + VS_ATTR_LIFETIME_WRITES0_FROM_HOST, /* 32 OFFSET : 386-397 bytes */ + VS_ATTR_LIFETIME_WRITES1_FROM_HOST, /* 33 OFFSET : 398-409 bytes */ + VS_ATTR_LIFETIME_READ0_FROM_HOST, /* 34 OFFSET : 410-421 bytes */ + VS_ATTR_LIFETIME_READ1_FROM_HOST, /* 35 OFFSET : 422-433 bytes */ + VS_ATTR_PCIE_PHY_CRC_ERROR, /* 36 OFFSET : 434-445 bytes */ + VS_ATTR_BAD_BLOCK_COUNT_SYSTEM, /* 37 OFFSET : 446-457 bytes */ + VS_ATTR_BAD_BLOCK_COUNT_USER, /* 38 OFFSET : 458-469 bytes */ + VS_ATTR_THERMAL_THROTTLING_STATUS, /* 39 OFFSET : 470-481 bytes */ + VS_ATTR_POWER_CONSUMPTION, /* 40 OFFSET : 482-493 bytes */ + VS_ATTR_MAX_SOC_LIFE_TEMPERATURE, /* 41 OFFSET : 494-505 bytes */ + VS_MAX_ATTR_NUMBER } extended_smart_attributes; /*Smart attribute IDs */ diff --git a/plugins/seagate/seagate-nvme.c b/plugins/seagate/seagate-nvme.c index a527c0f..1bd30a5 100644 --- a/plugins/seagate/seagate-nvme.c +++ b/plugins/seagate/seagate-nvme.c @@ -18,6 +18,8 @@ * * \file seagate-nvme.c * \brief This file defines the functions and macros to make building a nvme-cli seagate plug-in. + * + * Author: Debabrata Bardhan <debabrata.bardhan@seagate.com> */ @@ -25,6 +27,7 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <inttypes.h> #include <sys/stat.h> @@ -35,6 +38,7 @@ #include "plugin.h" #include "linux/types.h" #include "nvme-print.h" +#include <time.h> #define CREATE_CMD @@ -43,11 +47,11 @@ /*************************************** -*Command for "log-pages-supp" -***************************************/ + * Command for "log-pages-supp" + ***************************************/ static char *log_pages_supp_print(__u32 pageID) { - switch(pageID) { + switch (pageID) { case 0x01: return "ERROR_INFORMATION"; break; @@ -126,6 +130,20 @@ static char *log_pages_supp_print(__u32 pageID) } } +static int stx_is_jag_pan(char *devMN) +{ + int match_found = 1; /* found = 0, not_found = 1 */ + + for (int i = 0; i < STX_NUM_LEGACY_DRV; i++) { + match_found = strncmp(devMN, stx_jag_pan_mn[i], strlen(stx_jag_pan_mn[i])); + if (match_found == 0) { + break; + } + } + + return match_found; +} + static void json_log_pages_supp(log_page_map *logPageMap) { @@ -147,19 +165,18 @@ static void json_log_pages_supp(log_page_map *logPageMap) json_array_add_value_object(logPages, lbaf); } json_print_object(root, NULL); - printf("\n"); json_free_object(root); } static int log_pages_supp(int argc, char **argv, struct command *cmd, - struct plugin *plugin) + struct plugin *plugin) { int err = 0; - int fd = 0; __u32 i = 0; log_page_map logPageMap; const char *desc = "Retrieve Seagate Supported Log-Page information for the given device "; const char *output_format = "output in binary format"; + struct nvme_dev *dev; int fmt; struct config { @@ -175,35 +192,36 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; - err = nvme_get_log_simple(fd, 0xc5, sizeof(logPageMap), &logPageMap); + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + err = nvme_get_log_simple(dev_fd(dev), 0xc5, + sizeof(logPageMap), &logPageMap); if (!err) { - if (strcmp(cfg.output_format,"json")) { + if (strcmp(cfg.output_format, "json")) { printf ("Seagate Supported Log-pages count :%d\n", le32_to_cpu(logPageMap.NumLogPages)); printf ("%-15s %-30s\n", "LogPage-Id", "LogPage-Name"); - for(fmt=0; fmt<45; fmt++) - printf ("-"); + for (fmt = 0; fmt < 45; fmt++) + printf("-"); printf("\n"); } else json_log_pages_supp(&logPageMap); - for (i = 0; i<le32_to_cpu(logPageMap.NumLogPages); i++) { - if (strcmp(cfg.output_format,"json")) { + for (i = 0; i < le32_to_cpu(logPageMap.NumLogPages); i++) { + if (strcmp(cfg.output_format, "json")) { printf("0x%-15X", - le32_to_cpu(logPageMap.LogPageEntry[i].LogPageID)); + le32_to_cpu(logPageMap.LogPageEntry[i].LogPageID)); printf("%-30s\n", - log_pages_supp_print(le32_to_cpu(logPageMap.LogPageEntry[i].LogPageID))); + log_pages_supp_print(le32_to_cpu(logPageMap.LogPageEntry[i].LogPageID))); } } } if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -215,7 +233,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd, ***************************************/ static char *print_ext_smart_id(__u8 attrId) { - switch(attrId) { + switch (attrId) { case VS_ATTR_ID_SOFT_READ_ERROR_RATE: return "Soft ECC error count"; break; @@ -280,7 +298,7 @@ static char *print_ext_smart_id(__u8 attrId) return "LIFETIME_ENTERING_PS3_COUNT"; break; case VS_ATTR_ID_RETIRED_BLOCK_COUNT: - return "Retired block count"; /*VS_ATTR_ID_RETIRED_BLOCK_COUNT*/ + return "Retired block count"; break; case VS_ATTR_ID_PROGRAM_FAILURE_COUNT: return "Program fail count"; @@ -307,13 +325,13 @@ static char *print_ext_smart_id(__u8 attrId) return "Uncorrectable Read Error Count"; break; case VS_ATTR_ID_MAX_LIFE_TEMPERATURE: - return "Max lifetime temperature";/*VS_ATTR_ID_MAX_LIFE_TEMPERATURE for extended*/ + return "Max lifetime temperature"; break; case VS_ATTR_ID_RAISE_ECC_CORRECTABLE_ERROR_COUNT: return "RAIS_ECC_CORRECT_ERR_COUNT"; break; case VS_ATTR_ID_UNCORRECTABLE_RAISE_ERRORS: - return "Uncorrectable RAISE error count";/*VS_ATTR_ID_UNCORRECTABLE_RAISE_ERRORS*/ + return "Uncorrectable RAISE error count"; break; case VS_ATTR_ID_DRIVE_LIFE_PROTECTION_STATUS: return "DRIVE_LIFE_PROTECTION_STATUS"; @@ -356,7 +374,7 @@ static char *print_ext_smart_id(__u8 attrId) break; default: return "Un-Known"; - } + } } static __u64 smart_attribute_vs(__u16 verNo, SmartVendorSpecific attr) @@ -435,9 +453,8 @@ static void print_smart_log(__u16 verNo, SmartVendorSpecific attr, int lastAttr) if ((attr.AttributeNumber != 0) && (hideAttr != 1)) { printf("%-40s", print_ext_smart_id(attr.AttributeNumber)); - printf("%-15d", attr.AttributeNumber ); - printf(" 0x%016"PRIx64"", (uint64_t)smart_attribute_vs(verNo, attr)); - printf("\n"); + printf("%-15d", attr.AttributeNumber); + printf(" 0x%016"PRIx64"\n", (uint64_t)smart_attribute_vs(verNo, attr)); } if (lastAttr == 1) { @@ -448,8 +465,7 @@ static void print_smart_log(__u16 verNo, SmartVendorSpecific attr, int lastAttr) printf("%-15d", VS_ATTR_ID_GB_ERASED_MSB << 8 | VS_ATTR_ID_GB_ERASED_LSB); sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbGbErased, (uint64_t)lsbGbErased); - printf(" %s", buf); - printf("\n"); + printf(" %s\n", buf); sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB) + 7)); printf("%-40s", strBuf); @@ -457,8 +473,7 @@ static void print_smart_log(__u16 verNo, SmartVendorSpecific attr, int lastAttr) printf("%-15d", VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB << 8 | VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB); sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbLifWrtToFlash, (uint64_t)lsbLifWrtToFlash); - printf(" %s", buf); - printf("\n"); + printf(" %s\n", buf); sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB) + 7)); printf("%-40s", strBuf); @@ -466,8 +481,7 @@ static void print_smart_log(__u16 verNo, SmartVendorSpecific attr, int lastAttr) printf("%-15d", VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB << 8 | VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB); sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbLifWrtFrmHost, (uint64_t)lsbLifWrtFrmHost); - printf(" %s", buf); - printf("\n"); + printf(" %s\n", buf); sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB) + 7)); printf("%-40s", strBuf); @@ -475,8 +489,7 @@ static void print_smart_log(__u16 verNo, SmartVendorSpecific attr, int lastAttr) printf("%-15d", VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB << 8 | VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB); sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbLifRdToHost, (uint64_t)lsbLifRdToHost); - printf(" %s", buf); - printf("\n"); + printf(" %s\n", buf); sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_TRIM_COUNT_LSB) + 7)); printf("%-40s", strBuf); @@ -484,16 +497,13 @@ static void print_smart_log(__u16 verNo, SmartVendorSpecific attr, int lastAttr) printf("%-15d", VS_ATTR_ID_TRIM_COUNT_MSB << 8 | VS_ATTR_ID_TRIM_COUNT_LSB); sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbTrimCnt, (uint64_t)lsbTrimCnt); - printf(" %s", buf); - printf("\n"); + printf(" %s\n", buf); } } -static void json_print_smart_log(struct json_object *root, - EXTENDED_SMART_INFO_T *ExtdSMARTInfo ) +static void json_print_smart_log(struct json_object *root, EXTENDED_SMART_INFO_T *ExtdSMARTInfo) { - /*struct json_object *root; */ struct json_object *lbafs; int index = 0; @@ -501,46 +511,45 @@ static void json_print_smart_log(struct json_object *root, lsbLifWrtFrmHost = 0, msbLifWrtFrmHost = 0, lsbLifRdToHost = 0, msbLifRdToHost = 0, lsbTrimCnt = 0, msbTrimCnt = 0; char buf[40] = {0}; - /*root = json_create_object();*/ lbafs = json_create_array(); json_object_add_value_array(root, "Extended-SMART-Attributes", lbafs); - for (index =0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) { + for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) { struct json_object *lbaf = json_create_object(); if (ExtdSMARTInfo->vendorData[index].AttributeNumber != 0) { json_object_add_value_string(lbaf, "attribute_name", print_ext_smart_id(ExtdSMARTInfo->vendorData[index].AttributeNumber)); - json_object_add_value_int(lbaf, "attribute_id",ExtdSMARTInfo->vendorData[index].AttributeNumber); + json_object_add_value_int(lbaf, "attribute_id", ExtdSMARTInfo->vendorData[index].AttributeNumber); json_object_add_value_int(lbaf, "attribute_value", smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index])); json_array_add_value_object(lbafs, lbaf); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_GB_ERASED_LSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_GB_ERASED_LSB) lsbGbErased = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_GB_ERASED_MSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_GB_ERASED_MSB) msbGbErased = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB) lsbLifWrtToFlash = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB) msbLifWrtToFlash = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB) lsbLifWrtFrmHost = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB) msbLifWrtFrmHost = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB) lsbLifRdToHost = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB) msbLifRdToHost = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_TRIM_COUNT_LSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_TRIM_COUNT_LSB) lsbTrimCnt = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); - if(ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_TRIM_COUNT_MSB) + if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_TRIM_COUNT_MSB) msbTrimCnt = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]); } } @@ -598,11 +607,6 @@ static void json_print_smart_log(struct json_object *root, sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbTrimCnt, (uint64_t)lsbTrimCnt); json_object_add_value_string(lbaf, "attribute_value", buf); json_array_add_value_object(lbafs, lbaf); - - /* - json_print_object(root, NULL); - printf("\n"); - */ } static void print_smart_log_CF(vendor_log_page_CF *pLogPageCF) @@ -613,63 +617,47 @@ static void print_smart_log_CF(vendor_log_page_CF *pLogPageCF) printf("%-40s", "Super-cap current temperature"); currentTemp = pLogPageCF->AttrCF.SuperCapCurrentTemperature; - /*currentTemp = currentTemp ? currentTemp - 273 : 0;*/ - printf(" 0x%016"PRIx64"", le64_to_cpu(currentTemp)); - printf("\n"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(currentTemp)); maxTemp = pLogPageCF->AttrCF.SuperCapMaximumTemperature; - /*maxTemp = maxTemp ? maxTemp - 273 : 0;*/ printf("%-40s", "Super-cap maximum temperature"); - printf(" 0x%016"PRIx64"", le64_to_cpu(maxTemp)); - printf("\n"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(maxTemp)); printf("%-40s", "Super-cap status"); - printf(" 0x%016"PRIx64"", le64_to_cpu(pLogPageCF->AttrCF.SuperCapStatus)); - printf("\n"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.SuperCapStatus)); printf("%-40s", "Data units read to DRAM namespace"); - printf(" 0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.MS__u64), - le64_to_cpu(pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.LS__u64)); - printf("\n"); + printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.MS__u64), + le64_to_cpu(pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.LS__u64)); printf("%-40s", "Data units written to DRAM namespace"); - printf(" 0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.MS__u64), - le64_to_cpu(pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.LS__u64)); - printf("\n"); + printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.MS__u64), + le64_to_cpu(pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.LS__u64)); printf("%-40s", "DRAM correctable error count"); - printf(" 0x%016"PRIx64"", le64_to_cpu(pLogPageCF->AttrCF.DramCorrectableErrorCount)); - printf("\n"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.DramCorrectableErrorCount)); printf("%-40s", "DRAM uncorrectable error count"); - printf(" 0x%016"PRIx64"", le64_to_cpu(pLogPageCF->AttrCF.DramUncorrectableErrorCount)); - printf("\n"); - + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.DramUncorrectableErrorCount)); } -static void json_print_smart_log_CF(struct json_object *root, - vendor_log_page_CF *pLogPageCF) +static void json_print_smart_log_CF(struct json_object *root, vendor_log_page_CF *pLogPageCF) { - /*struct json_object *root;*/ struct json_object *logPages; unsigned int currentTemp, maxTemp; char buf[40]; - /*root = json_create_object(); */ - logPages = json_create_array(); json_object_add_value_array(root, "DRAM Supercap SMART Attributes", logPages); struct json_object *lbaf = json_create_object(); currentTemp = pLogPageCF->AttrCF.SuperCapCurrentTemperature; - /*currentTemp = currentTemp ? currentTemp - 273 : 0;*/ json_object_add_value_string(lbaf, "attribute_name", "Super-cap current temperature"); json_object_add_value_int(lbaf, "attribute_value", currentTemp); json_array_add_value_object(logPages, lbaf); lbaf = json_create_object(); maxTemp = pLogPageCF->AttrCF.SuperCapMaximumTemperature; - /*maxTemp = maxTemp ? maxTemp - 273 : 0;*/ json_object_add_value_string(lbaf, "attribute_name", "Super-cap maximum temperature"); json_object_add_value_int(lbaf, "attribute_value", maxTemp); json_array_add_value_object(logPages, lbaf); @@ -704,25 +692,285 @@ static void json_print_smart_log_CF(struct json_object *root, json_object_add_value_string(lbaf, "attribute_name", "DRAM uncorrectable error count"); json_object_add_value_int(lbaf, "attribute_value", pLogPageCF->AttrCF.DramUncorrectableErrorCount); json_array_add_value_object(logPages, lbaf); +} + + +static void print_stx_smart_log_C0(STX_EXT_SMART_LOG_PAGE_C0 *pLogPageC0) +{ + printf("\n\nSeagate SMART Health Attributes :\n"); + printf("%-39s %-19s \n", "Description", "Health Attributes"); + + printf("%-40s", "Physical Media Units Written"); + printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.MS__u64), + le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.LS__u64)); + + printf("%-40s", "Physical Media Units Read"); + printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->phyMediaUnitsRd.MS__u64), + le64_to_cpu(pLogPageC0->phyMediaUnitsRd.LS__u64)); + + printf("%-40s", "Bad User NAND Blocks"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->badUsrNandBlocks)); + + printf("%-40s", "Bad System NAND Blocks"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->badSysNandBlocks)); + + printf("%-40s", "XOR Recovery Count"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->xorRecoveryCnt)); + + printf("%-40s", "Uncorrectable Read Error Count"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->ucRdEc)); + + printf("%-40s", "Soft ECC Error Count"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->softEccEc)); + + printf("%-40s", "End to End Correction Counts"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->etoeCrrCnt)); + + printf("%-40s", "System Data Used in Parcent"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->sysDataUsed)); + + printf("%-40s", "Refresh Counts"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->refreshCount)); + + printf("%-40s", "User Data Erase Counts"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->usrDataEraseCnt)); + + printf("%-40s", "Thermal Throttling Status and Count"); + printf(" 0x%04x\n", le16_to_cpu(pLogPageC0->thermalThrottling)); + + printf("%-40s", "DSSD Specification Version"); + printf(" %d.%d.%d.%d\n", pLogPageC0->dssdSpecVerMajor, + le16_to_cpu(pLogPageC0->dssdSpecVerMinor), + le16_to_cpu(pLogPageC0->dssdSpecVerPoint), + pLogPageC0->dssdSpecVerErrata); + + printf("%-40s", "PCIe Correctable Error Count"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->pcieCorrEc)); + + printf("%-40s", "Incomplete Shutdowns"); + printf(" 0x%08x\n", le32_to_cpu(pLogPageC0->incompleteShutdowns)); + + printf("%-40s", "Free Blocks in Percent"); + printf(" %d\n", pLogPageC0->freeBlocks); + + printf("%-40s", "Capacitor Health"); + printf(" 0x%04x\n", le16_to_cpu(pLogPageC0->capHealth)); + + printf("%-40s", "NVMe Errata Version"); + printf(" %c\n", pLogPageC0->nvmeErrataVer); + + printf("%-40s", "Unaligned IO"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->unalignedIO)); + + printf("%-40s", "Security Version Number"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->secVerNum)); + + printf("%-40s", "Total Namespace Utilization"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->totalNUSE)); + + printf("%-40s", "PLP Start Count"); + printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->plpStartCnt.MS__u64), + le64_to_cpu(pLogPageC0->plpStartCnt.LS__u64)); + + printf("%-40s", "Endurance Estimate"); + printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->enduranceEstimate.MS__u64), + le64_to_cpu(pLogPageC0->enduranceEstimate.LS__u64)); + + printf("%-40s", "PCIe Link Retraining Count"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->pcieLinkRetCnt)); + + printf("%-40s", "Power State Change Count"); + printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->powStateChangeCnt)); + + printf("%-40s", "Log Page Version"); + printf(" 0x%04x\n", le16_to_cpu(pLogPageC0->logPageVer)); + + printf("%-40s", "Log Page GUID"); + printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->logPageGUID.MS__u64), + le64_to_cpu(pLogPageC0->logPageGUID.LS__u64)); +} + +static void json_print_stx_smart_log_C0(struct json_object *root, STX_EXT_SMART_LOG_PAGE_C0 *pLogPageC0) +{ + struct json_object *logPages; + char buf[40]; + + logPages = json_create_array(); + json_object_add_value_array(root, "Seagate SMART Health Attributes", logPages); + + struct json_object *lbaf = json_create_object(); + + json_object_add_value_string(lbaf, "attribute_name", "Physical Media Units Written"); + memset(buf, 0, sizeof(buf)); + sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.MS__u64), + le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.LS__u64)); + json_object_add_value_string(lbaf, "attribute_value", buf); + json_array_add_value_object(logPages, lbaf); + + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Physical Media Units Read"); + memset(buf, 0, sizeof(buf)); + sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->phyMediaUnitsRd.MS__u64), + le64_to_cpu(pLogPageC0->phyMediaUnitsRd.LS__u64)); + json_object_add_value_string(lbaf, "attribute_value", buf); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Bad User NAND Blocks"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->badUsrNandBlocks)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Bad System NAND Blocks"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->badSysNandBlocks)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "XOR Recovery Count"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->xorRecoveryCnt)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Uncorrectable Read Error Count"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->ucRdEc)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Soft ECC Error Count"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->softEccEc)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "End to End Correction Counts"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->etoeCrrCnt)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "System Data Used in Parcent"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->sysDataUsed)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Refresh Counts"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->refreshCount)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "User Data Erase Counts"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->usrDataEraseCnt)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Thermal Throttling Status and Count"); + json_object_add_value_int(lbaf, "attribute_value", le16_to_cpu(pLogPageC0->thermalThrottling)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "DSSD Specification Version"); + memset(buf, 0, sizeof(buf)); + sprintf(buf, "%d.%d.%d.%d", pLogPageC0->dssdSpecVerMajor, + le16_to_cpu(pLogPageC0->dssdSpecVerMinor), + le16_to_cpu(pLogPageC0->dssdSpecVerPoint), + pLogPageC0->dssdSpecVerErrata); + json_object_add_value_string(lbaf, "attribute_value", buf); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "PCIe Correctable Error Count"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->pcieCorrEc)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Incomplete Shutdowns"); + json_object_add_value_int(lbaf, "attribute_value", le32_to_cpu(pLogPageC0->incompleteShutdowns)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Free Blocks in Percent"); + json_object_add_value_int(lbaf, "attribute_value", pLogPageC0->freeBlocks); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Capacitor Health"); + json_object_add_value_int(lbaf, "attribute_value", le16_to_cpu(pLogPageC0->capHealth)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "NVMe Errata Version"); + json_object_add_value_int(lbaf, "attribute_value", pLogPageC0->nvmeErrataVer); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Unaligned IO"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->unalignedIO)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Security Version Number"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->secVerNum)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Total Namespace Utilization"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->totalNUSE)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "PLP Start Count"); + memset(buf, 0, sizeof(buf)); + sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->plpStartCnt.MS__u64), + le64_to_cpu(pLogPageC0->plpStartCnt.LS__u64)); + json_object_add_value_string(lbaf, "attribute_value", buf); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Endurance Estimate"); + memset(buf, 0, sizeof(buf)); + sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->enduranceEstimate.MS__u64), + le64_to_cpu(pLogPageC0->enduranceEstimate.LS__u64)); + json_object_add_value_string(lbaf, "attribute_value", buf); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "PCIe Link Retraining Count"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->pcieLinkRetCnt)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Power State Change Count"); + json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->powStateChangeCnt)); + json_array_add_value_object(logPages, lbaf); + + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Log Page Version"); + json_object_add_value_int(lbaf, "attribute_value", le16_to_cpu(pLogPageC0->logPageVer)); + json_array_add_value_object(logPages, lbaf); - /* - json_print_object(root, NULL); - printf("\n"); - */ + lbaf = json_create_object(); + json_object_add_value_string(lbaf, "attribute_name", "Log Page GUID"); + memset(buf, 0, sizeof(buf)); + sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->logPageGUID.MS__u64), + le64_to_cpu(pLogPageC0->logPageGUID.LS__u64)); + json_object_add_value_string(lbaf, "attribute_value", buf); + json_array_add_value_object(logPages, lbaf); } static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { + struct nvme_id_ctrl ctrl; + char modelNo[40]; + STX_EXT_SMART_LOG_PAGE_C0 ehExtSmart; EXTENDED_SMART_INFO_T ExtdSMARTInfo; vendor_log_page_CF logPageCF; - int fd; struct json_object *root = json_create_object(); struct json_object *lbafs = json_create_array(); struct json_object *lbafs_ExtSmart, *lbafs_DramSmart; - const char *desc = "Retrieve Seagate Extended SMART information for the given device "; + const char *desc = "Retrieve the Firmware Activation History for Seagate NVMe drives"; const char *output_format = "output in binary format"; - int err, index=0; + struct nvme_dev *dev; + int err, index = 0; struct config { char *output_format; }; @@ -736,23 +984,102 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { printf ("\nDevice not found \n"); return -1; } - if (strcmp(cfg.output_format,"json")) + if (strcmp(cfg.output_format, "json")) printf("Seagate Extended SMART Information :\n"); - err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + + /** + * Here we should identify if the drive is a Panthor or Jaguar. + * Here we need to extract the model no from ctrl-id abd use it + * to deternine drive family. + */ + + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (!err) { - if (strcmp(cfg.output_format,"json")) { + memcpy(modelNo, ctrl.mn, sizeof(modelNo)); + } else { + nvme_show_status(err); + return err; + } + + if (stx_is_jag_pan(modelNo) == 0) { + + err = nvme_get_log_simple(dev_fd(dev), 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + if (!err) { + if (strcmp(cfg.output_format, "json")) { + printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); + for (index = 0; index < 80; index++) + printf("-"); + printf("\n"); + for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) + print_smart_log(ExtdSMARTInfo.Version, ExtdSMARTInfo.vendorData[index], index == (NUMBER_EXTENDED_SMART_ATTRIBUTES - 1)); + + } else { + lbafs_ExtSmart = json_create_object(); + json_print_smart_log(lbafs_ExtSmart, &ExtdSMARTInfo); + + json_object_add_value_array(root, "SMART-Attributes", lbafs); + json_array_add_value_object(lbafs, lbafs_ExtSmart); + } + + /** + * Next get Log Page 0xCF + */ + + err = nvme_get_log_simple(dev_fd(dev), 0xCF, sizeof(logPageCF), &logPageCF); + if (!err) { + if (strcmp(cfg.output_format, "json")) { + print_smart_log_CF(&logPageCF); + } else { + lbafs_DramSmart = json_create_object(); + json_print_smart_log_CF(lbafs_DramSmart, &logPageCF); + json_array_add_value_object(lbafs, lbafs_DramSmart); + json_print_object(root, NULL); + } + } else if (!strcmp(cfg.output_format, "json")) { + json_print_object(root, NULL); + json_free_object(root); + } + } else if (err > 0) + nvme_show_status(err); + } else { + err = nvme_get_log_simple(dev_fd(dev), 0xC0, sizeof(ehExtSmart), &ehExtSmart); + + if (!err) { + if (strcmp(cfg.output_format, "json")) { + print_stx_smart_log_C0(&ehExtSmart); + + } else { + lbafs_ExtSmart = json_create_object(); + json_print_stx_smart_log_C0(lbafs_ExtSmart, &ehExtSmart); + + json_object_add_value_array(root, "SMART-Attributes", lbafs); + json_array_add_value_object(lbafs, lbafs_ExtSmart); + + json_print_object(root, NULL); + json_free_object(root); + } + } + + if (err > 0) + nvme_show_status(err); + } + + err = nvme_get_log_simple(dev_fd(dev), 0xC4, + sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + if (!err) { + if (strcmp(cfg.output_format, "json")) { printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value"); - for(index=0; index<80; index++) + for (index = 0; index < 80; index++) printf("-"); printf("\n"); - for(index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) + for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) print_smart_log(ExtdSMARTInfo.Version, ExtdSMARTInfo.vendorData[index], index == (NUMBER_EXTENDED_SMART_ATTRIBUTES - 1)); } else { @@ -767,11 +1094,10 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi * Next get Log Page 0xCF */ - err = nvme_get_log_simple(fd, 0xCF, sizeof(logPageCF), &logPageCF); + err = nvme_get_log_simple(dev_fd(dev), 0xCF, + sizeof(logPageCF), &logPageCF); if (!err) { - if(strcmp(cfg.output_format,"json")) { - /*printf("Seagate DRAM Supercap SMART Attributes :\n");*/ - + if (strcmp(cfg.output_format, "json")) { print_smart_log_CF(&logPageCF); } else { lbafs_DramSmart = json_create_object(); @@ -784,7 +1110,8 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); + return err; } @@ -794,7 +1121,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi * Temperature-Stats information ***************************************/ static void json_temp_stats(__u32 temperature, __u32 PcbTemp, __u32 SocTemp, __u32 maxTemperature, - __u32 MaxSocTemp, __u32 cf_err, __u32 scCurrentTemp, __u32 scMaxTem) + __u32 MaxSocTemp, __u32 cf_err, __u32 scCurrentTemp, __u32 scMaxTem) { struct json_object *root; root = json_create_object(); @@ -804,28 +1131,27 @@ static void json_temp_stats(__u32 temperature, __u32 PcbTemp, __u32 SocTemp, __u json_object_add_value_int(root, "Current SOC temperature", SocTemp); json_object_add_value_int(root, "Highest temperature", maxTemperature); json_object_add_value_int(root, "Max SOC temperature", MaxSocTemp); - if(!cf_err) { + if (!cf_err) { json_object_add_value_int(root, "SuperCap Current temperature", scCurrentTemp); json_object_add_value_int(root, "SuperCap Max temperature", scMaxTem); } json_print_object(root, NULL); - printf("\n"); - } + static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_smart_log smart_log; EXTENDED_SMART_INFO_T ExtdSMARTInfo; vendor_log_page_CF logPageCF; - int fd; int err, cf_err; int index; const char *desc = "Retrieve Seagate Temperature Stats information for the given device "; const char *output_format = "output in binary format"; unsigned int temperature = 0, PcbTemp = 0, SocTemp = 0, scCurrentTemp = 0, scMaxTemp = 0; unsigned long long maxTemperature = 0, MaxSocTemp = 0; + struct nvme_dev *dev; struct config { char *output_format; }; @@ -839,16 +1165,16 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { printf ("\nDevice not found \n");; return -1; } - if(strcmp(cfg.output_format,"json")) + if (strcmp(cfg.output_format, "json")) printf("Seagate Temperature Stats Information :\n"); /*STEP-1 : Get Current Temperature from SMART */ - err = nvme_get_log_smart(fd, 0xffffffff, false, &smart_log); + err = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); if (!err) { temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]); temperature = temperature ? temperature - 273 : 0; @@ -856,7 +1182,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin PcbTemp = PcbTemp ? PcbTemp - 273 : 0; SocTemp = le16_to_cpu(smart_log.temp_sensor[1]); SocTemp = SocTemp ? SocTemp - 273 : 0; - if (strcmp(cfg.output_format,"json")) { + if (strcmp(cfg.output_format, "json")) { printf("%-20s : %u C\n", "Current Temperature", temperature); printf("%-20s : %u C\n", "Current PCB Temperature", PcbTemp); printf("%-20s : %u C\n", "Current SOC Temperature", SocTemp); @@ -864,30 +1190,33 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin } /* STEP-2 : Get Max temperature form Ext SMART-id 194 */ - err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); + err = nvme_get_log_simple(dev_fd(dev), 0xC4, + sizeof(ExtdSMARTInfo), &ExtdSMARTInfo); if (!err) { - for(index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) { + for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) { if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_LIFE_TEMPERATURE) { maxTemperature = smart_attribute_vs(ExtdSMARTInfo.Version, ExtdSMARTInfo.vendorData[index]); maxTemperature = maxTemperature ? maxTemperature - 273 : 0; - if (strcmp(cfg.output_format,"json")) + if (strcmp(cfg.output_format, "json")) printf("%-20s : %d C\n", "Highest Temperature", (unsigned int)maxTemperature); } if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_SOC_LIFE_TEMPERATURE) { MaxSocTemp = smart_attribute_vs(ExtdSMARTInfo.Version, ExtdSMARTInfo.vendorData[index]); MaxSocTemp = MaxSocTemp ? MaxSocTemp - 273 : 0; - if (strcmp(cfg.output_format,"json")) + if (strcmp(cfg.output_format, "json")) printf("%-20s : %d C\n", "Max SOC Temperature", (unsigned int)MaxSocTemp); } } + } else { + if (err > 0) + nvme_show_status(err); } - else if (err > 0) - nvme_show_status(err); - cf_err = nvme_get_log_simple(fd, 0xCF, sizeof(ExtdSMARTInfo), &logPageCF); + cf_err = nvme_get_log_simple(dev_fd(dev), 0xCF, + sizeof(ExtdSMARTInfo), &logPageCF); - if(!cf_err) { + if (!cf_err) { scCurrentTemp = logPageCF.AttrCF.SuperCapCurrentTemperature; scCurrentTemp = scCurrentTemp ? scCurrentTemp - 273 : 0; printf("%-20s : %d C\n", "Super-cap Current Temperature", scCurrentTemp); @@ -897,10 +1226,10 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin printf("%-20s : %d C\n", "Super-cap Max Temperature", scMaxTemp); } - if(!strcmp(cfg.output_format,"json")) + if (!strcmp(cfg.output_format, "json")) json_temp_stats(temperature, PcbTemp, SocTemp, maxTemperature, MaxSocTemp, cf_err, scCurrentTemp, scMaxTemp); - close(fd); + dev_close(dev); return err; } /* EOF Temperature Stats information */ @@ -987,13 +1316,12 @@ static void json_vs_pcie_error_log(pcie_error_log_page pcieErrorLog) json_object_add_value_int(root, "Cpl TLP Poisoned Error Count", pcieErrorLog.CplTlpPoisonedErrCnt); json_object_add_value_int(root, "Request Completion Abort Error Count", pcieErrorLog.ReqCAErrCnt); json_print_object(root, NULL); - printf("\n"); } static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { pcie_error_log_page pcieErrorLog; - int fd; + struct nvme_dev *dev; const char *desc = "Retrieve Seagate PCIe error counters for the given device "; const char *output_format = "output in binary format"; @@ -1011,18 +1339,19 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { printf ("\nDevice not found \n");; return -1; } - if(strcmp(cfg.output_format,"json")) + if (strcmp(cfg.output_format, "json")) printf("Seagate PCIe error counters Information :\n"); - err = nvme_get_log_simple(fd, 0xCB, sizeof(pcieErrorLog), &pcieErrorLog); + err = nvme_get_log_simple(dev_fd(dev), 0xCB, + sizeof(pcieErrorLog), &pcieErrorLog); if (!err) { - if(strcmp(cfg.output_format,"json")) { + if (strcmp(cfg.output_format, "json")) { print_vs_pcie_error_log(pcieErrorLog); } else json_vs_pcie_error_log(pcieErrorLog); @@ -1030,17 +1359,233 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } /* EOF PCIE error-log information */ + +/*************************************** + * FW Activation History log + ***************************************/ +static void print_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwActivHis) +{ + __u32 i; + char prev_fw[9] = {0}; + char new_fw[9] = {0}; + char buf[80]; + + if (fwActivHis.numValidFwActHisEnt > 0) { + printf("\n\nSeagate FW Activation Histry :\n"); + printf("%-9s %-21s %-7s %-13s %-9s %-5s %-15s %-9s\n", "Counter ", " Timestamp ", " PCC ", "Previous FW ", "New FW ", "Slot", "Commit Action", "Result"); + + for (i = 0; i < fwActivHis.numValidFwActHisEnt; i++) { + + printf(" %-4d ", fwActivHis.fwActHisEnt[i].fwActivCnt); + + time_t t = fwActivHis.fwActHisEnt[i].timeStamp / 1000; + struct tm ts; + ts = *localtime(&t); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts); + printf(" %-20s ", buf); + printf("%-5" PRId64 " ", + (uint64_t)fwActivHis.fwActHisEnt[i].powCycleCnt); + + memset(prev_fw, 0, sizeof(prev_fw)); + memcpy(prev_fw, fwActivHis.fwActHisEnt[i].previousFW, sizeof(fwActivHis.fwActHisEnt[i].previousFW)); + printf("%-8s ", prev_fw); + + memset(new_fw, 0, sizeof(new_fw)); + memcpy(new_fw, fwActivHis.fwActHisEnt[i].newFW, sizeof(fwActivHis.fwActHisEnt[i].newFW)); + printf("%-8s ", new_fw); + + printf(" %-2d ", fwActivHis.fwActHisEnt[i].slotNum); + printf(" 0x%02x ", fwActivHis.fwActHisEnt[i].commitActionType); + printf(" 0x%02x \n", fwActivHis.fwActHisEnt[i].result); + } + } else { + printf("%s\n", "Do not have valid FW Activation History"); + } +} + +static void json_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwActivHis) +{ + struct json_object *root; + root = json_create_object(); + __u32 i; + + char buf[80]; + + struct json_object *historyLogPage; + historyLogPage = json_create_array(); + json_object_add_value_array(root, "Seagate FW Activation History", historyLogPage); + + if (fwActivHis.numValidFwActHisEnt > 0) { + for (i = 0; i < fwActivHis.numValidFwActHisEnt; i++) { + struct json_object *lbaf = json_create_object(); + char prev_fw[8] = { 0 }; + char new_fw[8] = { 0 }; + + json_object_add_value_int(lbaf, "Counter", fwActivHis.fwActHisEnt[i].fwActivCnt); + + time_t t = fwActivHis.fwActHisEnt[i].timeStamp / 1000; + struct tm ts; + ts = *localtime(&t); + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts); + printf(" %-20s ", buf); + json_object_add_value_string(lbaf, "Timestamp", buf); + + json_object_add_value_int(lbaf, "PCC", fwActivHis.fwActHisEnt[i].powCycleCnt); + sprintf(prev_fw, "%s", fwActivHis.fwActHisEnt[i].previousFW); + json_object_add_value_string(lbaf, "Previous_FW", prev_fw); + + sprintf(new_fw, "%s", fwActivHis.fwActHisEnt[i].newFW); + json_object_add_value_string(lbaf, "New_FW", new_fw); + + json_object_add_value_int(lbaf, "Slot", fwActivHis.fwActHisEnt[i].slotNum); + json_object_add_value_int(lbaf, "Commit_Action", fwActivHis.fwActHisEnt[i].commitActionType); + json_object_add_value_int(lbaf, "Result", fwActivHis.fwActHisEnt[i].result); + + json_array_add_value_object(historyLogPage, lbaf); + } + } else { + printf("%s\n", "Do not have valid FW Activation History"); + } + + json_print_object(root, NULL); + json_free_object(root); +} + +static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + stx_fw_activ_history_log_page fwActivHis; + struct nvme_dev *dev; + + const char *desc = "Retrieve FW Activate History for Seagate device "; + const char *output_format = "output in binary format"; + int err; + struct config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &cfg.output_format, output_format), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err < 0) { + printf ("\nDevice not found \n");; + return -1; + } + + if (strcmp(cfg.output_format, "json")) + printf("Seagate FW Activation Histry Information :\n"); + + err = nvme_get_log_simple(dev_fd(dev), 0xC2, sizeof(fwActivHis), &fwActivHis); + if (!err) { + if (strcmp(cfg.output_format, "json")) { + print_stx_vs_fw_activate_history(fwActivHis); + } else + json_stx_vs_fw_activate_history(fwActivHis); + + } else if (err > 0) + nvme_show_status(err); + + dev_close(dev); + return err; +} +/* EOF FW Activation History log information */ + + +static int clear_fw_activate_history(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Clear FW Activation History for the given Seagate device "; + const char *save = "specifies that the controller shall save the attribute"; + int err; + struct nvme_dev *dev; + struct nvme_id_ctrl ctrl; + char modelNo[40]; + __u32 result; + + struct config { + bool save; + }; + + struct config cfg = { + .save = 0, + }; + + OPT_ARGS(opts) = { + OPT_FLAG("save", 's', &cfg.save, save), + OPT_END() + }; + + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err < 0) { + printf ("\nDevice not found \n"); + return -1; + } + + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if (!err) { + memcpy(modelNo, ctrl.mn, sizeof(modelNo)); + } else { + nvme_show_status(err); + return err; + } + + if (stx_is_jag_pan(modelNo) == 0) { + printf ("\nDevice does not support Clear FW Activation History \n"); + } else { + + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = 0xC1, + .nsid = 0, + .cdw11 = 0x80000000, + .cdw12 = 0, + .save = 0, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (err) + fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", + __func__); + } + + if (err < 0) { + perror("set-feature"); + return errno; + } + + dev_close(dev); + return err; +} + + static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Clear Seagate PCIe Correctable counters for the given device "; const char *save = "specifies that the controller shall save the attribute"; - int err, fd; + + struct nvme_id_ctrl ctrl; + char modelNo[40]; + + struct nvme_dev *dev; + __u32 result; + int err; struct config { bool save; @@ -1055,21 +1600,53 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { printf ("\nDevice not found \n");; return -1; } - err = nvme_set_features_simple(fd, 0xE1, 0, 0xCB, cfg.save, &result); + + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); + if (!err) { + memcpy(modelNo, ctrl.mn, sizeof(modelNo)); + } else { + nvme_show_status(err); + return err; + } + + if (stx_is_jag_pan(modelNo) == 0) { + err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result); + } else { + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = dev_fd(dev), + .fid = 0xC3, + .nsid = 0, + .cdw11 = 0x80000000, + .cdw12 = 0, + .save = 0, + .uuidx = 0, + .cdw15 = 0, + .data_len = 0, + .data = NULL, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); + if (err) + fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", __func__); + } + + err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result); if (err < 0) { perror("set-feature"); + return errno; } - close(fd); + dev_close(dev); return err; - } static int get_host_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin) @@ -1081,11 +1658,12 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug "state of the controller at the time the command is processed. " \ "0 - controller shall not update the Telemetry Host Initiated Data."; const char *raw = "output in raw format"; - int err, fd, dump_fd; struct nvme_temetry_log_hdr tele_log; - __le64 offset = 0; int blkCnt, maxBlk = 0, blksToGet; + struct nvme_dev *dev; unsigned char *log; + __le64 offset = 0; + int err, dump_fd; struct config { __u32 namespace_id; @@ -1105,24 +1683,25 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; dump_fd = STDOUT_FILENO; cfg.log_id = (cfg.log_id << 8) | 0x07; - err = nvme_get_nsid_log(fd, false, cfg.log_id, cfg.namespace_id, - sizeof(tele_log), (void *)(&tele_log)); + err = nvme_get_nsid_log(dev_fd(dev), false, cfg.log_id, + cfg.namespace_id, + sizeof(tele_log), (void *)(&tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; offset += 512; if (!cfg.raw_binary) { printf("Device:%s log-id:%d namespace-id:%#x\n", - devicename, cfg.log_id, - cfg.namespace_id); + dev->name, cfg.log_id, + cfg.namespace_id); printf("Data Block 1 Last Block:%d Data Block 2 Last Block:%d Data Block 3 Last Block:%d\n", - tele_log.tele_data_area1, tele_log.tele_data_area2, tele_log.tele_data_area3); + tele_log.tele_data_area1, tele_log.tele_data_area2, tele_log.tele_data_area3); d((unsigned char *)(&tele_log), sizeof(tele_log), 16, 1); } else @@ -1134,13 +1713,13 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug blkCnt = 0; - while(blkCnt < maxBlk) { + while (blkCnt < maxBlk) { unsigned long long bytesToGet; blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); - if(blksToGet == 0) { - close(fd); + if (blksToGet == 0) { + dev_close(dev); return err; } @@ -1149,28 +1728,28 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug if (!log) { fprintf(stderr, "could not alloc buffer for log\n"); - close(fd); + dev_close(dev); return EINVAL; } memset(log, 0, bytesToGet); struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = fd, - .lid = cfg.log_id, - .nsid = cfg.namespace_id, - .lpo = offset, - .lsp = 0, - .lsi = 0, - .rae = true, - .uuidx = 0, - .csi = NVME_CSI_NVM, - .ot = false, - .len = bytesToGet, - .log = (void *)log, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, + .args_size = sizeof(args), + .fd = dev_fd(dev), + .lid = cfg.log_id, + .nsid = cfg.namespace_id, + .lpo = offset, + .lsp = 0, + .lsi = 0, + .rae = true, + .uuidx = 0, + .csi = NVME_CSI_NVM, + .ot = false, + .len = bytesToGet, + .log = (void *)log, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, }; err = nvme_get_log(&args); if (!err) { @@ -1192,17 +1771,18 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug free(log); } - close(fd); + dev_close(dev); return err; } static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - const char *desc = "Capture the Telemetry Controller-Initiated Data in either " \ + const char *desc = "Capture the Telemetry Controller-Initiated Data in either " \ "hex-dump (default) or binary format"; const char *namespace_id = "desired namespace"; const char *raw = "output in raw format"; - int err, fd, dump_fd; + struct nvme_dev *dev; + int err, dump_fd; struct nvme_temetry_log_hdr tele_log; __le64 offset = 0; __u16 log_id; @@ -1224,24 +1804,24 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; dump_fd = STDOUT_FILENO; log_id = 0x08; - err = nvme_get_nsid_log(fd, false, log_id, cfg.namespace_id, - sizeof(tele_log), (void *)(&tele_log)); + err = nvme_get_nsid_log(dev_fd(dev), false, log_id, cfg.namespace_id, + sizeof(tele_log), (void *)(&tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; offset += 512; if (!cfg.raw_binary) { printf("Device:%s namespace-id:%#x\n", - devicename, cfg.namespace_id); + dev->name, cfg.namespace_id); printf("Data Block 1 Last Block:%d Data Block 2 Last Block:%d Data Block 3 Last Block:%d\n", - tele_log.tele_data_area1, tele_log.tele_data_area2, tele_log.tele_data_area3); + tele_log.tele_data_area1, tele_log.tele_data_area2, tele_log.tele_data_area3); d((unsigned char *)(&tele_log), sizeof(tele_log), 16, 1); } else @@ -1253,12 +1833,12 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug blkCnt = 0; - while(blkCnt < maxBlk) { + while (blkCnt < maxBlk) { unsigned long long bytesToGet; blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); - if(blksToGet == 0) + if (blksToGet == 0) return err; bytesToGet = (unsigned long long)blksToGet * 512; @@ -1272,21 +1852,21 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug memset(log, 0, bytesToGet); struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = fd, - .lid = log_id, - .nsid = cfg.namespace_id, - .lpo = offset, - .lsp = 0, - .lsi = 0, - .rae = true, - .uuidx = 0, - .csi = NVME_CSI_NVM, - .ot = false, - .len = bytesToGet, - .log = (void *)log, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, + .args_size = sizeof(args), + .fd = dev_fd(dev), + .lid = log_id, + .nsid = cfg.namespace_id, + .lpo = offset, + .lsp = 0, + .lsi = 0, + .rae = true, + .uuidx = 0, + .csi = NVME_CSI_NVM, + .ot = false, + .len = bytesToGet, + .log = (void *)log, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, }; err = nvme_get_log(&args); if (!err) { @@ -1308,21 +1888,14 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug free(log); } - close(fd); + dev_close(dev); return err; } void seaget_d_raw(unsigned char *buf, int len, int fd) { - /********************* - int i; - fflush(stdout); - for (i = 0; i < len; i++) - putchar(*(buf+i)); - *********************/ - if (write(fd, (void *)buf, len) <= 0) - printf("%s: Write Failed\n",__FUNCTION__); + printf("%s: Write Failed\n", __FUNCTION__); } @@ -1333,9 +1906,10 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl const char *namespace_id = "desired namespace"; const char *file = "dump file"; - int err, fd, dump_fd; + struct nvme_dev *dev; + int err, dump_fd; int flags = O_WRONLY | O_CREAT; - int mode = S_IRUSR | S_IWUSR |S_IRGRP | S_IWGRP| S_IROTH; + int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; struct nvme_temetry_log_hdr tele_log; __le64 offset = 0; __u16 log_id; @@ -1358,31 +1932,27 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; dump_fd = STDOUT_FILENO; - if(strlen(cfg.file)) { + if (strlen(cfg.file)) { dump_fd = open(cfg.file, flags, mode); if (dump_fd < 0) { perror(cfg.file); - close(fd); + dev_close(dev); return EINVAL; } } log_id = 0x08; - err = nvme_get_nsid_log(fd, false, log_id, cfg.namespace_id, - sizeof(tele_log), (void *)(&tele_log)); + err = nvme_get_nsid_log(dev_fd(dev), false, log_id, cfg.namespace_id, + sizeof(tele_log), (void *)(&tele_log)); if (!err) { maxBlk = tele_log.tele_data_area3; offset += 512; - /* - printf("Data Block 1 Last Block:%d Data Block 2 Last Block:%d Data Block 3 Last Block:%d\n", - tele_log.tele_data_area1, tele_log.tele_data_area2, tele_log.tele_data_area3); - */ seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd); } else if (err > 0) nvme_show_status(err); @@ -1391,12 +1961,12 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl blkCnt = 0; - while(blkCnt < maxBlk) { + while (blkCnt < maxBlk) { unsigned long long bytesToGet; blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); - if(blksToGet == 0) { + if (blksToGet == 0) { goto out; } @@ -1412,21 +1982,21 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl memset(log, 0, bytesToGet); struct nvme_get_log_args args = { - .args_size = sizeof(args), - .fd = fd, - .lid = log_id, - .nsid = cfg.namespace_id, - .lpo = offset, - .lsp = 0, - .lsi = 0, - .rae = true, - .uuidx = 0, - .csi = NVME_CSI_NVM, - .ot = false, - .len = bytesToGet, - .log = (void *)log, - .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, - .result = NULL, + .args_size = sizeof(args), + .fd = dev_fd(dev), + .lid = log_id, + .nsid = cfg.namespace_id, + .lpo = offset, + .lsp = 0, + .lsi = 0, + .rae = true, + .uuidx = 0, + .csi = NVME_CSI_NVM, + .ot = false, + .len = bytesToGet, + .log = (void *)log, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = NULL, }; err = nvme_get_log(&args); if (!err) { @@ -1444,20 +2014,29 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl free(log); } out: - if(strlen(cfg.file)) + if (strlen(cfg.file)) close(dump_fd); - close(fd); + dev_close(dev); return err; } /*SEAGATE-PLUGIN Version */ -static int seagate_plugin_version(int argc, char **argv, struct command *cmd, - struct plugin *plugin) +static int seagate_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin) { printf("Seagate-Plugin version : %d.%d \n", - SEAGATE_PLUGIN_VERSION_MAJOR, - SEAGATE_PLUGIN_VERSION_MINOR); + SEAGATE_PLUGIN_VERSION_MAJOR, + SEAGATE_PLUGIN_VERSION_MINOR); return 0; } /*EOF SEAGATE-PLUGIN Version */ + +/*OCP SEAGATE-PLUGIN Version */ +static int stx_ocp_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + printf("Seagate-OCP-Plugin version : %d.%d \n", + SEAGATE_OCP_PLUGIN_VERSION_MAJOR, + SEAGATE_OCP_PLUGIN_VERSION_MINOR); + return 0; +} +/*EOF OCP SEAGATE-PLUGIN Version */ diff --git a/plugins/seagate/seagate-nvme.h b/plugins/seagate/seagate-nvme.h index 6df1331..99f6327 100644 --- a/plugins/seagate/seagate-nvme.h +++ b/plugins/seagate/seagate-nvme.h @@ -18,6 +18,8 @@ * * \file seagate-nvme.h * \brief This file defines the functions and macros to make building a nvme-cli seagate plug-in. + * + * Author: Debabrata Bardhan <debabrata.bardhan@seagate.com> */ #undef CMD_INC_FILE @@ -30,15 +32,18 @@ PLUGIN(NAME("seagate", "Seagate vendor specific extensions", NVME_VERSION), COMMAND_LIST( - ENTRY("vs-temperature-stats", "Retrieve Seagate temperature statistics ", temp_stats) - ENTRY("vs-log-page-sup", "Retrieve Seagate Supported Log-pages Information ", log_pages_supp) - ENTRY("vs-smart-add-log", "Retrieve Seagate extended-SMART Information ", vs_smart_log) - ENTRY("vs-pcie-stats", "Retrieve Seagate PCIe error statistics ", vs_pcie_error_log) - ENTRY("clear-pcie-correctable-errors", "Clear Seagate PCIe error statistics ", vs_clr_pcie_correctable_errs) - ENTRY("get-host-tele", "Retrieve Seagate Host-Initiated Telemetry ", get_host_tele) - ENTRY("get-ctrl-tele", "Retrieve Seagate Controller-Initiated Telemetry ", get_ctrl_tele) - ENTRY("vs-internal-log", "Retrieve Seagate Controller-Initiated Telemetry in binary format", vs_internal_log) - ENTRY("plugin-version", "Shows Seagate plugin's version information ", seagate_plugin_version) + ENTRY("vs-temperature-stats", "Retrieve Seagate temperature statistics ", temp_stats) + ENTRY("vs-log-page-sup", "Retrieve Seagate Supported Log-pages Information ", log_pages_supp) + ENTRY("vs-smart-add-log", "Retrieve Seagate extended-SMART Information ", vs_smart_log) + ENTRY("vs-pcie-stats", "Retrieve Seagate PCIe error statistics ", vs_pcie_error_log) + ENTRY("clear-pcie-correctable-errors", "Clear Seagate PCIe error statistics ", vs_clr_pcie_correctable_errs) + ENTRY("get-host-tele", "Retrieve Seagate Host-Initiated Telemetry ", get_host_tele) + ENTRY("get-ctrl-tele", "Retrieve Seagate Controller-Initiated Telemetry ", get_ctrl_tele) + ENTRY("vs-internal-log", "Retrieve Seagate Controller-Initiated Telemetry in binary format", vs_internal_log) + ENTRY("vs-fw-activate-history", "Retrieve the Firmware Activation History", stx_vs_fw_activate_history) + ENTRY("clear-fw-activate-history", "Clear Firmware Activation History", clear_fw_activate_history) + ENTRY("plugin-version", "Shows Seagate plugin's version information ", seagate_plugin_version) + ENTRY("cloud-SSD-plugin-version", "Shows OCP Seagate plugin's version information ", stx_ocp_plugin_version) ) ); diff --git a/plugins/shannon/shannon-nvme.c b/plugins/shannon/shannon-nvme.c index 220638f..424b3f7 100644 --- a/plugins/shannon/shannon-nvme.c +++ b/plugins/shannon/shannon-nvme.c @@ -117,15 +117,16 @@ static void show_shannon_smart_log(struct nvme_shannon_smart_log *smart, static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_shannon_smart_log smart_log; - int err, fd; char *desc = "Get Shannon vendor specific additional smart log (optionally, "\ "for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; + struct nvme_dev *dev; struct config { __u32 namespace_id; bool raw_binary; }; + int err; struct config cfg = { .namespace_id = NVME_NSID_ALL, @@ -137,20 +138,21 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; - err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id, - sizeof(smart_log), &smart_log); + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, + sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) - show_shannon_smart_log(&smart_log, cfg.namespace_id, devicename); + show_shannon_smart_log(&smart_log, cfg.namespace_id, + dev->name); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } else if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } @@ -174,9 +176,10 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st const char *data_len = "buffer len (if) data is returned"; const char *cdw11 = "dword 11 for interrupt vector config"; const char *human_readable = "show infos in readable format"; - int err, fd; - __u32 result; + struct nvme_dev *dev; void *buf = NULL; + __u32 result; + int err; struct config { __u32 namespace_id; @@ -207,24 +210,24 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; if (cfg.sel > 7) { fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); - close(fd); + dev_close(dev); return EINVAL; } if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - close(fd); + dev_close(dev); return EINVAL; } if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { - close(fd); + dev_close(dev); exit(ENOMEM); } memset(buf, 0, cfg.data_len); @@ -232,7 +235,7 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st struct nvme_get_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = cfg.feature_id, .nsid = cfg.namespace_id, .sel = cfg.sel, @@ -286,10 +289,11 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st const char *data = "optional file for feature data (default stdin)"; const char *value = "new value of feature (required)"; const char *save = "specifies that the controller shall save the attribute"; - int err, fd; - __u32 result; - void *buf = NULL; int ffd = STDIN_FILENO; + struct nvme_dev *dev; + void *buf = NULL; + __u32 result; + int err; struct config { char *file; @@ -319,20 +323,20 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; if (!cfg.feature_id) { fprintf(stderr, "feature-id required param\n"); - close(fd); + dev_close(dev); return EINVAL; } if (cfg.data_len) { if (posix_memalign(&buf, getpagesize(), cfg.data_len)){ fprintf(stderr, "can not allocate feature payload\n"); - close(fd); + dev_close(dev); return ENOMEM; } memset(buf, 0, cfg.data_len); @@ -357,7 +361,7 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st struct nvme_set_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = cfg.feature_id, .nsid = cfg.namespace_id, .cdw11 = cfg.value, diff --git a/plugins/solidigm/meson.build b/plugins/solidigm/meson.build index fb0f6a9..bca13bb 100644 --- a/plugins/solidigm/meson.build +++ b/plugins/solidigm/meson.build @@ -2,4 +2,6 @@ sources += [ 'plugins/solidigm/solidigm-smart.c', 'plugins/solidigm/solidigm-garbage-collection.c', 'plugins/solidigm/solidigm-latency-tracking.c', + 'plugins/solidigm/solidigm-telemetry.c', ] +subdir('solidigm-telemetry') diff --git a/plugins/solidigm/solidigm-garbage-collection.c b/plugins/solidigm/solidigm-garbage-collection.c index 415722b..8e2eccc 100644 --- a/plugins/solidigm/solidigm-garbage-collection.c +++ b/plugins/solidigm/solidigm-garbage-collection.c @@ -56,13 +56,15 @@ static void vu_gc_log_show(garbage_control_collection_log_t *payload, const char for (int i = 0; i < VU_GC_MAX_ITEMS; i++) { gc_item_t item = payload->item[i]; - printf("%-13lu %d\n",le64_to_cpu(item.timestamp), le32_to_cpu(item.timer_type)); + printf("%-13" PRIu64 " %d\n", le64_to_cpu(item.timestamp), le32_to_cpu(item.timer_type)); } } int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Get and parse Solidigm vendor specific garbage collection event log."; + struct nvme_dev *dev; + int err; struct config { char *output_format; @@ -77,35 +79,37 @@ int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *c OPT_END() }; - int fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - return fd; - } + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; enum nvme_print_flags flags = validate_output_format(cfg.output_format); if (flags == -EINVAL) { fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format); - close(fd); - return flags; + dev_close(dev); + return EINVAL; } garbage_control_collection_log_t gc_log; const int solidigm_vu_gc_log_id = 0xfd; - int err = nvme_get_log_simple(fd, solidigm_vu_gc_log_id, sizeof(gc_log), &gc_log); + err = nvme_get_log_simple(dev_fd(dev), solidigm_vu_gc_log_id, + sizeof(gc_log), &gc_log); if (!err) { if (flags & BINARY) { d_raw((unsigned char *)&gc_log, sizeof(gc_log)); } else if (flags & JSON) { - vu_gc_log_show_json(&gc_log, devicename); + vu_gc_log_show_json(&gc_log, dev->name); } else { - vu_gc_log_show(&gc_log, devicename); + vu_gc_log_show(&gc_log, dev->name); } } else if (err > 0) { nvme_show_status(err); } - - close(fd); + + /* Redundant close() to make static code analysis happy */ + close(dev->direct.fd); + dev_close(dev); return err; } diff --git a/plugins/solidigm/solidigm-latency-tracking.c b/plugins/solidigm/solidigm-latency-tracking.c index 0bfd611..1013ae8 100644 --- a/plugins/solidigm/solidigm-latency-tracking.c +++ b/plugins/solidigm/solidigm-latency-tracking.c @@ -216,7 +216,7 @@ static void latency_tracker_pre_parse(struct latency_tracker *lt) printf("Major Revision: %u\nMinor Revision: %u\n", le16_to_cpu(lt->stats.version_major), le16_to_cpu(lt->stats.version_minor)); if (lt->has_average_latency_field) { - printf("Average Latency: %lu\n", le64_to_cpu(lt->stats.average_latency)); + printf("Average Latency: %" PRIu64 "\n", le64_to_cpu(lt->stats.average_latency)); } print_dash_separator(); printf("%-12s%-12s%-12s%-20s\n", "Bucket", "Start", "End", "Value"); @@ -385,6 +385,7 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd struct plugin *plugin) { const char *desc = "Get and Parse Solidigm Latency Tracking Statistics log."; + struct nvme_dev *dev; __u32 enabled; int err; @@ -407,43 +408,45 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd OPT_END() }; - lt.fd = parse_and_open(argc, argv, desc, opts); - if (lt.fd < 0) - return lt.fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; + + lt.fd = dev_fd(dev); lt.print_flags = validate_output_format(lt.cfg.output_format); if (lt.print_flags == -EINVAL) { fprintf(stderr, "Invalid output format '%s'\n", lt.cfg.output_format); - close(lt.fd); + dev_close(dev); return EINVAL; } if (lt.cfg.type > 0xf) { fprintf(stderr, "Invalid Log type value '%d'\n", lt.cfg.type); - close(lt.fd); + dev_close(dev); return EINVAL; } if (lt.cfg.type && !(lt.cfg.read || lt.cfg.write)) { fprintf(stderr, "Log type option valid only when retrieving statistics\n"); - close(lt.fd); + dev_close(dev); return EINVAL; } err = latency_tracking_enable(<); if (err){ - close(lt.fd); + dev_close(dev); return err; } err = latency_tracker_get_log(<); if (err){ - close(lt.fd); + dev_close(dev); return err; } if ((lt.cfg.read || lt.cfg.write || lt.cfg.enable || lt.cfg.disable)) { - close(lt.fd); + dev_close(dev); return 0; } @@ -465,6 +468,8 @@ int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd } else { fprintf(stderr, "Could not read feature id 0xE2.\n"); } - close(lt.fd); + /* Redundant close() to make static code analysis happy */ + close(dev->direct.fd); + dev_close(dev); return err; } diff --git a/plugins/solidigm/solidigm-nvme.c b/plugins/solidigm/solidigm-nvme.c index 3eb3cc9..684648a 100644 --- a/plugins/solidigm/solidigm-nvme.c +++ b/plugins/solidigm/solidigm-nvme.c @@ -13,6 +13,7 @@ #include "solidigm-smart.h" #include "solidigm-garbage-collection.h" #include "solidigm-latency-tracking.h" +#include "solidigm-telemetry.h" static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { @@ -27,4 +28,9 @@ static int get_garbage_collection_log(int argc, char **argv, struct command *cmd static int get_latency_tracking_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { return solidigm_get_latency_tracking_log(argc, argv, cmd, plugin); +} + +static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + return solidigm_get_telemetry_log(argc, argv, cmd, plugin); }
\ No newline at end of file diff --git a/plugins/solidigm/solidigm-nvme.h b/plugins/solidigm/solidigm-nvme.h index 9fc8b45..ed48400 100644 --- a/plugins/solidigm/solidigm-nvme.h +++ b/plugins/solidigm/solidigm-nvme.h @@ -13,13 +13,14 @@ #include "cmd.h" -#define SOLIDIGM_PLUGIN_VERSION "0.4" +#define SOLIDIGM_PLUGIN_VERSION "0.6" PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION), COMMAND_LIST( ENTRY("smart-log-add", "Retrieve Solidigm SMART Log", get_additional_smart_log) ENTRY("garbage-collect-log", "Retrieve Garbage Collection Log", get_garbage_collection_log) ENTRY("latency-tracking-log", "Enable/Retrieve Latency tracking Log", get_latency_tracking_log) + ENTRY("parse-telemetry-log", "Parse Telemetry Log binary", get_telemetry_log) ) ); diff --git a/plugins/solidigm/solidigm-smart.c b/plugins/solidigm/solidigm-smart.c index 77a2210..77c26ac 100644 --- a/plugins/solidigm/solidigm-smart.c +++ b/plugins/solidigm/solidigm-smart.c @@ -10,8 +10,6 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <inttypes.h> -#include <endian.h> #include "common.h" #include "nvme.h" @@ -201,7 +199,8 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd const int solidigm_vu_smart_log_id = 0xCA; vu_smart_log_t smart_log_payload; enum nvme_print_flags flags; - int fd, err; + struct nvme_dev *dev; + int err; struct config { __u32 namespace_id; @@ -219,32 +218,36 @@ int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - return fd; - } + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; flags = validate_output_format(cfg.output_format); if (flags == -EINVAL) { fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format); - close(fd); + dev_close(dev); return flags; } - err = nvme_get_log_simple(fd, solidigm_vu_smart_log_id, sizeof(smart_log_payload), &smart_log_payload); + err = nvme_get_log_simple(dev_fd(dev), solidigm_vu_smart_log_id, + sizeof(smart_log_payload), &smart_log_payload); if (!err) { if (flags & JSON) { - vu_smart_log_show_json(&smart_log_payload, cfg.namespace_id, devicename); + vu_smart_log_show_json(&smart_log_payload, + cfg.namespace_id, dev->name); } else if (flags & BINARY) { d_raw((unsigned char *)&smart_log_payload, sizeof(smart_log_payload)); } else { - vu_smart_log_show(&smart_log_payload, cfg.namespace_id, devicename); + vu_smart_log_show(&smart_log_payload, cfg.namespace_id, + dev->name); } } else if (err > 0) { nvme_show_status(err); } - close(fd); + /* Redundant close() to make static code analysis happy */ + close(dev->direct.fd); + dev_close(dev); return err; } diff --git a/plugins/solidigm/solidigm-telemetry.c b/plugins/solidigm/solidigm-telemetry.c new file mode 100644 index 0000000..84a4e2a --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "common.h" +#include "nvme.h" +#include "libnvme.h" +#include "plugin.h" +#include "nvme-print.h" +#include "solidigm-telemetry.h" +#include "solidigm-telemetry/telemetry-log.h" +#include "solidigm-telemetry/cod.h" +#include "solidigm-telemetry/header.h" +#include "solidigm-telemetry/config.h" +#include "solidigm-telemetry/data-area.h" + +static int read_file2buffer(char *file_name, char **buffer, size_t *length) +{ + FILE *fd = fopen(file_name, "rb"); + + if (!fd) + return errno; + + fseek(fd, 0, SEEK_END); + size_t length_bytes = ftell(fd); + + fseek(fd, 0, SEEK_SET); + + *buffer = malloc(length_bytes); + if (!*buffer) { + fclose(fd); + return errno; + } + *length = fread(*buffer, 1, length_bytes, fd); + fclose(fd); + return 0; +} + +struct config { + __u32 host_gen; + bool ctrl_init; + int data_area; + char *cfg_file; + bool is_input_file; +}; + +int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + const char *desc = "Parse Solidigm Telemetry log"; + const char *hgen = "Controls when to generate new host initiated report. Default value '1' generates new host initiated report, value '0' causes retrieval of existing log."; + const char *cgen = "Gather report generated by the controller."; + const char *dgen = "Pick which telemetry data area to report. Default is 3 to fetch areas 1-3. Valid options are 1, 2, 3, 4."; + const char *cfile = "JSON configuration file"; + const char *sfile = "data source <device> is binary file containing log dump instead of block or character device"; + struct nvme_dev *dev; + + struct telemetry_log tl = { + .root = json_create_object(), + .log = NULL, + }; + + struct config cfg = { + .host_gen = 1, + .ctrl_init = false, + .data_area = 3, + .cfg_file = NULL, + .is_input_file = false, + }; + + OPT_ARGS(opts) = { + OPT_UINT("host-generate", 'g', &cfg.host_gen, hgen), + OPT_FLAG("controller-init", 'c', &cfg.ctrl_init, cgen), + OPT_UINT("data-area", 'd', &cfg.data_area, dgen), + OPT_FILE("config-file", 'j', &cfg.cfg_file, cfile), + OPT_FLAG("source-file", 's', &cfg.is_input_file, sfile), + OPT_END() + }; + + int err = argconfig_parse(argc, argv, desc, opts); + + if (err) + goto ret; + + if (cfg.is_input_file) { + if (optind >= argc) { + err = errno = EINVAL; + perror(argv[0]); + goto ret; + } + char *binary_file_name = argv[optind]; + + err = read_file2buffer(binary_file_name, (char **)&tl.log, &tl.log_size); + } else { + err = parse_and_open(&dev, argc, argv, desc, opts); + } + if (err) + goto ret; + + if (cfg.host_gen > 1) { + SOLIDIGM_LOG_WARNING("Invalid host-generate value '%d'", cfg.host_gen); + err = EINVAL; + goto close_fd; + } + + if (cfg.cfg_file) { + char *conf_str = 0; + size_t length = 0; + + err = read_file2buffer(cfg.cfg_file, &conf_str, &length); + if (err) { + SOLIDIGM_LOG_WARNING("Failed to open JSON configuration file %s: %s!", + cfg.cfg_file, strerror(err)); + goto close_fd; + } + json_tokener * jstok = json_tokener_new(); + + tl.configuration = json_tokener_parse_ex(jstok, conf_str, length); + if (jstok->err != json_tokener_success) { + SOLIDIGM_LOG_WARNING("Parsing error on JSON configuration file %s: %s (at offset %d)", + cfg.cfg_file, + json_tokener_error_desc(jstok->err), + jstok->char_offset); + json_tokener_free(jstok); + err = EINVAL; + goto close_fd; + } + json_tokener_free(jstok); + } + + if (!cfg.is_input_file) { + if (cfg.ctrl_init) + err = nvme_get_ctrl_telemetry(dev_fd(dev), true, + &tl.log, cfg.data_area, + &tl.log_size); + else if (cfg.host_gen) + err = nvme_get_new_host_telemetry(dev_fd(dev), &tl.log, + cfg.data_area, + &tl.log_size); + else + err = nvme_get_host_telemetry(dev_fd(dev), &tl.log, + cfg.data_area, + &tl.log_size); + + if (err < 0) { + SOLIDIGM_LOG_WARNING("get-telemetry-log: %s", + nvme_strerror(errno)); + goto close_fd; + } else if (err > 0) { + nvme_show_status(err); + SOLIDIGM_LOG_WARNING("Failed to acquire telemetry log %d!", err); + goto close_fd; + } + } + solidigm_telemetry_log_header_parse(&tl); + if (cfg.cfg_file) + solidigm_telemetry_log_data_areas_parse(&tl, cfg.data_area); + else + solidigm_telemetry_log_cod_parse(&tl); + + json_print_object(tl.root, NULL); + json_free_object(tl.root); + printf("\n"); + +close_fd: + if (!cfg.is_input_file) { + /* Redundant close() to make static code analysis happy */ + close(dev->direct.fd); + dev_close(dev); + } +ret: + json_free_object(tl.configuration); + free(tl.log); + return err; +} diff --git a/plugins/solidigm/solidigm-telemetry.h b/plugins/solidigm/solidigm-telemetry.h new file mode 100644 index 0000000..971ee2a --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry.h @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin); diff --git a/plugins/solidigm/solidigm-telemetry/cod.c b/plugins/solidigm/solidigm-telemetry/cod.c new file mode 100644 index 0000000..be5685b --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/cod.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ +#include "common.h" +#include "cod.h" + +const char *oemDataMapDesc[] = { + "Media Read Count", //Uid 0x00 + "Host Read count", //Uid 0x01 + "Media Write Count", //Uid 0x02 + "Host Write Count", //Uid 0x03 + "Device Model", // 0x04 + "Serial Number", // 0x05 + "Firmware Revision", // 0x06 + "Drive Status", // 0x07 + "Minimum Temperature", // 0x08 + "Maximum Temperature", // 0x09 + "Power Loss Protection Status", // 0x0a + "Lifetime Unsafe Shutdown Count", // 0x0b + "Lifetime Power Cycle Count", // 0x0c + "Minimum Read Latency", // 0x0d + "Maximum Read Latency", // 0x0e + "Average Read Latency", // 0x0f + "Minimum Write Latency", // 0x10 + "Maximum Write Latency", // 0x11 + "Average Write Latency", // 0x12 + "Grown Defects Count", // 0x13 + "DQS Recovery Count", // 0x14 + "Program Fail Count", // 0x15 + "Erase Fail Count", // 0x16 + "Defrag Writes in Progress Count", // 0x17 + "Total Defrag Writes Count", // 0x18 + "Max Die Offline Number", // 0x19 + "Current Die Offline Number", // 0x1A + "XOR Enable Status", // 0x1B + "Media Life Used", // 0x1C + "Uncorrectable Error Count", // 0x1D + "Current Wear Range Delta", // 0x1E + "Read Errors Corrected by XOR", // 0x1F + "Background Data Refresh", // 0x20 + "Pmic Vin History Data 1 Min", // 0x21 + "Pmic Vin History Data 1 Max", // 0x22 + "Pmic Vin History Data 1 Avg", // 0x23 + "Pmic Vin History Data 2 Min", // 0x24 + "Pmic Vin History Data 2 Max", // 0x25 + "Pmic Vin History Data 2 Avg", // 0x26 + "Pmic Vin History Data Total Readings", // 0x27 + "All Time Current Max Wear Level", // 0x28 + "Media Wear Remaining", // 0x29 + "Total Non-Defrag Writes", // 0x2A + "Number of sectors relocated in reaction to an error" //Uid 0x2B = 43 +}; + +static const char * getOemDataMapDescription(__u32 id) +{ + if (id < (sizeof(oemDataMapDesc) / sizeof(oemDataMapDesc[0]))) { + return oemDataMapDesc[id]; + } + return "unknown"; +} + +#define OEMSIGNATURE 0x504D4443 + +#pragma pack(push, cod, 1) +struct cod_header +{ + uint32_t versionMajor; + uint32_t versionMinor; + uint32_t Signature; //!Fixed signature value (0x504D4443) for identification and validation + uint32_t MapSizeInBytes; //!Total size of the map data structure in bytes + uint32_t EntryCount; //!Total number of entries in the entry list + uint8_t Reserved[12]; +}; + +struct cod_item +{ + uint32_t DataFieldMapUid; //!The data field unique identifier value + uint32_t reserved1 : 8; + uint32_t dataFieldType : 8; + uint32_t issigned : 1; + uint32_t bigEndian : 1; + uint32_t dataInvalid : 1; + uint32_t reserved2 : 13; + uint32_t DataFieldSizeInBytes; + uint8_t Reserved1[4]; + uint64_t DataFieldOffset; + uint8_t Reserved2[8]; +}; + +struct cod_map +{ + struct cod_header header; + struct cod_item items[]; +}; + +#pragma pack(pop, cod) + +void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl) +{ + enum cod_field_type + { + INTEGER, + FLOAT, + STRING, + TWO_BYTE_ASCII, + FOUR_BYTE_ASCII, + + UNKNOWN = 0xFF, + }; + json_object *telemetry_header = NULL; + json_object *COD_offset = NULL; + json_object *reason_id = NULL; + + if (!json_object_object_get_ex(tl->root, "telemetryHeader", &telemetry_header)) + return; + if (!json_object_object_get_ex(telemetry_header, "reasonIdentifier", &reason_id)) + return; + if (!json_object_object_get_ex(reason_id, "OemDataMapOffset", &COD_offset)) + return; + + __u64 offset = json_object_get_int(COD_offset); + + if (offset == 0) { + return; + } + + if ((offset + sizeof(struct cod_header)) > tl->log_size) { + SOLIDIGM_LOG_WARNING("Warning: COD map header out of bounds."); + return; + } + + const struct cod_map *data = (struct cod_map *) (((__u8 *)tl->log ) + offset); + + uint32_t signature = be32_to_cpu(data->header.Signature); + if ( signature != OEMSIGNATURE){ + SOLIDIGM_LOG_WARNING("Warning: Unsupported COD data signature %x!", signature); + return; + } + if ((offset + data->header.MapSizeInBytes) > tl->log_size){ + SOLIDIGM_LOG_WARNING("Warning: COD map data out of bounds."); + return; + } + + json_object *cod = json_create_object(); + json_object_object_add(tl->root, "cod", cod); + + for (int i =0 ; i < data->header.EntryCount; i++) { + if ((offset + sizeof(struct cod_header) + (i + 1) * sizeof(struct cod_item)) > + tl->log_size){ + SOLIDIGM_LOG_WARNING("Warning: COD data out of bounds at item %d!", i); + return; + } + struct cod_item item = data->items[i]; + if (item.DataFieldOffset + item.DataFieldOffset > tl->log_size) { + continue; + } + if (item.dataInvalid) { + continue; + } + uint8_t *val = ((uint8_t *)tl->log )+ item.DataFieldOffset; + const char *key = getOemDataMapDescription(item.DataFieldMapUid); + switch(item.dataFieldType){ + case(INTEGER): + if (item.issigned) { + json_object_object_add(cod, key, + json_object_new_int64(le64_to_cpu(*(uint64_t *)val))); + } else { + json_object_add_value_uint64(cod, key, le64_to_cpu(*(uint64_t *)val)); + } + break; + case(FLOAT): + json_object_add_value_float(cod, key, *(float *) val); + break; + case(STRING): + json_object_object_add(cod, key, + json_object_new_string_len((const char *)val, item.DataFieldSizeInBytes)); + break; + case(TWO_BYTE_ASCII): + json_object_object_add(cod, key, + json_object_new_string_len((const char *)val,2)); + break; + case(FOUR_BYTE_ASCII): + json_object_object_add(cod, key, + json_object_new_string_len((const char *)val, 4)); + break; + default: + SOLIDIGM_LOG_WARNING("Warning: Unknown COD field type (%d)", item.DataFieldMapUid); + + } + } +} diff --git a/plugins/solidigm/solidigm-telemetry/cod.h b/plugins/solidigm/solidigm-telemetry/cod.h new file mode 100644 index 0000000..032ccdc --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/cod.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include "telemetry-log.h" +void solidigm_telemetry_log_cod_parse(struct telemetry_log *tl); diff --git a/plugins/solidigm/solidigm-telemetry/config.c b/plugins/solidigm/solidigm-telemetry/config.c new file mode 100644 index 0000000..781d786 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/config.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ +#include <stdbool.h> +#include "util/json.h" +#include <stdio.h> + +// max 16 bit unsigned integer nummber 65535 +#define MAX_16BIT_NUM_AS_STRING_SIZE 6 + +static bool config_get_by_version(const json_object *obj, int version_major, + int version_minor, json_object **value) +{ + char str_key[MAX_16BIT_NUM_AS_STRING_SIZE]; + char str_subkey[MAX_16BIT_NUM_AS_STRING_SIZE]; + + snprintf(str_key, sizeof(str_key), "%d", version_major); + snprintf(str_subkey, sizeof(str_subkey), "%d", version_minor); + json_object *major_obj = NULL; + + if (!json_object_object_get_ex(obj, str_key, &major_obj)) + return false; + if (!json_object_object_get_ex(major_obj, str_subkey, value)) + return false; + return value != NULL; +} + +bool solidigm_config_get_by_token_version(const json_object *obj, int token_id, + int version_major, int version_minor, + json_object **value) +{ + json_object *token_obj = NULL; + char str_key[MAX_16BIT_NUM_AS_STRING_SIZE]; + + snprintf(str_key, sizeof(str_key), "%d", token_id); + if (!json_object_object_get_ex(obj, str_key, &token_obj)) + return false; + if (!config_get_by_version(token_obj, version_major, version_minor, value)) + return false; + return value != NULL; +} diff --git a/plugins/solidigm/solidigm-telemetry/config.h b/plugins/solidigm/solidigm-telemetry/config.h new file mode 100644 index 0000000..bea84fb --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/config.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ +#include <stdbool.h> +#include "util/json.h" + +bool solidigm_config_get_by_token_version(const json_object *obj, int key, int subkey, int subsubkey, json_object **value); diff --git a/plugins/solidigm/solidigm-telemetry/data-area.c b/plugins/solidigm/solidigm-telemetry/data-area.c new file mode 100644 index 0000000..7233e8f --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/data-area.c @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include "common.h" +#include "data-area.h" +#include "config.h" +#include <ctype.h> + +#define SIGNED_INT_PREFIX "int" +#define BITS_IN_BYTE 8 + +#define MAX_WARNING_SIZE 1024 + +static bool telemetry_log_get_value(const struct telemetry_log *tl, + uint32_t offset_bit, uint32_t size_bit, + bool is_signed, json_object **val_obj) +{ + uint32_t offset_bit_from_byte; + uint32_t additional_size_byte; + uint32_t offset_byte; + uint32_t val; + + if (size_bit == 0) { + char err_msg[MAX_WARNING_SIZE]; + + snprintf(err_msg, MAX_WARNING_SIZE, + "Value with size_bit=0 not supported."); + *val_obj = json_object_new_string(err_msg); + + return false; + } + additional_size_byte = (size_bit - 1) ? (size_bit - 1) / BITS_IN_BYTE : 0; + offset_byte = offset_bit / BITS_IN_BYTE; + + if (offset_byte > (tl->log_size - additional_size_byte)) { + char err_msg[MAX_WARNING_SIZE]; + + snprintf(err_msg, MAX_WARNING_SIZE, + "Value offset greater than binary size (%u > %zu).", + offset_byte, tl->log_size); + *val_obj = json_object_new_string(err_msg); + + return false; + } + + offset_bit_from_byte = offset_bit - (offset_byte * BITS_IN_BYTE); + + if ((size_bit + offset_bit_from_byte) > (sizeof(uint64_t) * BITS_IN_BYTE)) { + char err_msg[MAX_WARNING_SIZE]; + + snprintf(err_msg, MAX_WARNING_SIZE, + "Value crossing 64 bit, byte aligned bounday, " + "not supported. size_bit=%u, offset_bit_from_byte=%u.", + size_bit, offset_bit_from_byte); + *val_obj = json_object_new_string(err_msg); + + return false; + } + + val = *(uint64_t *)(((char *)tl->log) + offset_byte); + val >>= offset_bit_from_byte; + if (size_bit < 64) + val &= (1ULL << size_bit) - 1; + if (is_signed) { + if (val >> (size_bit - 1)) + val |= -1ULL << size_bit; + *val_obj = json_object_new_int64(val); + } else { + *val_obj = json_object_new_uint64(val); + } + + return true; +} + +static int telemetry_log_structure_parse(const struct telemetry_log *tl, + json_object *struct_def, + size_t parent_offset_bit, + json_object *output, + json_object *metadata) +{ + json_object *obj_arraySizeArray = NULL; + json_object *obj = NULL; + json_object *obj_memberList; + json_object *major_dimension; + json_object *sub_output; + bool is_enumeration = false; + bool has_member_list; + const char *type = ""; + const char *name; + size_t array_rank; + size_t offset_bit; + size_t size_bit; + uint32_t linear_array_pos_bit; + + if (!json_object_object_get_ex(struct_def, "name", &obj)) { + SOLIDIGM_LOG_WARNING("Warning: Structure definition missing property 'name': %s", + json_object_to_json_string(struct_def)); + return -1; + } + + name = json_object_get_string(obj); + + if (metadata) { + json_object_get(obj); + json_object_object_add(metadata, "objName", obj); + } + + if (json_object_object_get_ex(struct_def, "type", &obj)) + type = json_object_get_string(obj); + + if (!json_object_object_get_ex(struct_def, "offsetBit", &obj)) { + SOLIDIGM_LOG_WARNING("Warning: Structure definition missing " + "property 'offsetBit': %s", + json_object_to_json_string(struct_def)); + return -1; + } + + offset_bit = json_object_get_uint64(obj); + + if (!json_object_object_get_ex(struct_def, "sizeBit", &obj)) { + SOLIDIGM_LOG_WARNING("Warning: Structure definition missing " + "property 'sizeBit': %s", + json_object_to_json_string(struct_def)); + return -1; + } + + size_bit = json_object_get_uint64(obj); + + if (json_object_object_get_ex(struct_def, "enum", &obj)) + is_enumeration = json_object_get_boolean(obj); + + has_member_list = json_object_object_get_ex(struct_def, + "memberList", + &obj_memberList); + + if (!json_object_object_get_ex(struct_def, "arraySize", + &obj_arraySizeArray)) { + SOLIDIGM_LOG_WARNING("Warning: Structure definition missing " + "property 'arraySize': %s", + json_object_to_json_string(struct_def)); + return -1; + } + + array_rank = json_object_array_length(obj_arraySizeArray); + if (array_rank == 0) { + SOLIDIGM_LOG_WARNING("Warning: Structure property 'arraySize' " + "don't support flexible array: %s", + json_object_to_json_string(struct_def)); + return -1; + } + uint32_t array_size_dimension[array_rank]; + + for (size_t i = 0; i < array_rank; i++) { + json_object *dimension = json_object_array_get_idx(obj_arraySizeArray, i); + + array_size_dimension[i] = json_object_get_uint64(dimension); + major_dimension = dimension; + } + if (array_rank > 1) { + uint32_t linear_pos_per_index = array_size_dimension[0]; + uint32_t prev_index_offset_bit = 0; + json_object *dimension_output; + + for (int i = 1; i < (array_rank - 1); i++) + linear_pos_per_index *= array_size_dimension[i]; + + dimension_output = json_create_array(); + if (json_object_get_type(output) == json_type_array) + json_object_array_add(output, dimension_output); + else + json_object_add_value_array(output, name, dimension_output); + + /* + * Make sure major_dimension object will not be + * deleted from memory when deleted from array + */ + json_object_get(major_dimension); + json_object_array_del_idx(obj_arraySizeArray, array_rank - 1, 1); + + for (int i = 0 ; i < array_size_dimension[0]; i++) { + json_object *sub_array = json_create_array(); + size_t offset; + + offset = parent_offset_bit + prev_index_offset_bit; + + json_object_array_add(dimension_output, sub_array); + telemetry_log_structure_parse(tl, struct_def, + offset, sub_array, NULL); + prev_index_offset_bit += linear_pos_per_index * size_bit; + } + + json_object_array_put_idx(obj_arraySizeArray, array_rank - 1, + major_dimension); + + return 0; + } + + linear_array_pos_bit = 0; + sub_output = output; + + if (array_size_dimension[0] > 1) { + sub_output = json_create_array(); + if (json_object_get_type(output) == json_type_array) + json_object_array_add(output, sub_output); + else + json_object_add_value_array(output, name, sub_output); + } + + for (uint32_t j = 0; j < array_size_dimension[0]; j++) { + if (is_enumeration || !has_member_list) { + bool is_signed = !strncmp(type, SIGNED_INT_PREFIX, sizeof(SIGNED_INT_PREFIX)-1); + json_object *val_obj; + size_t offset; + + offset = parent_offset_bit + offset_bit + linear_array_pos_bit; + if (telemetry_log_get_value(tl, offset, size_bit, is_signed, &val_obj)) { + if (array_size_dimension[0] > 1) + json_object_array_put_idx(sub_output, j, val_obj); + else + json_object_object_add(sub_output, name, val_obj); + } else { + SOLIDIGM_LOG_WARNING("Warning: %s From property '%s', " + "array index %u, structure definition: %s", + json_object_get_string(val_obj), + name, j, json_object_to_json_string(struct_def)); + json_free_object(val_obj); + } + } else { + json_object *sub_sub_output = json_object_new_object(); + int num_members; + + if (array_size_dimension[0] > 1) + json_object_array_put_idx(sub_output, j, sub_sub_output); + else + json_object_add_value_object(sub_output, name, sub_sub_output); + + num_members = json_object_array_length(obj_memberList); + for (int k = 0; k < num_members; k++) { + json_object *member = json_object_array_get_idx(obj_memberList, k); + size_t offset; + + offset = parent_offset_bit + offset_bit + linear_array_pos_bit; + telemetry_log_structure_parse(tl, member, offset, + sub_sub_output, NULL); + } + } + linear_array_pos_bit += size_bit; + } + return 0; +} + +static int telemetry_log_data_area_get_offset(const struct telemetry_log *tl, + enum nvme_telemetry_da da, + uint32_t *offset, uint32_t *size) +{ + uint32_t offset_blocks = 1; + uint32_t last_block = tl->log->dalb1; + uint32_t last; + + switch (da) { + case NVME_TELEMETRY_DA_1: + offset_blocks = 1; + last_block = tl->log->dalb1; + break; + case NVME_TELEMETRY_DA_2: + offset_blocks = tl->log->dalb1 + 1; + last_block = tl->log->dalb2; + break; + case NVME_TELEMETRY_DA_3: + offset_blocks = tl->log->dalb2 + 1; + last_block = tl->log->dalb3; + break; + case NVME_TELEMETRY_DA_4: + offset_blocks = tl->log->dalb3 + 1; + last_block = tl->log->dalb4; + break; + default: + return -1; + } + + *offset = offset_blocks * NVME_LOG_TELEM_BLOCK_SIZE; + last = (last_block + 1) * NVME_LOG_TELEM_BLOCK_SIZE; + *size = last - *offset; + if ((*offset > tl->log_size) || (last > tl->log_size) || (last <= *offset)) { + SOLIDIGM_LOG_WARNING("Warning: Data Area %d don't fit this Telemetry log.", da); + return -1; + } + + return 0; +} + +struct toc_item { + uint32_t OffsetBytes; + uint32_t ContentSizeBytes; +}; + +struct data_area_header { + uint8_t versionMajor; + uint8_t versionMinor; + uint16_t TableOfContentsCount; + uint32_t DataAreaSize; + uint8_t Reserved[8]; +}; + +struct table_of_contents { + struct data_area_header header; + struct toc_item items[]; +}; + +struct telemetry_object_header { + uint16_t versionMajor; + uint16_t versionMinor; + uint32_t Token; + uint8_t CoreId; + uint8_t Reserved[3]; +}; + + +static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, + enum nvme_telemetry_da da, + json_object *toc_array, + json_object *tele_obj_array) +{ + + const struct telemetry_object_header *header; + const struct table_of_contents *toc; + char *payload; + uint32_t da_offset; + uint32_t da_size; + + if (telemetry_log_data_area_get_offset(tl, da, &da_offset, &da_size)) + return; + + toc = (struct table_of_contents *)(((char *)tl->log) + da_offset); + payload = (char *) tl->log; + + for (int i = 0; i < toc->header.TableOfContentsCount; i++) { + json_object *structure_definition = NULL; + json_object *toc_item; + uint32_t obj_offset; + bool has_struct; + + if ((char *)&toc->items[i] > (((char *)toc) + da_size - sizeof(const struct toc_item))) { + SOLIDIGM_LOG_WARNING("Warning: Data Area %d, " + "Table of Contents item %d " + "crossed Data Area size.", da, i); + return; + } + + obj_offset = toc->items[i].OffsetBytes; + if ((obj_offset + sizeof(const struct telemetry_object_header)) > da_size) { + SOLIDIGM_LOG_WARNING("Warning: Data Area %d, item %d " + "data, crossed Data Area size.", da, i); + continue; + } + + toc_item = json_create_object(); + json_object_array_add(toc_array, toc_item); + json_object_add_value_uint(toc_item, "dataArea", da); + json_object_add_value_uint(toc_item, "dataAreaIndex", i); + json_object_add_value_uint(toc_item, "dataAreaOffset", obj_offset); + json_object_add_value_uint(toc_item, "fileOffset", obj_offset + da_offset); + json_object_add_value_uint(toc_item, "size", toc->items[i].ContentSizeBytes); + + header = (const struct telemetry_object_header *) (payload + da_offset + obj_offset); + json_object_add_value_uint(toc_item, "telemMajor", header->versionMajor); + json_object_add_value_uint(toc_item, "telemMinor", header->versionMinor); + json_object_add_value_uint(toc_item, "objectId", header->Token); + json_object_add_value_uint(toc_item, "mediaBankId", header->CoreId); + + has_struct = solidigm_config_get_by_token_version(tl->configuration, + header->Token, + header->versionMajor, + header->versionMinor, + &structure_definition); + + if (has_struct) { + json_object *tele_obj_item = json_create_object(); + + json_object_array_add(tele_obj_array, tele_obj_item); + json_object_get(toc_item); + json_object_add_value_object(tele_obj_item, "metadata", toc_item); + json_object *parsed_struct = json_object_new_object(); + + json_object_add_value_object(tele_obj_item, "objectData", parsed_struct); + json_object *obj_hasTelemObjHdr = NULL; + uint32_t header_offset = sizeof(const struct telemetry_object_header); + uint32_t file_offset; + + if (json_object_object_get_ex(structure_definition, + "hasTelemObjHdr", + &obj_hasTelemObjHdr)) { + bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr); + + if (hasHeader) + header_offset = 0; + } + + file_offset = da_offset + obj_offset + header_offset; + telemetry_log_structure_parse(tl, structure_definition, + BITS_IN_BYTE * file_offset, + parsed_struct, toc_item); + } + } +} + +int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl, + enum nvme_telemetry_da last_da) +{ + json_object *tele_obj_array = json_create_array(); + json_object *toc_array = json_create_array(); + + json_object_add_value_array(tl->root, "tableOfContents", toc_array); + json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array); + + for (enum nvme_telemetry_da da = NVME_TELEMETRY_DA_1; da <= last_da; da++) + telemetry_log_data_area_toc_parse(tl, da, toc_array, tele_obj_array); + + return 0; +} diff --git a/plugins/solidigm/solidigm-telemetry/data-area.h b/plugins/solidigm/solidigm-telemetry/data-area.h new file mode 100644 index 0000000..095eb64 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/data-area.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ +#include "common.h" +#include "telemetry-log.h" + +int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl, + enum nvme_telemetry_da last_da); diff --git a/plugins/solidigm/solidigm-telemetry/header.c b/plugins/solidigm/solidigm-telemetry/header.c new file mode 100644 index 0000000..72b2d97 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/header.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include "common.h" +#include "header.h" + +#pragma pack(push, reason_indentifier, 1) +struct reason_indentifier_1_0 +{ + uint16_t versionMajor; + uint16_t versionMinor; + uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue. + char DriveStatus[20]; //! Drive Status String (for example: "Healthy", "*BAD_CONTEXT_2020") + char FirmwareVersion[12]; //! Similar to IdentifyController.FR + char BootloaderVersion[12]; //! Bootloader version string + char SerialNumber[20]; //! Device serial number + uint8_t Reserved[56]; //! Reserved for future usage +}; +static_assert(sizeof(const struct reason_indentifier_1_0) == + MEMBER_SIZE(struct nvme_telemetry_log, rsnident), + "Size mismatch for reason_indentifier_1_0"); + +struct reason_indentifier_1_1 +{ + uint16_t versionMajor; + uint16_t versionMinor; + uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue. + char DriveStatus[20]; //! Drive Status String (for example: "Healthy", "*BAD_CONTEXT_2020") + char FirmwareVersion[12]; //! Similar to IdentifyController.FR + char BootloaderVersion[12]; //! Bootloader version string + char SerialNumber[20]; //! Device serial number + uint64_t OemDataMapOffset; //! Customer Data Map Object Log Offset + uint8_t TelemetryMajorVersion; //! Shadow of version in TOC + uint8_t TelemetryMinorVersion; //! Shadow of version in TOC + uint8_t Reserved[46]; //! Reserved for future usage +}; +static_assert(sizeof(const struct reason_indentifier_1_1) == + MEMBER_SIZE(struct nvme_telemetry_log, rsnident), + "Size mismatch for reason_indentifier_1_1"); + +struct reason_indentifier_1_2 +{ + uint16_t versionMajor; + uint16_t versionMinor; + uint32_t reasonCode; //! 0 denotes no issue. All other values denote a potential issue. + char DriveStatus[20]; //! Drive Status String (for example: "Healthy", "*BAD_CONTEXT_2020") + uint8_t Reserved1[24]; //! pad over Fields removed from version 1.1 + char SerialNumber[20]; //! Device serial number + uint64_t OemDataMapOffset; //! Customer Data Map Object Log Offset + uint8_t TelemetryMajorVersion; //! Shadow of version in TOC + uint8_t TelemetryMinorVersion; //! Shadow of version in TOC + uint8_t ProductFamilyId; + uint8_t Reserved2[5]; //! Reserved for future usage + uint8_t DualPortReserved[40]; //! Reserved for dual port +}; +static_assert(sizeof(const struct reason_indentifier_1_2) == + MEMBER_SIZE(struct nvme_telemetry_log, rsnident), + "Size mismatch for reason_indentifier_1_2"); +#pragma pack(pop, reason_indentifier) + +static void telemetry_log_reason_id_parse1_0_ext(const struct telemetry_log *tl, + json_object *reason_id) +{ + const struct reason_indentifier_1_0 *ri; + json_object *reserved; + + ri = (struct reason_indentifier_1_0 *) tl->log->rsnident; + json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion))); + json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion))); + json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber))); + + reserved = json_create_array(); + json_object_add_value_array(reason_id, "Reserved", reserved); + for ( int i=0; i < sizeof(ri->Reserved); i++) { + json_object *val = json_object_new_int(ri->Reserved[i]); + json_object_array_add(reserved, val); + } +} + +static void telemetry_log_reason_id_parse1_1_ext(const struct telemetry_log *tl, + json_object *reason_id) +{ + const struct reason_indentifier_1_1 *ri; + json_object *reserved; + + ri = (struct reason_indentifier_1_1 *) tl->log->rsnident; + json_object_object_add(reason_id, "FirmwareVersion", json_object_new_string_len(ri->FirmwareVersion, sizeof(ri->FirmwareVersion))); + json_object_object_add(reason_id, "BootloaderVersion", json_object_new_string_len(ri->BootloaderVersion, sizeof(ri->BootloaderVersion))); + json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber))); + json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset)); + json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion)); + json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion)); + + reserved = json_create_array(); + json_object_add_value_array(reason_id, "Reserved", reserved); + for (int i = 0; i < sizeof(ri->Reserved); i++) { + json_object *val = json_object_new_int(ri->Reserved[i]); + json_object_array_add(reserved, val); + } +} + +static void telemetry_log_reason_id_parse1_2_ext(const struct telemetry_log *tl, + json_object *reason_id) +{ + const struct reason_indentifier_1_2 *ri; + json_object *dp_reserved; + json_object *reserved; + + ri = (struct reason_indentifier_1_2 *) tl->log->rsnident; + + json_object_object_add(reason_id, "SerialNumber", json_object_new_string_len(ri->SerialNumber, sizeof(ri->SerialNumber))); + json_object_add_value_uint64(reason_id, "OemDataMapOffset", le64_to_cpu(ri->OemDataMapOffset)); + json_object_add_value_uint(reason_id, "TelemetryMajorVersion", le16_to_cpu(ri->TelemetryMajorVersion)); + json_object_add_value_uint(reason_id, "TelemetryMinorVersion", le16_to_cpu(ri->TelemetryMinorVersion)); + json_object_add_value_uint(reason_id, "ProductFamilyId", ri->ProductFamilyId); + + reserved = json_create_array(); + json_object_add_value_array(reason_id, "Reserved2", reserved); + for (int i = 0; i < sizeof(ri->Reserved2); i++) { + json_object *val = json_object_new_int(ri->Reserved2[i]); + json_object_array_add(reserved, val); + } + + dp_reserved = json_create_array(); + json_object_add_value_array(reason_id, "DualPortReserved", dp_reserved); + for (int i = 0; i < sizeof(ri->DualPortReserved); i++) { + json_object *val = json_object_new_int(ri->DualPortReserved[i]); + json_object_array_add(dp_reserved, val); + } +} + +static void solidigm_telemetry_log_reason_id_parse(const struct telemetry_log *tl, json_object *reason_id) +{ + const struct reason_indentifier_1_0 *ri1_0 = + (struct reason_indentifier_1_0 *) tl->log->rsnident; + __u16 version_major = le16_to_cpu(ri1_0->versionMajor); + __u16 version_minor = le16_to_cpu(ri1_0->versionMinor); + + json_object_add_value_uint(reason_id, "versionMajor", version_major); + json_object_add_value_uint(reason_id, "versionMinor", version_minor); + json_object_add_value_uint(reason_id, "reasonCode", le32_to_cpu(ri1_0->reasonCode)); + json_object_add_value_object(reason_id, "DriveStatus", json_object_new_string_len(ri1_0->DriveStatus, sizeof(ri1_0->DriveStatus))); + if (version_major == 1) { + switch (version_minor) { + case 0: + telemetry_log_reason_id_parse1_0_ext(tl, reason_id); + break; + case 1: + telemetry_log_reason_id_parse1_1_ext(tl, reason_id); + break; + default: + telemetry_log_reason_id_parse1_2_ext(tl, reason_id); + } + } +} + +bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl) +{ + const struct nvme_telemetry_log *log; + json_object *ieee_oui_id; + json_object *reason_id; + json_object *header; + + if (tl->log_size < sizeof(const struct nvme_telemetry_log)) { + SOLIDIGM_LOG_WARNING("Telemetry log too short."); + return false; + } + + header = json_create_object(); + + json_object_object_add(tl->root, "telemetryHeader", header); + log = tl->log; + + json_object_add_value_uint(header, "logIdentifier", log->lpi); + ieee_oui_id = json_create_array(); + + json_object_object_add(header, "ieeeOuiIdentifier", ieee_oui_id); + for (int i = 0; i < sizeof(log->ieee); i++) { + json_object *val = json_object_new_int(log->ieee[i]); + + json_object_array_add(ieee_oui_id, val); + } + json_object_add_value_uint(header, "dataArea1LastBlock", log->dalb1); + json_object_add_value_uint(header, "dataArea2LastBlock", log->dalb2); + json_object_add_value_uint(header, "dataArea3LastBlock", log->dalb3); + json_object_add_value_uint(header, "hostInitiatedDataGeneration", log->hostdgn); + json_object_add_value_uint(header, "controllerInitiatedDataAvailable", log->ctrlavail); + json_object_add_value_uint(header, "controllerInitiatedDataGeneration", log->ctrldgn); + + reason_id = json_create_object(); + json_object_add_value_object(header, "reasonIdentifier", reason_id); + solidigm_telemetry_log_reason_id_parse(tl, reason_id); + + return true; +} diff --git a/plugins/solidigm/solidigm-telemetry/header.h b/plugins/solidigm/solidigm-telemetry/header.h new file mode 100644 index 0000000..027af55 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/header.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#include "telemetry-log.h" +bool solidigm_telemetry_log_header_parse(const struct telemetry_log *tl); diff --git a/plugins/solidigm/solidigm-telemetry/meson.build b/plugins/solidigm/solidigm-telemetry/meson.build new file mode 100644 index 0000000..53ab452 --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/meson.build @@ -0,0 +1,6 @@ +sources += [ + 'plugins/solidigm/solidigm-telemetry/cod.c', + 'plugins/solidigm/solidigm-telemetry/header.c', + 'plugins/solidigm/solidigm-telemetry/config.c', + 'plugins/solidigm/solidigm-telemetry/data-area.c', +] diff --git a/plugins/solidigm/solidigm-telemetry/telemetry-log.h b/plugins/solidigm/solidigm-telemetry/telemetry-log.h new file mode 100644 index 0000000..ef4ec5d --- /dev/null +++ b/plugins/solidigm/solidigm-telemetry/telemetry-log.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2022 Solidigm. + * + * Author: leonardo.da.cunha@solidigm.com + */ + +#ifndef _SOLIDIGM_TELEMETRY_LOG_H +#define _SOLIDIGM_TELEMETRY_LOG_H + +#include "libnvme.h" +#include "util/json.h" +#include <assert.h> + +#if !defined __cplusplus +#define static_assert _Static_assert +#endif + +#define VA_ARGS(...), ##__VA_ARGS__ +#define SOLIDIGM_LOG_WARNING(format, ...) fprintf(stderr, format"\n" VA_ARGS(__VA_ARGS__)) + +#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) + +struct telemetry_log { + struct nvme_telemetry_log *log; + size_t log_size; + json_object *root; + json_object *configuration; +}; + +#endif /* _SOLIDIGM_TELEMETRY_LOG_H */
\ No newline at end of file diff --git a/plugins/toshiba/toshiba-nvme.c b/plugins/toshiba/toshiba-nvme.c index cf19352..5540fea 100644 --- a/plugins/toshiba/toshiba-nvme.c +++ b/plugins/toshiba/toshiba-nvme.c @@ -361,11 +361,11 @@ struct nvme_xdn_smart_log_c0 { __u8 resv[512 - NR_SMART_ITEMS_C0]; }; -static void default_show_vendor_log_c0(int fd, __u32 nsid, const char *devname, +static void default_show_vendor_log_c0(struct nvme_dev *dev, __u32 nsid, struct nvme_xdn_smart_log_c0 *smart) { printf("Vendor Log Page Directory 0xC0 for NVME device:%s namespace-id:%x\n", - devname, nsid); + dev->name, nsid); printf("Error Log : %u \n", smart->items[ERROR_LOG_C0]); printf("SMART Health Log : %u \n", smart->items[SMART_HEALTH_LOG_C0]); printf("Firmware Slot Info : %u \n", smart->items[FIRMWARE_SLOT_INFO_C0]); @@ -375,8 +375,8 @@ static void default_show_vendor_log_c0(int fd, __u32 nsid, const char *devname, printf("SMART Attributes : %u \n", smart->items[SMART_ATTRIBUTES_C0]); } -static int nvme_get_vendor_log(int fd, __u32 namespace_id, int log_page, - const char* const filename) +static int nvme_get_vendor_log(struct nvme_dev *dev, __u32 namespace_id, + int log_page, const char* const filename) { int err; void* log = NULL; @@ -388,11 +388,12 @@ static int nvme_get_vendor_log(int fd, __u32 namespace_id, int log_page, } /* Check device supported */ - err = nvme_get_sct_status(fd, MASK_0 | MASK_1); + err = nvme_get_sct_status(dev_fd(dev), MASK_0 | MASK_1); if (err) { goto end; } - err = nvme_get_nsid_log(fd, false, log_page, namespace_id, log_len, log); + err = nvme_get_nsid_log(dev_fd(dev), false, log_page, namespace_id, + log_len, log); if (err) { fprintf(stderr, "%s: couldn't get log 0x%x\n", __func__, log_page); @@ -419,8 +420,7 @@ static int nvme_get_vendor_log(int fd, __u32 namespace_id, int log_page, } } else { if (log_page == 0xc0) - default_show_vendor_log_c0(fd, namespace_id, devicename, - (struct nvme_xdn_smart_log_c0 *)log); + default_show_vendor_log_c0(dev, namespace_id, log); else d(log, log_len,16,1); } @@ -433,11 +433,12 @@ end: static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err, fd; char *desc = "Get extended SMART information and show it."; const char *namespace = "(optional) desired namespace"; const char *output_file = "(optional) binary output filename"; const char *log = "(optional) log ID (0xC0, or 0xCA), default 0xCA"; + struct nvme_dev *dev; + int err; struct config { __u32 namespace_id; @@ -458,8 +459,8 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { fprintf(stderr,"%s: failed to parse arguments\n", __func__); return EINVAL; } @@ -470,22 +471,24 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin goto end; } - err = nvme_get_vendor_log(fd, cfg.namespace_id, cfg.log, cfg.output_file); + err = nvme_get_vendor_log(dev, cfg.namespace_id, cfg.log, + cfg.output_file); if (err) fprintf(stderr, "%s: couldn't get vendor log 0x%x\n", __func__, cfg.log); end: if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } static int internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err, fd; char *desc = "Get internal status log and show it."; const char *output_file = "(optional) binary output filename"; const char *prev_log = "(optional) use previous log. Otherwise uses current log."; + struct nvme_dev *dev; + int err; struct config { const char* output_file; @@ -503,8 +506,8 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { fprintf(stderr,"%s: failed to parse arguments\n", __func__); return EINVAL; } @@ -514,46 +517,48 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi else printf("Getting current log\n"); - err = nvme_get_internal_log_file(fd, cfg.output_file, !cfg.prev_log); + err = nvme_get_internal_log_file(dev_fd(dev), cfg.output_file, + !cfg.prev_log); if (err < 0) fprintf(stderr, "%s: couldn't get fw log \n", __func__); if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } static int clear_correctable_errors(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err, fd; char *desc = "Clear PCIe correctable error count."; const __u32 namespace_id = 0xFFFFFFFF; const __u32 feature_id = 0xCA; const __u32 value = 1; /* Bit0 - reset clear PCIe correctable count */ const __u32 cdw12 = 0; const bool save = false; + struct nvme_dev *dev; __u32 result; + int err; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { fprintf(stderr,"%s: failed to parse arguments\n", __func__); return EINVAL; } /* Check device supported */ - err = nvme_get_sct_status(fd, MASK_0 | MASK_1); + err = nvme_get_sct_status(dev_fd(dev), MASK_0 | MASK_1); if (err) goto end; struct nvme_set_features_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .fid = feature_id, .nsid = namespace_id, .cdw11 = value, @@ -573,6 +578,6 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd, end: if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } diff --git a/plugins/transcend/transcend-nvme.c b/plugins/transcend/transcend-nvme.c index a3b739d..024351f 100644 --- a/plugins/transcend/transcend-nvme.c +++ b/plugins/transcend/transcend-nvme.c @@ -21,20 +21,20 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu { struct nvme_smart_log smart_log; char *desc = "Get nvme health percentage."; - int result=0, fd; int percent_used = 0, healthvalue=0; - + struct nvme_dev *dev; + int result; + OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - - if (fd < 0) { + result = parse_and_open(&dev, argc, argv, desc, opts); + if (result) { printf("\nDevice not found \n");; return -1; } - result = nvme_get_log_smart(fd, 0xffffffff, false, &smart_log); + result = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log); if (!result) { printf("Transcend NVME heath value: "); percent_used =smart_log.percent_used; @@ -50,7 +50,7 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu } } - close(fd); + dev_close(dev); return result; } @@ -59,15 +59,16 @@ static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin { char *desc = "Get nvme bad block number."; - int result=0, fd; + struct nvme_dev *dev; + int result; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + result = parse_and_open(&dev, argc, argv, desc, opts); + if (result) { printf("\nDevice not found \n");; return -1; } @@ -79,11 +80,11 @@ static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin nvmecmd.cdw12=DW12_BAD_BLOCK; nvmecmd.addr = (__u64)(uintptr_t)data; nvmecmd.data_len = 0x1; - result = nvme_submit_admin_passthru(fd, &nvmecmd, NULL); + result = nvme_submit_admin_passthru(dev_fd(dev), &nvmecmd, NULL); if(!result) { int badblock = data[0]; printf("Transcend NVME badblock count: %d\n",badblock); } - close(fd); + dev_close(dev); return result; } diff --git a/plugins/virtium/virtium-nvme.c b/plugins/virtium/virtium-nvme.c index b8cefe6..c8df126 100644 --- a/plugins/virtium/virtium-nvme.c +++ b/plugins/virtium/virtium-nvme.c @@ -14,6 +14,7 @@ #include "nvme.h" #include "libnvme.h" #include "plugin.h" +#include "util/types.h" #define CREATE_CMD #include "virtium-nvme.h" @@ -51,18 +52,6 @@ struct vtview_save_log_settings { const char* test_name; }; -static long double int128_to_double(__u8 *data) -{ - int i; - long double result = 0; - - for (i = 0; i < 16; i++) { - result *= 256; - result += data[15 - i]; - } - return result; -} - static void vt_initialize_header_buffer(struct vtview_log_header *pbuff) { memset(pbuff->path, 0, sizeof(pbuff->path)); @@ -151,25 +140,25 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l strcat(text, tempbuff); snprintf(tempbuff, sizeof(tempbuff), "Percentage_Used;%u;", smart->raw_smart.percent_used); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Data_Units_Read;%0.Lf;", int128_to_double(smart->raw_smart.data_units_read)); + snprintf(tempbuff, sizeof(tempbuff), "Data_Units_Read;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.data_units_read))); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Data_Units_Written;%0.Lf;", int128_to_double(smart->raw_smart.data_units_written)); + snprintf(tempbuff, sizeof(tempbuff), "Data_Units_Written;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.data_units_written))); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Host_Read_Commands;%0.Lf;", int128_to_double(smart->raw_smart.host_reads)); + snprintf(tempbuff, sizeof(tempbuff), "Host_Read_Commands;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.host_reads))); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Host_Write_Commands;%0.Lf;", int128_to_double(smart->raw_smart.host_writes)); + snprintf(tempbuff, sizeof(tempbuff), "Host_Write_Commands;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.host_writes))); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Controller_Busy_Time;%0.Lf;", int128_to_double(smart->raw_smart.ctrl_busy_time)); + snprintf(tempbuff, sizeof(tempbuff), "Controller_Busy_Time;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.ctrl_busy_time))); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Power_Cycles;%0.Lf;", int128_to_double(smart->raw_smart.power_cycles)); + snprintf(tempbuff, sizeof(tempbuff), "Power_Cycles;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.power_cycles))); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Power_On_Hours;%0.Lf;", int128_to_double(smart->raw_smart.power_on_hours)); + snprintf(tempbuff, sizeof(tempbuff), "Power_On_Hours;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.power_on_hours))); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Unsafe_Shutdowns;%0.Lf;", int128_to_double(smart->raw_smart.unsafe_shutdowns)); + snprintf(tempbuff, sizeof(tempbuff), "Unsafe_Shutdowns;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.unsafe_shutdowns))); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Media_Errors;%0.Lf;", int128_to_double(smart->raw_smart.media_errors)); + snprintf(tempbuff, sizeof(tempbuff), "Media_Errors;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.media_errors))); strcat(text, tempbuff); - snprintf(tempbuff, sizeof(tempbuff), "Num_Err_Log_Entries;%0.Lf;", int128_to_double(smart->raw_smart.num_err_log_entries)); + snprintf(tempbuff, sizeof(tempbuff), "Num_Err_Log_Entries;%s;", uint128_t_to_string(le128_to_cpu(smart->raw_smart.num_err_log_entries))); strcat(text, tempbuff); snprintf(tempbuff, sizeof(tempbuff), "Warning_Temperature_Time;%u;", le32_to_cpu(smart->raw_smart.warning_temp_time)); strcat(text, tempbuff); @@ -927,8 +916,7 @@ static void vt_parse_detail_identify(const struct nvme_id_ctrl *ctrl) static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err = 0; - int fd, ret; + int ret, err = 0; long int total_time = 0; long int freq_time = 0; long int cur_time = 0; @@ -949,6 +937,7 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm const char *freq = "(optional) How often you want to log SMART data (0.25 = 15' , 0.5 = 30' , 1 = 1 hour, 2 = 2 hours, etc.). Default = 10 hours."; const char *output_file = "(optional) Name of the log file (give it a name that easy for you to remember what the test is). You can leave it blank too, we will take care it for you."; const char *test_name = "(optional) Name of the test you are doing. We use this as part of the name of the log file."; + struct nvme_dev *dev; struct vtview_save_log_settings cfg = { .run_time_hrs = 20, @@ -975,10 +964,10 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm strcpy(path, argv[1]); } - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - printf("Error parse and open (fd = %d)\n", fd); - return (fd); + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { + printf("Error parse and open (err = %d)\n", err); + return err; } printf("Running...\n"); @@ -986,10 +975,10 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm printf("Running for %lf hour(s)\n", cfg.run_time_hrs); printf("Logging SMART data for every %lf hour(s)\n", cfg.log_record_frequency_hrs); - ret = vt_update_vtview_log_header(fd, path, &cfg); + ret = vt_update_vtview_log_header(dev_fd(dev), path, &cfg); if (ret) { err = EINVAL; - close(fd); + dev_close(dev); return (err); } @@ -1009,7 +998,7 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm if(cur_time >= end_time) break; - ret = vt_add_entry_to_log(fd, path, &cfg); + ret = vt_add_entry_to_log(dev_fd(dev), path, &cfg); if (ret) { printf("Cannot update driver log\n"); break; @@ -1021,15 +1010,15 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm fflush(stdout); } - close (fd); + dev_close(dev); return (err); } static int vt_show_identify(int argc, char **argv, struct command *cmd, struct plugin *plugin) { - int err = 0; - int fd ,ret; + int ret, err = 0; struct nvme_id_ctrl ctrl; + struct nvme_dev *dev; char *desc = "Parse identify data to json format\n\n" "Typical usages:\n\n" "virtium show-identify /dev/yourDevice\n"; @@ -1038,16 +1027,16 @@ static int vt_show_identify(int argc, char **argv, struct command *cmd, struct p OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { - printf("Error parse and open (fd = %d)\n", fd); - return (fd); + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) { + printf("Error parse and open (err = %d)\n", err); + return err; } - ret = nvme_identify_ctrl(fd, &ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { printf("Cannot read identify device\n"); - close (fd); + dev_close(dev); return (-1); } @@ -1055,6 +1044,6 @@ static int vt_show_identify(int argc, char **argv, struct command *cmd, struct p vt_process_string(ctrl.mn, sizeof(ctrl.mn)); vt_parse_detail_identify(&ctrl); - close(fd); + dev_close(dev); return (err); } diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index 5f90c76..cf185be 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -36,6 +36,7 @@ #include "libnvme.h" #include "plugin.h" #include "linux/types.h" +#include "util/types.h" #include "nvme-print.h" #define CREATE_CMD @@ -77,11 +78,15 @@ #define WDC_NVME_SN650_DEV_ID_3 0x2720 #define WDC_NVME_SN650_DEV_ID_4 0x2721 #define WDC_NVME_SN655_DEV_ID 0x2722 +#define WDC_NVME_SN860_DEV_ID 0x2730 +#define WDC_NVME_SN660_DEV_ID 0x2704 + +/* This id's are no longer supported, delete ?? */ +#define WDC_NVME_SN550_DEV_ID 0x2708 #define WDC_NVME_SN560_DEV_ID_1 0x2712 #define WDC_NVME_SN560_DEV_ID_2 0x2713 #define WDC_NVME_SN560_DEV_ID_3 0x2714 -#define WDC_NVME_SN860_DEV_ID 0x2730 -#define WDC_NVME_SN550_DEV_ID 0x2708 + #define WDC_NVME_SXSLCL_DEV_ID 0x2001 #define WDC_NVME_SN520_DEV_ID 0x5003 #define WDC_NVME_SN520_DEV_ID_1 0x5004 @@ -89,8 +94,6 @@ #define WDC_NVME_SN530_DEV_ID 0x5009 #define WDC_NVME_SN720_DEV_ID 0x5002 #define WDC_NVME_SN730A_DEV_ID 0x5006 -#define WDC_NVME_SN730B_DEV_ID 0x3714 -#define WDC_NVME_SN730B_DEV_ID_1 0x3734 #define WDC_NVME_SN740_DEV_ID 0x5015 #define WDC_NVME_SN740_DEV_ID_1 0x5016 #define WDC_NVME_SN740_DEV_ID_2 0x5017 @@ -327,7 +330,7 @@ #define WDC_NVME_SMART_CLOUD_ATTR_LEN 0x200 /* C0 SMART Cloud Attributes Log Page*/ -#define WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE 0xC0 +#define WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID 0xC0 /* CB - FW Activate History Log Page */ #define WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID 0xCB @@ -341,7 +344,7 @@ /* C3 Latency Monitor Log Page */ #define WDC_LATENCY_MON_LOG_BUF_LEN 0x200 -#define WDC_LATENCY_MON_OPCODE 0xC3 +#define WDC_LATENCY_MON_LOG_ID 0xC3 #define WDC_LATENCY_MON_VERSION 0x0001 #define WDC_C3_GUID_LENGTH 16 @@ -792,17 +795,18 @@ static NVME_VU_DE_LOGPAGE_LIST deVULogPagesList[] = { NVME_DE_LOGPAGE_C0, 0xC0, 512, "0xc0"} }; -static int wdc_get_serial_name(int fd, char *file, size_t len, const char *suffix); +static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, + const char *suffix); static int wdc_create_log_file(char *file, __u8 *drive_log_data, __u32 drive_log_length); -static int wdc_do_clear_dump(int fd, __u8 opcode, __u32 cdw12); -static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, +static int wdc_do_clear_dump(struct nvme_dev *dev, __u8 opcode, __u32 cdw12); +static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode,__u32 data_len, __u32 cdw12, char *file, __u32 xfer_size); -static int wdc_do_crash_dump(int fd, char *file, int type); -static int wdc_crash_dump(int fd, char *file, int type); +static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type); +static int wdc_crash_dump(struct nvme_dev *dev, char *file, int type); static int wdc_get_crash_dump(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_do_drive_log(int fd, char *file); +static int wdc_do_drive_log(struct nvme_dev *dev, char *file); static int wdc_drive_log(int argc, char **argv, struct command *command, struct plugin *plugin); static const char* wdc_purge_mon_status_to_string(__u32 status); @@ -810,10 +814,11 @@ static int wdc_purge(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_purge_monitor(int argc, char **argv, struct command *command, struct plugin *plugin); -static bool wdc_nvme_check_supported_log_page(nvme_root_t r, int fd, __u8 log_id); +static bool wdc_nvme_check_supported_log_page(nvme_root_t r, + struct nvme_dev *dev, __u8 log_id); static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key); +static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, char *dir, char *key); static int wdc_drive_essentials(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_drive_status(int argc, char **argv, struct command *command, @@ -822,27 +827,31 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_drive_resize(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_do_drive_resize(int fd, uint64_t new_size); +static int wdc_do_drive_resize(struct nvme_dev *dev, uint64_t new_size); static int wdc_namespace_resize(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_do_namespace_resize(int fd, __u32 nsid, __u32 op_option); +static int wdc_do_namespace_resize(struct nvme_dev *dev, __u32 nsid, + __u32 op_option); static int wdc_reason_identifier(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_do_get_reason_id(int fd, char *file, int log_id); -static int wdc_save_reason_id(int fd, __u8 *rsn_ident, int size); -static int wdc_clear_reason_id(int fd); +static int wdc_do_get_reason_id(struct nvme_dev *dev, char *file, int log_id); +static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size); +static int wdc_clear_reason_id(struct nvme_dev *dev); static int wdc_log_page_directory(int argc, char **argv, struct command *command, struct plugin *plugin); -static int wdc_do_drive_info(int fd, __u32 *result); +static int wdc_do_drive_info(struct nvme_dev *dev, __u32 *result); static int wdc_vs_drive_info(int argc, char **argv, struct command *command, struct plugin *plugin); static int wdc_vs_temperature_stats(int argc, char **argv, struct command *command, struct plugin *plugin); -static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd); -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); +static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, struct nvme_dev *dev); +static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, + __u32 xfer_size, __u32 data_len, FILE *out); +static int wdc_enc_submit_move_data(struct nvme_dev *dev, 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, struct nvme_dev *dev, + __u8 log_id, void **cbs_data); +static __u32 wdc_get_fw_cust_id(nvme_root_t r, struct nvme_dev *dev); /* Drive log data size */ struct wdc_log_size { @@ -1084,7 +1093,8 @@ struct __attribute__((__packed__)) wdc_ssd_d0_smart_log { #define WDC_OCP_C1_GUID_LENGTH 16 #define WDC_ERROR_REC_LOG_BUF_LEN 512 #define WDC_ERROR_REC_LOG_ID 0xC1 -#define WDC_ERROR_REC_LOG_VERSION 0002 +#define WDC_ERROR_REC_LOG_VERSION1 0001 +#define WDC_ERROR_REC_LOG_VERSION2 0002 struct __attribute__((__packed__)) wdc_ocp_c1_error_recovery_log { __le16 panic_reset_wait_time; /* 000 - Panic Reset Wait Time */ @@ -1096,9 +1106,9 @@ struct __attribute__((__packed__)) wdc_ocp_c1_error_recovery_log { __u8 rsvd1[3]; /* 017 - 3 Reserved Bytes */ __le32 vs_cmd_cdw12; /* 020 - Vendor Specific Command CDW12 */ __le32 vs_cmd_cdw13; /* 024 - Vendor Specific Command CDW13 */ - __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout */ - __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 */ - __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout */ + __u8 vs_cmd_to; /* 028 - Vendor Specific Command Timeout V2 */ + __u8 dev_recovery_action2; /* 029 - Device Recovery Action 2 V2 */ + __u8 dev_recovery_action2_to; /* 030 - Device Recovery Action 2 Timeout V2*/ __u8 rsvd2[463]; /* 031 - 463 Reserved Bytes */ __le16 log_page_version; /* 494 - Log Page Version */ __u8 log_page_guid[WDC_OCP_C1_GUID_LENGTH]; /* 496 - Log Page GUID */ @@ -1277,27 +1287,15 @@ static double calc_percent(uint64_t numerator, uint64_t denominator) (uint64_t)(((double)numerator / (double)denominator) * 100) : 0; } -static long double int128_to_double(__u8 *data) -{ - int i; - long double result = 0; - - for (i = 0; i < 16; i++) { - result *= 256; - result += data[15 - i]; - } - return result; -} - -static int wdc_get_pci_ids(nvme_root_t r, uint32_t *device_id, - uint32_t *vendor_id) +static int wdc_get_pci_ids(nvme_root_t r, struct nvme_dev *dev, + uint32_t *device_id, uint32_t *vendor_id) { char vid[256], did[256], id[32]; nvme_ctrl_t c = NULL; nvme_ns_t n = NULL; int fd, ret; - c = nvme_scan_ctrl(r, devicename); + c = nvme_scan_ctrl(r, dev->name); if (c) { snprintf(vid, sizeof(vid), "%s/device/vendor", nvme_ctrl_get_sysfs_dir(c)); @@ -1305,9 +1303,9 @@ static int wdc_get_pci_ids(nvme_root_t r, uint32_t *device_id, nvme_ctrl_get_sysfs_dir(c)); nvme_free_ctrl(c); } else { - n = nvme_scan_namespace(devicename); + n = nvme_scan_namespace(dev->name); if (!n) { - fprintf(stderr, "Unable to find %s\n", devicename); + fprintf(stderr, "Unable to find %s\n", dev->name); return -1; } @@ -1359,13 +1357,13 @@ static int wdc_get_pci_ids(nvme_root_t r, uint32_t *device_id, return 0; } -static int wdc_get_vendor_id(int fd, uint32_t *vendor_id) +static int wdc_get_vendor_id(struct nvme_dev *dev, uint32_t *vendor_id) { int ret; struct nvme_id_ctrl ctrl; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(fd, &ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", ret); @@ -1382,13 +1380,13 @@ static bool wdc_check_power_of_2(int num) return (num && ( !(num & (num-1)))); } -static int wdc_get_model_number(int fd, char *model) +static int wdc_get_model_number(struct nvme_dev *dev, char *model) { int ret,i; struct nvme_id_ctrl ctrl; memset(&ctrl, 0, sizeof(struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(fd, &ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", ret); @@ -1404,16 +1402,16 @@ static int wdc_get_model_number(int fd, char *model) return ret; } -static bool wdc_check_device(nvme_root_t r, int fd) +static bool wdc_check_device(nvme_root_t r, struct nvme_dev *dev) { int ret; bool supported; uint32_t read_device_id = -1, read_vendor_id = -1; - ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); if (ret < 0) { /* Use the identify nvme command to get vendor id due to NVMeOF device. */ - if (wdc_get_vendor_id(fd, &read_vendor_id) < 0) + if (wdc_get_vendor_id(dev, &read_vendor_id) < 0) return false; } @@ -1430,13 +1428,13 @@ static bool wdc_check_device(nvme_root_t r, int fd) return supported; } -static bool wdc_enc_check_model(int fd) +static bool wdc_enc_check_model(struct nvme_dev *dev) { int ret; bool supported; char model[NVME_ID_CTRL_MODEL_NUMBER_SIZE+1]; - ret = wdc_get_model_number(fd, model); + ret = wdc_get_model_number(dev, model); if (ret < 0) return false; @@ -1450,23 +1448,24 @@ static bool wdc_enc_check_model(int fd) return supported; } -static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { +static __u64 wdc_get_drive_capabilities(nvme_root_t r, struct nvme_dev *dev) +{ int ret; uint32_t read_device_id = -1, read_vendor_id = -1; __u64 capabilities = 0; __u32 cust_id; - ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); if (ret < 0) { - if (wdc_get_vendor_id(fd, &read_vendor_id) < 0) + if (wdc_get_vendor_id(dev, &read_vendor_id) < 0) return capabilities; } /* below check condition is added due in NVMeOF device we dont have device_id so we need to use only vendor_id*/ if (read_device_id == -1 && read_vendor_id != -1) { - capabilities = wdc_get_enc_drive_capabilities(r, fd); + capabilities = wdc_get_enc_drive_capabilities(r, dev); return capabilities; } @@ -1484,11 +1483,13 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { WDC_DRIVE_CAP_PURGE); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xC1 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_ADD_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_ADD_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; break; default: @@ -1504,11 +1505,14 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_CLEAR_PCIE); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_VU_SMART_LOG_OPCODE) + == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; case WDC_NVME_SN640_DEV_ID: @@ -1524,8 +1528,12 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { case WDC_NVME_SN560_DEV_ID_2: /* FALLTHRU */ case WDC_NVME_SN560_DEV_ID_3: + /* FALLTHRU */ + case WDC_NVME_SN660_DEV_ID: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID) + == true) { capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; } @@ -1536,30 +1544,36 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { WDC_DRIVE_CAP_LOG_PAGE_DIR); /* verify the 0xC1 (OCP Error Recovery) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_ERROR_REC_LOG_ID) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_ERROR_REC_LOG_ID)) capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE; /* verify the 0xC3 (OCP Latency Monitor) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_LATENCY_MON_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_LATENCY_MON_LOG_ID)) capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; /* verify the 0xC4 (OCP Device Capabilities) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_DEV_CAP_LOG_ID) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_DEV_CAP_LOG_ID)) capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE; /* verify the 0xC5 (OCP Unsupported Requirments) log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_UNSUPPORTED_REQS_LOG_ID) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_UNSUPPORTED_REQS_LOG_ID)) capabilities |= WDC_DRIVE_CAP_OCP_C5_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) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_VU_SMART_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - cust_id = wdc_get_fw_cust_id(r, fd); + cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; @@ -1579,9 +1593,9 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { /* FALLTHRU */ case WDC_NVME_SN860_DEV_ID: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_EOL_STATUS_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; - } /* FALLTHRU */ case WDC_NVME_ZN540_DEV_ID: /* FALLTHRU */ @@ -1595,11 +1609,13 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { WDC_DRIVE_CAP_LOG_PAGE_DIR ); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_VU_SMART_LOG_OPCODE)) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; break; case WDC_NVME_SN650_DEV_ID: @@ -1610,23 +1626,45 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { case WDC_NVME_SN655_DEV_ID: case WDC_NVME_SN550_DEV_ID: /* verify the 0xC0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE) == true) { + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID)) capabilities |= WDC_DRIVE_CAP_C0_LOG_PAGE; - } + + /* verify the 0xC1 (OCP Error Recovery) log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_ERROR_REC_LOG_ID)) + capabilities |= WDC_DRIVE_CAP_OCP_C1_LOG_PAGE; + + /* verify the 0xC3 (OCP Latency Monitor) log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_LATENCY_MON_LOG_ID)) + capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; + + /* verify the 0xC4 (OCP Device Capabilities) log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_DEV_CAP_LOG_ID)) + capabilities |= WDC_DRIVE_CAP_OCP_C4_LOG_PAGE; + + /* verify the 0xC5 (OCP Unsupported Requirments) log page is supported */ + if (wdc_nvme_check_supported_log_page(r, dev, WDC_UNSUPPORTED_REQS_LOG_ID)) + capabilities |= WDC_DRIVE_CAP_OCP_C5_LOG_PAGE; capabilities |= (WDC_DRIVE_CAP_CAP_DIAG | WDC_DRIVE_CAP_INTERNAL_LOG | WDC_DRIVE_CAP_DRIVE_STATUS | WDC_DRIVE_CAP_CLEAR_ASSERT | - WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_CLEAR_PCIE | - WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | + WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID | - WDC_DRIVE_CAP_LOG_PAGE_DIR | WDC_DRIVE_CAP_INFO | - WDC_DRIVE_CAP_CLOUD_SSD_VERSION); + WDC_DRIVE_CAP_LOG_PAGE_DIR); + + cust_id = wdc_get_fw_cust_id(r, dev); + if (cust_id == WDC_INVALID_CUSTOMER_ID) { + fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); + return -1; + } + + 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 + capabilities |= (WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY | WDC_DRIVE_CAP_CLEAR_PCIE); - break; - case WDC_NVME_SN730B_DEV_ID: - /* FALLTHRU */ - case WDC_NVME_SN730B_DEV_ID_1: - capabilities = WDC_SN730B_CAP_VUC_LOG; break; default: capabilities = 0; @@ -1685,13 +1723,15 @@ static __u64 wdc_get_drive_capabilities(nvme_root_t r, int fd) { return capabilities; } -static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd) { +static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, + struct nvme_dev *dev) +{ int ret; uint32_t read_vendor_id; __u64 capabilities = 0; __u32 cust_id; - ret = wdc_get_vendor_id(fd, &read_vendor_id); + ret = wdc_get_vendor_id(dev, &read_vendor_id); if (ret < 0) return capabilities; @@ -1701,11 +1741,11 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd) { WDC_DRIVE_CAP_DRIVE_LOG | WDC_DRIVE_CAP_CRASH_DUMP | WDC_DRIVE_CAP_PFAIL_DUMP); /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xC1 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_ADD_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_ADD_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_C1_LOG_PAGE; break; case WDC_NVME_VID_2: @@ -1714,22 +1754,22 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd) { WDC_DRIVE_CAP_RESIZE); /* verify the 0xC3 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_LATENCY_MON_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, WDC_LATENCY_MON_LOG_ID) == true) capabilities |= WDC_DRIVE_CAP_C3_LOG_PAGE; /* verify the 0xCB log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true) + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == true) capabilities |= WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY; /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_CA_LOG_PAGE; /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == true) capabilities |= WDC_DRIVE_CAP_D0_LOG_PAGE; - cust_id = wdc_get_fw_cust_id(r, fd); + cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; @@ -1752,7 +1792,8 @@ static __u64 wdc_get_enc_drive_capabilities(nvme_root_t r, int fd) { return capabilities; } -static int wdc_get_serial_name(int fd, char *file, size_t len, const char *suffix) +static int wdc_get_serial_name(struct nvme_dev *dev, char *file, size_t len, + const char *suffix) { int i; int ret; @@ -1765,7 +1806,7 @@ static int wdc_get_serial_name(int fd, char *file, size_t len, const char *suffi strncpy(orig, file, PATH_MAX - 1); memset(file, 0, len); memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(fd, &ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", ret); @@ -1927,7 +1968,8 @@ bool wdc_get_dev_mng_log_entry(__u32 log_length, return valid_log; } -static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **cbs_data) +static bool get_dev_mgment_cbs_data(nvme_root_t r, struct nvme_dev *dev, + __u8 log_id, void **cbs_data) { int ret = -1; void* data; @@ -1940,7 +1982,7 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **c *cbs_data = NULL; __u32 device_id, read_vendor_id; - ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); if(device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) { lid = WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8; uuid_ix = 0; @@ -1956,7 +1998,7 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **c /* get the log page length */ struct nvme_get_log_args args_len = { .args_size = sizeof(args_len), - .fd = fd, + .fd = dev_fd(dev), .lid = lid, .nsid = 0xFFFFFFFF, .lpo = 0, @@ -1993,7 +2035,7 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **c /* get the log page data */ struct nvme_get_log_args args_data = { .args_size = sizeof(args_data), - .fd = fd, + .fd = dev_fd(dev), .lid = lid, .nsid = 0xFFFFFFFF, .lpo = 0, @@ -2034,7 +2076,7 @@ static bool get_dev_mgment_cbs_data(nvme_root_t r, int fd, __u8 log_id, void **c /* get the log page data */ struct nvme_get_log_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .lid = lid, .nsid = 0xFFFFFFFF, .lpo = 0, @@ -2072,13 +2114,15 @@ end: return found; } -static bool wdc_nvme_check_supported_log_page(nvme_root_t r, int fd, __u8 log_id) +static bool wdc_nvme_check_supported_log_page(nvme_root_t r, + struct nvme_dev *dev, + __u8 log_id) { int i; bool found = false; struct wdc_c2_cbs_data *cbs_data = NULL; - if (get_dev_mgment_cbs_data(r, fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(r, dev, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { if (cbs_data != NULL) { for (i = 0; i < le32_to_cpu(cbs_data->length); i++) { if (log_id == cbs_data->data[i]) { @@ -2104,12 +2148,14 @@ static bool wdc_nvme_check_supported_log_page(nvme_root_t r, int fd, __u8 log_id return found; } -static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, int fd, __le32 *ret_data, +static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, + struct nvme_dev *dev, + __le32 *ret_data, __u8 log_id) { __u32 *cbs_data = NULL; - if (get_dev_mgment_cbs_data(r, fd, log_id, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(r, dev, log_id, (void *)&cbs_data)) { if (cbs_data != NULL) { memcpy((void *)ret_data, (void *)cbs_data, 4); free(cbs_data); @@ -2122,7 +2168,7 @@ static bool wdc_nvme_get_dev_status_log_data(nvme_root_t r, int fd, __le32 *ret_ return false; } -static int wdc_do_clear_dump(int fd, __u8 opcode, __u32 cdw12) +static int wdc_do_clear_dump(struct nvme_dev *dev, __u8 opcode, __u32 cdw12) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -2130,7 +2176,7 @@ static int wdc_do_clear_dump(int fd, __u8 opcode, __u32 cdw12) memset(&admin_cmd, 0, sizeof (struct nvme_passthru_cmd)); admin_cmd.opcode = opcode; admin_cmd.cdw12 = cdw12; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); if (ret != 0) { fprintf(stdout, "ERROR : WDC : Crash dump erase failed\n"); } @@ -2248,7 +2294,7 @@ static __u32 wdc_dump_dui_data_v2(int fd, __u32 dataLen, __u64 offset, __u8 *dum return ret; } -static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, +static int wdc_do_dump(struct nvme_dev *dev, __u32 opcode,__u32 data_len, __u32 cdw12, char *file, __u32 xfer_size) { int ret = 0; @@ -2277,7 +2323,8 @@ static int wdc_do_dump(int fd, __u32 opcode,__u32 data_len, admin_cmd.cdw13 = curr_data_offset; while (curr_data_offset < data_len) { - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, + NULL); if (ret != 0) { nvme_show_status(ret); fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", @@ -2370,7 +2417,8 @@ static int wdc_do_dump_e6(int fd, __u32 opcode,__u32 data_len, return ret; } -static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int data_area) +static int wdc_do_cap_telemetry_log(struct nvme_dev *dev, char *file, + __u32 bs, int type, int data_area) { struct nvme_telemetry_log *log; size_t full_size = 0; @@ -2386,7 +2434,7 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int nvme_root_t r; memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (err) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", err); @@ -2399,7 +2447,7 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int } r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if (type == WDC_TELEMETRY_TYPE_HOST) { host_gen = 1; @@ -2407,8 +2455,9 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int } else if (type == WDC_TELEMETRY_TYPE_CONTROLLER) { if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) { /* Verify the Controller Initiated Option is enabled */ - err = nvme_get_features_data(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, - 4, buf, &result); + err = nvme_get_features_data(dev_fd(dev), + WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + 0, 4, buf, &result); if (err == 0) { if (result == 0) { /* enabled */ @@ -2448,11 +2497,14 @@ static int wdc_do_cap_telemetry_log(int fd, char *file, __u32 bs, int type, int } if (ctrl_init) - err = nvme_get_ctrl_telemetry(fd, true, &log, data_area, &full_size); + err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &log, + data_area, &full_size); else if (host_gen) - err = nvme_get_new_host_telemetry(fd, &log, data_area, &full_size); + err = nvme_get_new_host_telemetry(dev_fd(dev), &log, + data_area, &full_size); else - err = nvme_get_host_telemetry(fd, &log, data_area, &full_size); + err = nvme_get_host_telemetry(dev_fd(dev), &log, data_area, + &full_size); if (err < 0) { perror("get-telemetry-log"); @@ -2499,7 +2551,7 @@ close_output: return err; } -static int wdc_do_cap_diag(nvme_root_t r, int fd, char *file, +static int wdc_do_cap_diag(nvme_root_t r, struct nvme_dev *dev, char *file, __u32 xfer_size, int type, int data_area) { int ret = -1; @@ -2516,7 +2568,8 @@ static int wdc_do_cap_diag(nvme_root_t r, int fd, char *file, memset(log_hdr, 0, e6_log_hdr_size); if (type == WDC_TELEMETRY_TYPE_NONE) { - ret = wdc_dump_length_e6(fd, WDC_NVME_CAP_DIAG_OPCODE, + ret = wdc_dump_length_e6(dev_fd(dev), + WDC_NVME_CAP_DIAG_OPCODE, WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE>>2, 0x00, log_hdr); @@ -2531,7 +2584,9 @@ static int wdc_do_cap_diag(nvme_root_t r, int fd, char *file, if (cap_diag_length == 0) { fprintf(stderr, "INFO : WDC : Capture Diagnostics log is empty\n"); } else { - ret = wdc_do_dump_e6(fd, WDC_NVME_CAP_DIAG_OPCODE, cap_diag_length, + ret = wdc_do_dump_e6(dev_fd(dev), + WDC_NVME_CAP_DIAG_OPCODE, + cap_diag_length, (WDC_NVME_CAP_DIAG_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CAP_DIAG_CMD, file, xfer_size, (__u8 *)log_hdr); @@ -2540,7 +2595,7 @@ static int wdc_do_cap_diag(nvme_root_t r, int fd, char *file, } else if ((type == WDC_TELEMETRY_TYPE_HOST) || (type == WDC_TELEMETRY_TYPE_CONTROLLER)) { /* Get the desired telemetry log page */ - ret = wdc_do_cap_telemetry_log(fd, file, xfer_size, type, data_area); + ret = wdc_do_cap_telemetry_log(dev, file, xfer_size, type, data_area); } else fprintf(stderr, "%s: ERROR : Invalid type : %d\n", __func__, type); @@ -2932,10 +2987,11 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, char *desc = "Capture Diagnostics Log."; char *file = "Output file pathname."; char *size = "Data retrieval transfer size."; + __u64 capabilities = 0; char f[PATH_MAX] = {0}; + struct nvme_dev *dev; __u32 xfer_size = 0; - int fd, ret = 0; - __u64 capabilities = 0; + int ret = 0; struct config { char *file; @@ -2953,9 +3009,9 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); @@ -2963,7 +3019,7 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, strncpy(f, cfg.file, PATH_MAX - 1); if (cfg.xfer_size != 0) xfer_size = cfg.xfer_size; - ret = wdc_get_serial_name(fd, f, PATH_MAX, "cap_diag"); + ret = wdc_get_serial_name(dev, f, PATH_MAX, "cap_diag"); if (ret) { fprintf(stderr, "ERROR : WDC: failed to generate file name\n"); goto out; @@ -2977,15 +3033,15 @@ static int wdc_cap_diag(int argc, char **argv, struct command *command, strcat(f, ".bin"); } - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CAP_DIAG) == WDC_DRIVE_CAP_CAP_DIAG) - ret = wdc_do_cap_diag(r, fd, f, xfer_size, 0, 0); + ret = wdc_do_cap_diag(r, dev, f, xfer_size, 0, 0); else fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -3232,13 +3288,14 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command char *verbose = "Display more debug messages."; char f[PATH_MAX] = {0}; char fileSuffix[PATH_MAX] = {0}; + struct nvme_dev *dev; nvme_root_t r; __u32 xfer_size = 0; - int fd, ret = -1; int telemetry_type = 0, telemetry_data_area = 0; UtilsTimeInfo timeInfo; __u8 timeStamp[MAX_PATH_LEN]; __u64 capabilities = 0; + int ret = -1; struct config { char *file; @@ -3271,12 +3328,12 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) goto out; if (cfg.xfer_size != 0) @@ -3305,7 +3362,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command timeInfo.hour, timeInfo.minute, timeInfo.second); snprintf(fileSuffix, PATH_MAX, "_internal_fw_log_%s", (char*)timeStamp); - ret = wdc_get_serial_name(fd, f, PATH_MAX, fileSuffix); + ret = wdc_get_serial_name(dev, f, PATH_MAX, fileSuffix); if (ret) { fprintf(stderr, "ERROR : WDC: failed to generate file name\n"); goto out; @@ -3349,12 +3406,12 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command goto out; } - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_INTERNAL_LOG) == WDC_DRIVE_CAP_INTERNAL_LOG) { if (telemetry_data_area == 0) telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ - ret = wdc_do_cap_diag(r, fd, f, xfer_size, + ret = wdc_do_cap_diag(r, dev, f, xfer_size, telemetry_type, telemetry_data_area); goto out; } @@ -3364,7 +3421,7 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command if (telemetry_data_area == 0) telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ /* Get the desired telemetry log page */ - ret = wdc_do_cap_telemetry_log(fd, f, xfer_size, + ret = wdc_do_cap_telemetry_log(dev, f, xfer_size, telemetry_type, telemetry_data_area); goto out; } else { @@ -3374,7 +3431,8 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command /* FW requirement - xfer size must be 256k for data area 4 */ if (cfg.data_area >= 4) xfer_size = 0x40000; - ret = wdc_do_cap_dui(fd, f, xfer_size, cfg.data_area, + ret = wdc_do_cap_dui(dev_fd(dev), f, xfer_size, + cfg.data_area, cfg.verbose, cfg.file_size, cfg.offset); goto out; @@ -3386,29 +3444,29 @@ static int wdc_vs_internal_fw_log(int argc, char **argv, struct command *command if (telemetry_data_area == 0) telemetry_data_area = 3; /* Set the default DA to 3 if not specified */ /* Get the desired telemetry log page */ - ret = wdc_do_cap_telemetry_log(fd, f, xfer_size, + ret = wdc_do_cap_telemetry_log(dev, f, xfer_size, telemetry_type, telemetry_data_area); goto out; } else { - ret = wdc_do_cap_dui(fd, f, xfer_size, + ret = wdc_do_cap_dui(dev_fd(dev), f, xfer_size, WDC_NVME_DUI_MAX_DATA_AREA, cfg.verbose, 0, 0); goto out; } } if ((capabilities & WDC_SN730B_CAP_VUC_LOG) == WDC_SN730B_CAP_VUC_LOG) - ret = wdc_do_sn730_get_and_tar(fd, f); + ret = wdc_do_sn730_get_and_tar(dev_fd(dev), f); else { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; } out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } -static int wdc_do_crash_dump(int fd, char *file, int type) +static int wdc_do_crash_dump(struct nvme_dev *dev, char *file, int type) { int ret; __u32 crash_dump_length; @@ -3445,11 +3503,11 @@ static int wdc_do_crash_dump(int fd, char *file, int type) WDC_NVME_CLEAR_CRASH_DUMP_CMD); } - ret = wdc_dump_length(fd, - opcode, - cdw10_size, - cdw12_size, - &crash_dump_length); + ret = wdc_dump_length(dev_fd(dev), + opcode, + cdw10_size, + cdw12_size, + &crash_dump_length); if (ret == -1) { if (type == WDC_NVME_PFAIL_DUMP_TYPE) @@ -3466,7 +3524,7 @@ static int wdc_do_crash_dump(int fd, char *file, int type) else fprintf(stderr, "INFO : WDC: Crash dump is empty\n"); } else { - ret = wdc_do_dump(fd, + ret = wdc_do_dump(dev, opcode, crash_dump_length, cdw12, @@ -3474,12 +3532,13 @@ static int wdc_do_crash_dump(int fd, char *file, int type) crash_dump_length); if (ret == 0) - ret = wdc_do_clear_dump(fd, WDC_NVME_CLEAR_DUMP_OPCODE, cdw12_clear); + ret = wdc_do_clear_dump(dev, WDC_NVME_CLEAR_DUMP_OPCODE, + cdw12_clear); } return ret; } -static int wdc_crash_dump(int fd, char *file, int type) +static int wdc_crash_dump(struct nvme_dev *dev, char *file, int type) { char f[PATH_MAX] = {0}; const char *dump_type; @@ -3494,26 +3553,26 @@ static int wdc_crash_dump(int fd, char *file, int type) else dump_type = "_crash_dump"; - ret = wdc_get_serial_name(fd, f, PATH_MAX, dump_type); + ret = wdc_get_serial_name(dev, f, PATH_MAX, dump_type); if (ret) fprintf(stderr, "ERROR : WDC : failed to generate file name\n"); else - ret = wdc_do_crash_dump(fd, f, type); + ret = wdc_do_crash_dump(dev, f, type); return ret; } -static int wdc_do_drive_log(int fd, char *file) +static int wdc_do_drive_log(struct nvme_dev *dev, char *file) { int ret; __u8 *drive_log_data; __u32 drive_log_length; struct nvme_passthru_cmd admin_cmd; - ret = wdc_dump_length(fd, WDC_NVME_DRIVE_LOG_SIZE_OPCODE, - WDC_NVME_DRIVE_LOG_SIZE_NDT, - (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD << - WDC_NVME_SUBCMD_SHIFT | WDC_NVME_DRIVE_LOG_SIZE_CMD), - &drive_log_length); + ret = wdc_dump_length(dev_fd(dev), WDC_NVME_DRIVE_LOG_SIZE_OPCODE, + WDC_NVME_DRIVE_LOG_SIZE_NDT, + (WDC_NVME_DRIVE_LOG_SIZE_SUBCMD << + WDC_NVME_SUBCMD_SHIFT | WDC_NVME_DRIVE_LOG_SIZE_CMD), + &drive_log_length); if (ret == -1) { return -1; } @@ -3533,7 +3592,7 @@ static int wdc_do_drive_log(int fd, char *file) admin_cmd.cdw12 = ((WDC_NVME_DRIVE_LOG_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_LOG_SIZE_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); nvme_show_status(ret); if (ret == 0) { ret = wdc_create_log_file(file, drive_log_data, drive_log_length); @@ -3548,7 +3607,7 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, const char *desc = "Capture Drive Log."; const char *file = "Output file pathname."; char f[PATH_MAX] = {0}; - int fd; + struct nvme_dev *dev; int ret; nvme_root_t r; __u64 capabilities = 0; @@ -3565,18 +3624,18 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - if (!wdc_check_device(r, fd)) { + if (!wdc_check_device(r, dev)) { nvme_free_tree(r); - close(fd); + dev_close(dev); return -1; } - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_DRIVE_LOG) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -3585,14 +3644,14 @@ static int wdc_drive_log(int argc, char **argv, struct command *command, if (cfg.file != NULL) { strncpy(f, cfg.file, PATH_MAX - 1); } - ret = wdc_get_serial_name(fd, f, PATH_MAX, "drive_log"); + ret = wdc_get_serial_name(dev, f, PATH_MAX, "drive_log"); if (ret) fprintf(stderr, "ERROR : WDC : failed to generate file name\n"); else - ret = wdc_do_drive_log(fd, f); + ret = wdc_do_drive_log(dev, f); } nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -3601,9 +3660,10 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, { const char *desc = "Get Crash Dump."; const char *file = "Output file pathname."; - int fd, ret; - nvme_root_t r; __u64 capabilities = 0; + struct nvme_dev *dev; + nvme_root_t r; + int ret; struct config { char *file; @@ -3618,32 +3678,32 @@ static int wdc_get_crash_dump(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - if (!wdc_check_device(r, fd)) { + if (!wdc_check_device(r, dev)) { nvme_free_tree(r); - close(fd); + dev_close(dev); return -1; } - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CRASH_DUMP) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; } else { - ret = wdc_crash_dump(fd, cfg.file, WDC_NVME_CRASH_DUMP_TYPE); + ret = wdc_crash_dump(dev, cfg.file, WDC_NVME_CRASH_DUMP_TYPE); if (ret != 0) { fprintf(stderr, "ERROR : WDC : failed to read crash dump\n"); } } nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -3652,13 +3712,13 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, { char *desc = "Get Pfail Crash Dump."; char *file = "Output file pathname."; - int fd; - int ret; - nvme_root_t r; __u64 capabilities = 0; + struct nvme_dev *dev; struct config { char *file; }; + nvme_root_t r; + int ret; struct config cfg = { .file = NULL, @@ -3669,30 +3729,30 @@ static int wdc_get_pfail_dump(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - if (!wdc_check_device(r, fd)) { + if (!wdc_check_device(r, dev)) { nvme_free_tree(r); - close(fd); + dev_close(dev); return -1; } - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_PFAIL_DUMP) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; } else { - ret = wdc_crash_dump(fd, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE); + ret = wdc_crash_dump(dev, cfg.file, WDC_NVME_PFAIL_DUMP_TYPE); if (ret != 0) { fprintf(stderr, "ERROR : WDC : failed to read pfail crash dump\n"); } } nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -3748,29 +3808,30 @@ static int wdc_purge(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a Purge command."; - char *err_str; - int fd, ret; - nvme_root_t r; struct nvme_passthru_cmd admin_cmd; __u64 capabilities = 0; + struct nvme_dev *dev; + char *err_str; + nvme_root_t r; + int ret; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - if (!wdc_check_device(r, fd)) { + if (!wdc_check_device(r, dev)) { nvme_free_tree(r); - close(fd); + dev_close(dev); return -1; } - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { ret = -1; fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -3779,7 +3840,8 @@ static int wdc_purge(int argc, char **argv, memset(&admin_cmd, 0, sizeof (admin_cmd)); admin_cmd.opcode = WDC_NVME_PURGE_CMD_OPCODE; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, + NULL); if (ret > 0) { switch (ret) { case WDC_NVME_PURGE_CMD_SEQ_ERR: @@ -3798,7 +3860,7 @@ static int wdc_purge(int argc, char **argv, nvme_show_status(ret); } nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -3806,30 +3868,31 @@ static int wdc_purge_monitor(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a Purge Monitor command."; - int fd, ret; - nvme_root_t r; __u8 output[WDC_NVME_PURGE_MONITOR_DATA_LEN]; double progress_percent; struct nvme_passthru_cmd admin_cmd; struct wdc_nvme_purge_monitor_data *mon; + struct nvme_dev *dev; __u64 capabilities; + nvme_root_t r; + int ret; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - if (!wdc_check_device(r, fd)) { + if (!wdc_check_device(r, dev)) { nvme_free_tree(r); - close(fd); + dev_close(dev); return -1; } - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if((capabilities & WDC_DRIVE_CAP_PURGE) == 0) { ret = -1; fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -3842,7 +3905,8 @@ static int wdc_purge_monitor(int argc, char **argv, admin_cmd.cdw10 = WDC_NVME_PURGE_MONITOR_CMD_CDW10; admin_cmd.timeout_ms = WDC_NVME_PURGE_MONITOR_TIMEOUT; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, + NULL); if (ret == 0) { mon = (struct wdc_nvme_purge_monitor_data *) output; printf("Purge state = 0x%0x\n", admin_cmd.result); @@ -3858,7 +3922,7 @@ static int wdc_purge_monitor(int argc, char **argv, nvme_show_status(ret); } nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -4009,15 +4073,16 @@ static int wdc_convert_ts(time_t time, char *ts_buf) return 0; } -static int wdc_print_latency_monitor_log_normal(int fd, struct wdc_ssd_latency_monitor_log *log_data) +static int wdc_print_latency_monitor_log_normal(struct nvme_dev *dev, + struct wdc_ssd_latency_monitor_log *log_data) { printf("Latency Monitor/C3 Log Page Data \n"); - printf(" Controller : %s\n", devicename); + printf(" Controller : %s\n", dev->name); int err = -1, i, j; struct nvme_id_ctrl ctrl; char ts_buf[128]; - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (!err) printf(" Serial Number: %-.*s\n", (int)sizeof(ctrl.sn), ctrl.sn); else { @@ -4164,14 +4229,16 @@ static void wdc_print_error_rec_log_normal(struct wdc_ocp_c1_error_recovery_log printf(" Panic Reset Wait Time : 0x%x \n", le16_to_cpu(log_data->panic_reset_wait_time)); printf(" Panic Reset Action : 0x%x \n", log_data->panic_reset_action); printf(" Device Recovery Action 1 : 0x%x \n", log_data->dev_recovery_action1); - printf(" Panic ID : 0x%lx \n", le64_to_cpu(log_data->panic_id)); + printf(" Panic ID : 0x%" PRIu64 "\n", le64_to_cpu(log_data->panic_id)); printf(" Device Capabilities : 0x%x \n", le32_to_cpu(log_data->dev_capabilities)); printf(" Vendor Specific Recovery Opcode : 0x%x \n", log_data->vs_recovery_opc); printf(" Vendor Specific Command CDW12 : 0x%x \n", le32_to_cpu(log_data->vs_cmd_cdw12)); printf(" Vendor Specific Command CDW13 : 0x%x \n", le32_to_cpu(log_data->vs_cmd_cdw13)); - printf(" Vendor Specific Command Timeout : 0x%x \n", log_data->vs_cmd_to); - printf(" Device Recovery Action 2 : 0x%x \n", log_data->dev_recovery_action2); - printf(" Device Recovery Action 2 Timeout : 0x%x \n", log_data->dev_recovery_action2_to); + if (le16_to_cpu(log_data->log_page_version) == WDC_ERROR_REC_LOG_VERSION2) { + printf(" Vendor Specific Command Timeout : 0x%x \n", log_data->vs_cmd_to); + printf(" Device Recovery Action 2 : 0x%x \n", log_data->dev_recovery_action2); + printf(" Device Recovery Action 2 Timeout : 0x%x \n", log_data->dev_recovery_action2_to); + } printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version)); printf(" Log page GUID : 0x"); for (j = 0; j < WDC_OCP_C1_GUID_LENGTH; j++) { @@ -4193,9 +4260,11 @@ static void wdc_print_error_rec_log_json(struct wdc_ocp_c1_error_recovery_log *l json_object_add_value_int(root, "Vendor Specific Recovery Opcode", log_data->vs_recovery_opc); json_object_add_value_int(root, "Vendor Specific Command CDW12", le32_to_cpu(log_data->vs_cmd_cdw12)); json_object_add_value_int(root, "Vendor Specific Command CDW13", le32_to_cpu(log_data->vs_cmd_cdw13)); - json_object_add_value_int(root, "Vendor Specific Command Timeout", log_data->vs_cmd_to); - json_object_add_value_int(root, "Device Recovery Action 2", log_data->dev_recovery_action2); - json_object_add_value_int(root, "Device Recovery Action 2 Timeout", log_data->dev_recovery_action2_to); + if (le16_to_cpu(log_data->log_page_version) == WDC_ERROR_REC_LOG_VERSION2) { + json_object_add_value_int(root, "Vendor Specific Command Timeout", log_data->vs_cmd_to); + json_object_add_value_int(root, "Device Recovery Action 2", log_data->dev_recovery_action2); + json_object_add_value_int(root, "Device Recovery Action 2 Timeout", log_data->dev_recovery_action2_to); + } json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); char guid[40]; @@ -4442,7 +4511,7 @@ static void wdc_print_fb_ca_log_json(struct wdc_ssd_ca_perf_stats *perf) json_free_object(root); } -static void wdc_print_bd_ca_log_normal(void *data) +static void wdc_print_bd_ca_log_normal(struct nvme_dev *dev, void *data) { struct wdc_bd_ca_log_format *bd_data = (struct wdc_bd_ca_log_format *)data; __u64 *raw; @@ -4453,7 +4522,7 @@ static void wdc_print_bd_ca_log_normal(void *data) if (bd_data->field_id == 0x00) { raw = (__u64*)&bd_data->raw_value[0]; printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", - devicename, WDC_DE_GLOBAL_NSID); + dev->name, WDC_DE_GLOBAL_NSID); printf("key normalized raw\n"); printf("program_fail_count : %3"PRIu8"%% %"PRIu64"\n", bd_data->normalized_value, le64_to_cpu(*raw & 0x00FFFFFFFFFFFFFF)); @@ -5056,7 +5125,7 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 root = json_create_object(); - if(data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID) { + if (data[0] == WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID) { struct wdc_fw_act_history_log_format_c2 *fw_act_history_entry = (struct wdc_fw_act_history_log_format_c2 *)(data); oldestEntryIdx = WDC_MAX_NUM_ACT_HIST_ENTRIES; @@ -5100,7 +5169,7 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 json_object_add_value_string(root, "Power on Hour", time_str); } else { uint64_t timestamp = (0x0000FFFFFFFFFFFF & le64_to_cpu(fw_act_history_entry->entry[entryIdx].timestamp)); - json_object_add_value_int(root, "Timestamp", timestamp); + json_object_add_value_uint64(root, "Timestamp", timestamp); } json_object_add_value_int(root, "Power Cycle Count", @@ -5122,6 +5191,9 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 json_object_add_value_string(root, "Result", fail_str); } + json_print_object(root, NULL); + printf("\n"); + entryIdx++; if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES) entryIdx = 0; @@ -5179,15 +5251,15 @@ static void wdc_print_fw_act_history_log_json(__u8 *data, int num_entries, __u32 json_object_add_value_string(root, "Result", fail_str); } + json_print_object(root, NULL); + printf("\n"); + entryIdx++; if (entryIdx >= WDC_MAX_NUM_ACT_HIST_ENTRIES) entryIdx = 0; } } - json_print_object(root, NULL); - printf("\n"); - json_free_object(root); } @@ -5205,7 +5277,7 @@ static int nvme_get_ext_smart_cloud_log(int fd, __u8 **data, int uuid_index, __u struct nvme_get_log_args args = { .args_size = sizeof(args), .fd = fd, - .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, .nsid = namespace_id, .lpo = 0, .lsp = NVME_LOG_LSP_NONE, @@ -5626,10 +5698,12 @@ static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask) else printf(" SMART Cloud Attributes :- \n"); - printf(" Physical Media Units Written TLC (Bytes) : %'.0Lf\n", - int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt)); - printf(" Physical Media Units Written SLC (Bytes) : %'.0Lf\n", - int128_to_double(ext_smart_log_ptr->ext_smart_pmuws)); + printf(" Physical Media Units Written TLC (Bytes) : %s\n", + uint128_t_to_string(le128_to_cpu( + ext_smart_log_ptr->ext_smart_pmuwt))); + printf(" Physical Media Units Written SLC (Bytes) : %s\n", + uint128_t_to_string(le128_to_cpu( + ext_smart_log_ptr->ext_smart_pmuws))); printf(" Bad User NAND Block Count (Normalized) (Int) : %d\n", le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc)); printf(" Bad User NAND Block Count (Raw) (Int) : %"PRIu64"\n", @@ -5677,8 +5751,9 @@ static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask) le64_to_cpu(ext_smart_log_ptr->ext_smart_svn)); printf(" %% Free Blocks (System) (Int) : %d %%\n", ext_smart_log_ptr->ext_smart_pfbs); - printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int) : %'.0Lf\n", - int128_to_double(ext_smart_log_ptr->ext_smart_dcc)); + printf(" NVMe Stats (# Data Set Management/TRIM Commands Completed) (Int) : %s\n", + uint128_t_to_string(le128_to_cpu( + ext_smart_log_ptr->ext_smart_dcc))); printf(" Total Namespace Utilization (nvme0n1 NUSE) (Bytes) : %"PRIu64"\n", le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu)); printf(" NVMe Stats (# NVMe Format Commands Completed) (Int) : %d\n", @@ -5696,16 +5771,18 @@ static void wdc_print_ext_smart_cloud_log_normal(void *data, int mask) le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc)); printf(" Bad System NAND Block Count (Raw) (Int) : %"PRIu64"\n", le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000)); - printf(" Endurance Estimate (Total Writable Lifetime Bytes) (Bytes) : %'.0Lf\n", - int128_to_double(ext_smart_log_ptr->ext_smart_eest)); + printf(" Endurance Estimate (Total Writable Lifetime Bytes) (Bytes) : %s\n", + uint128_t_to_string( + le128_to_cpu(ext_smart_log_ptr->ext_smart_eest))); if (mask == WDC_SCA_V1_ALL) { printf(" Thermal Throttling Status & Count (Number of thermal throttling events) (Int) : %d\n", le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc)); printf(" Total # Unaligned I/O (Int) : %"PRIu64"\n", le64_to_cpu(ext_smart_log_ptr->ext_smart_uio)); } - printf(" Total Physical Media Units Read (Bytes) (Int) : %'.0Lf\n", - int128_to_double(ext_smart_log_ptr->ext_smart_pmur)); + printf(" Total Physical Media Units Read (Bytes) (Int) : %s\n", + uint128_t_to_string( + le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur))); if (mask == WDC_SCA_V1_ALL) { printf(" Command Timeout (# of READ Commands > 5 Seconds) (Int) : %"PRIu32"\n", le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc)); @@ -5746,10 +5823,10 @@ static void wdc_print_ext_smart_cloud_log_json(void *data, int mask) struct json_object *root; root = json_create_object(); - json_object_add_value_double(root, "physical_media_units_bytes_tlc", - int128_to_double(ext_smart_log_ptr->ext_smart_pmuwt)); - json_object_add_value_double(root, "physical_media_units_bytes_slc", - int128_to_double(ext_smart_log_ptr->ext_smart_pmuws)); + json_object_add_value_uint128(root, "physical_media_units_bytes_tlc", + le128_to_cpu(ext_smart_log_ptr->ext_smart_pmuwt)); + json_object_add_value_uint128(root, "physical_media_units_bytes_slc", + le128_to_cpu(ext_smart_log_ptr->ext_smart_pmuws)); json_object_add_value_uint(root, "bad_user_blocks_normalized", le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bunbc)); json_object_add_value_uint64(root, "bad_user_blocks_raw", @@ -5797,8 +5874,8 @@ static void wdc_print_ext_smart_cloud_log_json(void *data, int mask) le64_to_cpu(ext_smart_log_ptr->ext_smart_svn)); json_object_add_value_uint(root, "pct_free_blocks_system", (__u8)ext_smart_log_ptr->ext_smart_pfbs); - json_object_add_value_double(root, "num_of_trim_commands", - int128_to_double(ext_smart_log_ptr->ext_smart_dcc)); + json_object_add_value_uint128(root, "num_of_trim_commands", + le128_to_cpu(ext_smart_log_ptr->ext_smart_dcc)); json_object_add_value_uint64(root, "total_nuse_bytes", le64_to_cpu(ext_smart_log_ptr->ext_smart_tnu)); json_object_add_value_uint(root, "num_of_format_commands", @@ -5816,16 +5893,16 @@ static void wdc_print_ext_smart_cloud_log_json(void *data, int mask) le16_to_cpu(*(uint16_t *)ext_smart_log_ptr->ext_smart_bsnbc)); json_object_add_value_uint64(root, "bad_system_block_raw", le64_to_cpu(*(uint64_t *)ext_smart_log_ptr->ext_smart_bsnbc & 0xFFFFFFFFFFFF0000)); - json_object_add_value_double(root, "endurance_est_bytes", - int128_to_double(ext_smart_log_ptr->ext_smart_eest)); + json_object_add_value_uint128(root, "endurance_est_bytes", + le128_to_cpu(ext_smart_log_ptr->ext_smart_eest)); if (mask == WDC_SCA_V1_ALL) { json_object_add_value_uint(root, "num_throttling_events", le16_to_cpu(ext_smart_log_ptr->ext_smart_ttc)); json_object_add_value_uint64(root, "total_unaligned_io", le64_to_cpu(ext_smart_log_ptr->ext_smart_uio)); } - json_object_add_value_double(root, "physical_media_units_read_bytes", - int128_to_double(ext_smart_log_ptr->ext_smart_pmur)); + json_object_add_value_uint128(root, "physical_media_units_read_bytes", + le128_to_cpu(ext_smart_log_ptr->ext_smart_pmur)); if (mask == WDC_SCA_V1_ALL) { json_object_add_value_uint(root, "num_read_timeouts", le32_to_cpu(ext_smart_log_ptr->ext_smart_rtoc)); @@ -5874,8 +5951,10 @@ static void wdc_print_smart_cloud_attr_C0_normal(void *data) printf(" SMART Cloud Attributes :- \n"); - printf(" Physical media units written : %'.0Lf\n", int128_to_double(&log_data[SCAO_PMUW])); - printf(" Physical media units read : %'.0Lf\n", int128_to_double(&log_data[SCAO_PMUR])); + printf(" Physical media units written : %s\n", + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PMUW]))); + printf(" Physical media units read : %s\n", + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PMUR]))); printf(" Bad user nand blocks Raw : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); printf(" Bad user nand blocks Normalized : %d\n", @@ -5916,8 +5995,10 @@ static void wdc_print_smart_cloud_attr_C0_normal(void *data) (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); printf(" NUSE Namespace utilization : %"PRIu64"\n", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); - printf(" PLP start count : %'.0Lf\n", int128_to_double(&log_data[SCAO_PSC])); - printf(" Endurance estimate : %'.0Lf\n", int128_to_double(&log_data[SCAO_EEST])); + printf(" PLP start count : %s\n", + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_PSC]))); + printf(" Endurance estimate : %s\n", + uint128_t_to_string(le128_to_cpu(&log_data[SCAO_EEST]))); smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); printf(" Log page version : %"PRIu16"\n",smart_log_ver); printf(" Log page GUID : 0x"); @@ -5951,10 +6032,10 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) uint16_t smart_log_ver = 0; root = json_create_object(); - json_object_add_value_double(root, "Physical media units written", - int128_to_double(&log_data[SCAO_PMUW])); - json_object_add_value_double(root, "Physical media units read", - int128_to_double(&log_data[SCAO_PMUR])); + json_object_add_value_uint128(root, "Physical media units written", + le128_to_cpu(&log_data[SCAO_PMUW])); + json_object_add_value_uint128(root, "Physical media units read", + le128_to_cpu(&log_data[SCAO_PMUR])); json_object_add_value_uint64(root, "Bad user nand blocks - Raw", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF)); json_object_add_value_uint(root, "Bad user nand blocks - Normalized", @@ -5999,10 +6080,10 @@ static void wdc_print_smart_cloud_attr_C0_json(void *data) (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN])); json_object_add_value_uint64(root, "NUSE - Namespace utilization", (uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE])); - json_object_add_value_double(root, "PLP start count", - int128_to_double(&log_data[SCAO_PSC])); - json_object_add_value_double(root, "Endurance estimate", - int128_to_double(&log_data[SCAO_EEST])); + json_object_add_value_uint128(root, "PLP start count", + le128_to_cpu(&log_data[SCAO_PSC])); + json_object_add_value_uint128(root, "Endurance estimate", + le128_to_cpu(&log_data[SCAO_EEST])); smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]); json_object_add_value_uint(root, "Log page version", smart_log_ver); char guid[40]; @@ -6135,7 +6216,7 @@ static int wdc_print_c0_eol_log(void *data, int fmt) return 0; } -static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, +static int wdc_get_c0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format, int uuid_index, __u32 namespace_id) { int ret = 0; @@ -6145,7 +6226,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, __u32 cust_id; uint32_t device_id, read_vendor_id; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -6153,7 +6234,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, return fmt; } - ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); switch (device_id) { @@ -6173,7 +6254,8 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, case WDC_NVME_SN560_DEV_ID_1: case WDC_NVME_SN560_DEV_ID_2: case WDC_NVME_SN560_DEV_ID_3: - cust_id = wdc_get_fw_cust_id(r, fd); + case WDC_NVME_SN550_DEV_ID: + cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; @@ -6189,7 +6271,8 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, } if (namespace_id == NVME_NSID_ALL) { - ret = nvme_get_nsid(fd, &namespace_id); + ret = nvme_get_nsid(dev_fd(dev), + &namespace_id); if (ret < 0) { namespace_id = NVME_NSID_ALL; } @@ -6198,8 +6281,8 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, /* Get the 0xC0 log data */ struct nvme_get_log_args args = { .args_size = sizeof(args), - .fd = fd, - .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + .fd = dev_fd(dev), + .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, .nsid = namespace_id, .lpo = 0, .lsp = NVME_LOG_LSP_NONE, @@ -6261,7 +6344,7 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, /* Get the 0xC0 log data */ struct nvme_get_log_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .lid = WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, .nsid = NVME_NSID_ALL, .lpo = 0, @@ -6302,8 +6385,10 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, } /* Get the 0xC0 log data */ - ret = nvme_get_log_simple(fd, WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, - WDC_NVME_EOL_STATUS_LOG_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), + WDC_NVME_GET_EOL_STATUS_LOG_OPCODE, + WDC_NVME_EOL_STATUS_LOG_LEN, + data); if (strcmp(format, "json")) nvme_show_status(ret); @@ -6328,8 +6413,9 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, } /* Get the 0xC0 log data */ - ret = nvme_get_log_simple(fd, WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, - WDC_NVME_SMART_CLOUD_ATTR_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), + WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, + WDC_NVME_SMART_CLOUD_ATTR_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); @@ -6348,7 +6434,8 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, case WDC_NVME_SN820CL_DEV_ID: /* Get the 0xC0 Extended Smart Cloud Attribute log data */ data = NULL; - ret = nvme_get_ext_smart_cloud_log(fd, &data, uuid_index, namespace_id); + ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, + uuid_index, namespace_id); if (strcmp(format, "json")) nvme_show_status(ret); @@ -6375,7 +6462,9 @@ static int wdc_get_c0_log_page(nvme_root_t r, int fd, char *format, return ret; } -static int wdc_print_latency_monitor_log(int fd, struct wdc_ssd_latency_monitor_log *log_data, int fmt) +static int wdc_print_latency_monitor_log(struct nvme_dev *dev, + struct wdc_ssd_latency_monitor_log *log_data, + int fmt) { if (!log_data) { fprintf(stderr, "ERROR : WDC : Invalid C3 log data buffer\n"); @@ -6383,7 +6472,7 @@ static int wdc_print_latency_monitor_log(int fd, struct wdc_ssd_latency_monitor_ } switch (fmt) { case NORMAL: - wdc_print_latency_monitor_log_normal(fd, log_data); + wdc_print_latency_monitor_log_normal(dev, log_data); break; case JSON: wdc_print_latency_monitor_log_json(log_data); @@ -6460,7 +6549,7 @@ static int wdc_print_fb_ca_log(struct wdc_ssd_ca_perf_stats *perf, int fmt) return 0; } -static int wdc_print_bd_ca_log(void *bd_data, int fmt) +static int wdc_print_bd_ca_log(struct nvme_dev *dev, void *bd_data, int fmt) { if (!bd_data) { fprintf(stderr, "ERROR : WDC : Invalid buffer to read data\n"); @@ -6468,7 +6557,7 @@ static int wdc_print_bd_ca_log(void *bd_data, int fmt) } switch (fmt) { case NORMAL: - wdc_print_bd_ca_log_normal(bd_data); + wdc_print_bd_ca_log_normal(dev, bd_data); break; case JSON: wdc_print_bd_ca_log_json(bd_data); @@ -6515,7 +6604,7 @@ static int wdc_print_fw_act_history_log(__u8 *data, int num_entries, int fmt, __ return 0; } -static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format) +static int wdc_get_ca_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { int ret = 0; int fmt = -1; @@ -6524,7 +6613,7 @@ static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format) uint32_t read_device_id, read_vendor_id; __u32 cust_id; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -6533,19 +6622,19 @@ static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format) } /* verify the 0xCA log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) { + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == false) { fprintf(stderr, "ERROR : WDC : 0xCA Log Page not supported\n"); return -1; } /* get the FW customer id */ - cust_id = wdc_get_fw_cust_id(r, fd); + cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); return -1; } - ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); switch (read_device_id) { @@ -6560,8 +6649,9 @@ static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - WDC_FB_CA_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), + WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, + WDC_FB_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); @@ -6596,8 +6686,9 @@ static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FB_CA_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - WDC_FB_CA_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), + WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, + WDC_FB_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); @@ -6617,14 +6708,15 @@ static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_BD_CA_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, - WDC_BD_CA_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), + WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE, + WDC_BD_CA_LOG_BUF_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); if (ret == 0) { /* parse the data */ - ret = wdc_print_bd_ca_log(data, fmt); + ret = wdc_print_bd_ca_log(dev, data, fmt); } else { fprintf(stderr, "ERROR : WDC : Unable to read CA Log Page data\n"); ret = -1; @@ -6649,7 +6741,7 @@ static int wdc_get_ca_log_page(nvme_root_t r, int fd, char *format) return ret; } -static int wdc_get_c1_log_page(nvme_root_t r, int fd, +static int wdc_get_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *format, uint8_t interval) { int ret = 0; @@ -6663,7 +6755,7 @@ static int wdc_get_c1_log_page(nvme_root_t r, int fd, struct wdc_log_page_subpage_header *sph; struct wdc_ssd_perf_stats *perf; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -6682,8 +6774,8 @@ static int wdc_get_c1_log_page(nvme_root_t r, int fd, } memset(data, 0, sizeof (__u8) * WDC_ADD_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_NVME_ADD_LOG_OPCODE, - WDC_ADD_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_ADD_LOG_OPCODE, + WDC_ADD_LOG_BUF_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); if (ret == 0) { @@ -6708,7 +6800,7 @@ static int wdc_get_c1_log_page(nvme_root_t r, int fd, return ret; } -static int wdc_get_c3_log_page(nvme_root_t r, int fd, char *format) +static int wdc_get_c3_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { int ret = 0; int fmt = -1; @@ -6716,7 +6808,7 @@ static int wdc_get_c3_log_page(nvme_root_t r, int fd, char *format) int i; struct wdc_ssd_latency_monitor_log *log_data; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -6730,7 +6822,7 @@ static int wdc_get_c3_log_page(nvme_root_t r, int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_LATENCY_MON_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_LATENCY_MON_OPCODE, + ret = nvme_get_log_simple(dev_fd(dev), WDC_LATENCY_MON_LOG_ID, WDC_LATENCY_MON_LOG_BUF_LEN, data); if (strcmp(format, "json")) @@ -6768,7 +6860,7 @@ static int wdc_get_c3_log_page(nvme_root_t r, int fd, char *format) } /* parse the data */ - wdc_print_latency_monitor_log(fd, log_data, fmt); + wdc_print_latency_monitor_log(dev, log_data, fmt); } else { fprintf(stderr, "ERROR : WDC : Unable to read C3 data from buffer\n"); } @@ -6779,7 +6871,7 @@ out: } -static int wdc_get_ocp_c1_log_page(nvme_root_t r, int fd, char *format) +static int wdc_get_ocp_c1_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { int ret = 0; int fmt = -1; @@ -6787,7 +6879,7 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, int fd, char *format) int i; struct wdc_ocp_c1_error_recovery_log *log_data; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -6801,8 +6893,8 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_ERROR_REC_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_ERROR_REC_LOG_ID, - WDC_ERROR_REC_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), WDC_ERROR_REC_LOG_ID, + WDC_ERROR_REC_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); @@ -6811,7 +6903,8 @@ static int wdc_get_ocp_c1_log_page(nvme_root_t r, int fd, char *format) log_data = (struct wdc_ocp_c1_error_recovery_log *)data; /* check log page version */ - if (log_data->log_page_version != WDC_ERROR_REC_LOG_VERSION) { + if ((log_data->log_page_version != WDC_ERROR_REC_LOG_VERSION1) && + (log_data->log_page_version != WDC_ERROR_REC_LOG_VERSION2)) { fprintf(stderr, "ERROR : WDC : invalid error recovery log version - %d\n", log_data->log_page_version); ret = -1; goto out; @@ -6848,7 +6941,7 @@ out: return ret; } -static int wdc_get_ocp_c4_log_page(nvme_root_t r, int fd, char *format) +static int wdc_get_ocp_c4_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { int ret = 0; int fmt = -1; @@ -6856,7 +6949,7 @@ static int wdc_get_ocp_c4_log_page(nvme_root_t r, int fd, char *format) int i; struct wdc_ocp_C4_dev_cap_log *log_data; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -6870,8 +6963,8 @@ static int wdc_get_ocp_c4_log_page(nvme_root_t r, int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_DEV_CAP_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_DEV_CAP_LOG_ID, - WDC_DEV_CAP_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), WDC_DEV_CAP_LOG_ID, + WDC_DEV_CAP_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); @@ -6893,7 +6986,7 @@ static int wdc_get_ocp_c4_log_page(nvme_root_t r, int fd, char *format) int j; fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); for (j = 0; j<16; j++) { - fprintf(stderr, "%x", wdc_ocp_c1_guid[j]); + fprintf(stderr, "%x", wdc_ocp_c4_guid[j]); } fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); for (j = 0; j<16; j++) { @@ -6917,7 +7010,7 @@ out: return ret; } -static int wdc_get_ocp_c5_log_page(nvme_root_t r, int fd, char *format) +static int wdc_get_ocp_c5_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { int ret = 0; int fmt = -1; @@ -6925,7 +7018,7 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, int fd, char *format) int i; struct wdc_ocp_C5_unsupported_reqs *log_data; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -6939,8 +7032,8 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_UNSUPPORTED_REQS_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_UNSUPPORTED_REQS_LOG_ID, - WDC_UNSUPPORTED_REQS_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), WDC_UNSUPPORTED_REQS_LOG_ID, + WDC_UNSUPPORTED_REQS_LOG_BUF_LEN, data); if (strcmp(format, "json")) fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret, false), ret); @@ -6962,7 +7055,7 @@ static int wdc_get_ocp_c5_log_page(nvme_root_t r, int fd, char *format) int j; fprintf(stderr, "ERROR : WDC : Expected GUID: 0x"); for (j = 0; j<16; j++) { - fprintf(stderr, "%x", wdc_ocp_c1_guid[j]); + fprintf(stderr, "%x", wdc_ocp_c5_guid[j]); } fprintf(stderr, "\nERROR : WDC : Actual GUID: 0x"); for (j = 0; j<16; j++) { @@ -6986,14 +7079,14 @@ out: return ret; } -static int wdc_get_d0_log_page(nvme_root_t r, int fd, char *format) +static int wdc_get_d0_log_page(nvme_root_t r, struct nvme_dev *dev, char *format) { int ret = 0; int fmt = -1; __u8 *data; struct wdc_ssd_d0_smart_log *perf; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); if (fmt < 0) { @@ -7002,7 +7095,7 @@ static int wdc_get_d0_log_page(nvme_root_t r, int fd, char *format) } /* verify the 0xD0 log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) { + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_VU_SMART_LOG_OPCODE) == false) { fprintf(stderr, "ERROR : WDC : 0xD0 Log Page not supported\n"); return -1; } @@ -7013,8 +7106,9 @@ static int wdc_get_d0_log_page(nvme_root_t r, int fd, char *format) } memset(data, 0, sizeof (__u8) * WDC_NVME_VU_SMART_LOG_LEN); - ret = nvme_get_log_simple(fd, WDC_NVME_GET_VU_SMART_LOG_OPCODE, - WDC_NVME_VU_SMART_LOG_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), + WDC_NVME_GET_VU_SMART_LOG_OPCODE, + WDC_NVME_VU_SMART_LOG_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); @@ -7036,10 +7130,10 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, { const char *desc = "Retrieve additional performance statistics."; const char *interval = "Interval to read the statistics from [1, 15]."; - int fd; const char *log_page_version = "Log Page Version: 0 = vendor, 1 = WDC"; const char *log_page_mask = "Log Page Mask, comma separated list: 0xC0, 0xC1, 0xCA, 0xD0"; const char *namespace_id = "desired namespace id"; + struct nvme_dev *dev; nvme_root_t r; int ret = 0; int uuid_index = 0; @@ -7072,9 +7166,9 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); if (cfg.log_page_version == 0) { @@ -7121,7 +7215,7 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC: Unknown log page mask - %s\n", cfg.log_page_mask); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_SMART_LOG_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7132,35 +7226,37 @@ static int wdc_vs_smart_add_log(int argc, char **argv, struct command *command, if (((capabilities & WDC_DRIVE_CAP_C0_LOG_PAGE) == WDC_DRIVE_CAP_C0_LOG_PAGE) && (page_mask & WDC_C0_PAGE_MASK)) { /* Get 0xC0 log page if possible. */ - ret = wdc_get_c0_log_page(r, fd, cfg.output_format, uuid_index, cfg.namespace_id); + ret = wdc_get_c0_log_page(r, dev, cfg.output_format, + uuid_index, cfg.namespace_id); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the C0 Log Page, ret = %d\n", ret); } if (((capabilities & (WDC_DRIVE_CAP_CA_LOG_PAGE)) == (WDC_DRIVE_CAP_CA_LOG_PAGE)) && (page_mask & WDC_CA_PAGE_MASK)) { /* Get the CA Log Page */ - ret = wdc_get_ca_log_page(r, fd, cfg.output_format); + ret = wdc_get_ca_log_page(r, dev, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the CA Log Page, ret = %d\n", ret); } if (((capabilities & WDC_DRIVE_CAP_C1_LOG_PAGE) == WDC_DRIVE_CAP_C1_LOG_PAGE) && (page_mask & WDC_C1_PAGE_MASK)) { /* Get the C1 Log Page */ - ret = wdc_get_c1_log_page(r, fd, cfg.output_format, cfg.interval); + ret = wdc_get_c1_log_page(r, dev, cfg.output_format, + cfg.interval); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the C1 Log Page, ret = %d\n", ret); } if (((capabilities & WDC_DRIVE_CAP_D0_LOG_PAGE) == WDC_DRIVE_CAP_D0_LOG_PAGE) && (page_mask & WDC_D0_PAGE_MASK)) { /* Get the D0 Log Page */ - ret = wdc_get_d0_log_page(r, fd, cfg.output_format); + ret = wdc_get_d0_log_page(r, dev, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the D0 Log Page, ret = %d\n", ret); } out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7169,12 +7265,11 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, { const char *desc = "Retrieve Cloud Log Smart/Health Information"; const char *namespace_id = "desired namespace id"; - int fd; - nvme_root_t r; - int ret = 0; __u64 capabilities = 0; + struct nvme_dev *dev; + int ret, fmt = -1; + nvme_root_t r; __u8 *data; - int fmt = -1; struct config { char *output_format; @@ -7192,13 +7287,13 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CLOUD_LOG_PAGE) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7207,7 +7302,8 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, } data = NULL; - ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, cfg.namespace_id); + ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, + cfg.namespace_id); if (strcmp(cfg.output_format, "json")) nvme_show_status(ret); @@ -7231,7 +7327,7 @@ static int wdc_vs_cloud_log(int argc, char **argv, struct command *command, out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7240,12 +7336,11 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, { const char *desc = "Retrieve Hardware Revision Log Information"; const char *namespace_id = "desired namespace id"; - int fd; - nvme_root_t r; - int ret = 0; __u64 capabilities = 0; + struct nvme_dev *dev; + int ret, fmt = -1; __u8 *data = NULL; - int fmt = -1; + nvme_root_t r; struct config { char *output_format; @@ -7263,13 +7358,13 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_HW_REV_LOG_PAGE) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7277,7 +7372,7 @@ static int wdc_vs_hw_rev_log(int argc, char **argv, struct command *command, goto out; } - ret = nvme_get_hw_rev_log(fd, &data, 0, cfg.namespace_id); + ret = nvme_get_hw_rev_log(dev_fd(dev), &data, 0, cfg.namespace_id); if (strcmp(cfg.output_format, "json")) nvme_show_status(ret); @@ -7314,7 +7409,7 @@ free_buf: out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7324,8 +7419,8 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, const char *desc = "Retrieve Device Write Amplication Factor"; const char *namespace_id = "desired namespace id"; struct nvme_smart_log smart_log; + struct nvme_dev *dev; __u8 *data; - int fd; nvme_root_t r; int ret = 0; int fmt = -1; @@ -7354,13 +7449,13 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_DEVICE_WAF) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7369,7 +7464,8 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, } /* get data units written from the smart log page */ - ret = nvme_get_log_smart(fd, cfg.namespace_id, false, &smart_log); + ret = nvme_get_log_smart(dev_fd(dev), cfg.namespace_id, false, + &smart_log); if (!ret) { data_units_written = int128_to_double(smart_log.data_units_written); } @@ -7385,7 +7481,8 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, /* get Physical Media Units Written from extended smart/C0 log page */ data = NULL; - ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, cfg.namespace_id); + ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, + cfg.namespace_id); if (ret == 0) { ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data; @@ -7438,7 +7535,7 @@ static int wdc_vs_device_waf(int argc, char **argv, struct command *command, out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7446,10 +7543,10 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co struct plugin *plugin) { const char *desc = "Retrieve latency monitor log data."; + __u64 capabilities = 0; + struct nvme_dev *dev; nvme_root_t r; - int fd; int ret = 0; - __u64 capabilities = 0; struct config { char *output_format; @@ -7464,12 +7561,12 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_C3_LOG_PAGE) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7477,13 +7574,13 @@ static int wdc_get_latency_monitor_log(int argc, char **argv, struct command *co goto out; } - ret = wdc_get_c3_log_page(r, fd, cfg.output_format); + ret = wdc_get_c3_log_page(r, dev, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the Latency Monitor (C3) Log Page, ret = %d\n", ret); out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7491,10 +7588,10 @@ static int wdc_get_error_recovery_log(int argc, char **argv, struct command *com struct plugin *plugin) { const char *desc = "Retrieve error recovery log data."; + __u64 capabilities = 0; + struct nvme_dev *dev; nvme_root_t r; - int fd; int ret = 0; - __u64 capabilities = 0; struct config { char *output_format; @@ -7509,12 +7606,12 @@ static int wdc_get_error_recovery_log(int argc, char **argv, struct command *com OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_OCP_C1_LOG_PAGE) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7522,13 +7619,13 @@ static int wdc_get_error_recovery_log(int argc, char **argv, struct command *com goto out; } - ret = wdc_get_ocp_c1_log_page(r, fd, cfg.output_format); + ret = wdc_get_ocp_c1_log_page(r, dev, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the Error Recovery (C1) Log Page, ret = 0x%x\n", ret); out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7536,10 +7633,10 @@ static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *c struct plugin *plugin) { const char *desc = "Retrieve device capabilities log data."; + __u64 capabilities = 0; + struct nvme_dev *dev; nvme_root_t r; - int fd; int ret = 0; - __u64 capabilities = 0; struct config { char *output_format; @@ -7554,12 +7651,12 @@ static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *c OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_OCP_C4_LOG_PAGE) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7567,13 +7664,13 @@ static int wdc_get_dev_capabilities_log(int argc, char **argv, struct command *c goto out; } - ret = wdc_get_ocp_c4_log_page(r, fd, cfg.output_format); + ret = wdc_get_ocp_c4_log_page(r, dev, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the Device Capabilities (C4) Log Page, ret = 0x%x\n", ret); out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7581,10 +7678,10 @@ static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *c struct plugin *plugin) { const char *desc = "Retrieve unsupported requirements log data."; + __u64 capabilities = 0; + struct nvme_dev *dev; nvme_root_t r; - int fd; int ret = 0; - __u64 capabilities = 0; struct config { char *output_format; @@ -7599,12 +7696,12 @@ static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *c OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_OCP_C5_LOG_PAGE) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); @@ -7612,13 +7709,13 @@ static int wdc_get_unsupported_reqs_log(int argc, char **argv, struct command *c goto out; } - ret = wdc_get_ocp_c5_log_page(r, fd, cfg.output_format); + ret = wdc_get_ocp_c5_log_page(r, dev, cfg.output_format); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the Unsupported Requirements (C5) Log Page, ret = 0x%x\n", ret); out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7667,25 +7764,26 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma struct plugin *plugin) { char *desc = "Clear PCIE Correctable Errors."; - int fd, ret; - nvme_root_t r; __u64 capabilities = 0; + struct nvme_dev *dev; + nvme_root_t r; + int ret; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - if (!wdc_check_device(r, fd)) { + if (!wdc_check_device(r, dev)) { ret = -1; goto out; } - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CLEAR_PCIE_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -7693,18 +7791,18 @@ static int wdc_clear_pcie_correctable_errors(int argc, char **argv, struct comma } if (capabilities & WDC_DRIVE_CAP_CLEAR_PCIE) { - ret = wdc_do_clear_pcie_correctable_errors(fd); + ret = wdc_do_clear_pcie_correctable_errors(dev_fd(dev)); } else if (capabilities & WDC_DRIVE_CAP_VUC_CLEAR_PCIE) { - ret = wdc_do_clear_pcie_correctable_errors_vuc(fd); + ret = wdc_do_clear_pcie_correctable_errors_vuc(dev_fd(dev)); } else { - ret = wdc_do_clear_pcie_correctable_errors_fid(fd); + ret = wdc_do_clear_pcie_correctable_errors_fid(dev_fd(dev)); } out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7712,7 +7810,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, struct plugin *plugin) { char *desc = "Get Drive Status."; - int fd; + struct nvme_dev *dev; int ret = 0; nvme_root_t r; __le32 system_eol_state; @@ -7727,12 +7825,12 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_DRIVE_STATUS) != WDC_DRIVE_CAP_DRIVE_STATUS) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -7740,41 +7838,42 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, } /* verify the 0xC2 Device Manageability log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) { + if (wdc_nvme_check_supported_log_page(r, dev, + WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE) == false) { fprintf(stderr, "ERROR : WDC : 0xC2 Log Page not supported\n"); ret = -1; goto out; } /* Get the assert dump present status */ - if (!wdc_nvme_get_dev_status_log_data(r, fd, &assert_status, + if (!wdc_nvme_get_dev_status_log_data(r, dev, &assert_status, WDC_C2_ASSERT_DUMP_PRESENT_ID)) fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n"); /* Get the thermal throttling status */ - if (!wdc_nvme_get_dev_status_log_data(r, fd, &thermal_status, + if (!wdc_nvme_get_dev_status_log_data(r, dev, &thermal_status, WDC_C2_THERMAL_THROTTLE_STATUS_ID)) fprintf(stderr, "ERROR : WDC : Get Thermal Throttling Status Failed\n"); /* Get EOL status */ - if (!wdc_nvme_get_dev_status_log_data(r, fd, &eol_status, + if (!wdc_nvme_get_dev_status_log_data(r, dev, &eol_status, WDC_C2_USER_EOL_STATUS_ID)) { fprintf(stderr, "ERROR : WDC : Get User EOL Status Failed\n"); eol_status = cpu_to_le32(-1); } /* Get Customer EOL state */ - if (!wdc_nvme_get_dev_status_log_data(r, fd, &user_eol_state, + if (!wdc_nvme_get_dev_status_log_data(r, dev, &user_eol_state, WDC_C2_USER_EOL_STATE_ID)) fprintf(stderr, "ERROR : WDC : Get User EOL State Failed\n"); /* Get System EOL state*/ - if (!wdc_nvme_get_dev_status_log_data(r, fd, &system_eol_state, + if (!wdc_nvme_get_dev_status_log_data(r, dev, &system_eol_state, WDC_C2_SYSTEM_EOL_STATE_ID)) fprintf(stderr, "ERROR : WDC : Get System EOL State Failed\n"); /* Get format corrupt reason*/ - if (!wdc_nvme_get_dev_status_log_data(r, fd, &format_corrupt_reason, + if (!wdc_nvme_get_dev_status_log_data(r, dev, &format_corrupt_reason, WDC_C2_FORMAT_CORRUPT_REASON_ID)) fprintf(stderr, "ERROR : WDC : Get Format Corrupt Reason Failed\n"); @@ -7822,7 +7921,7 @@ static int wdc_drive_status(int argc, char **argv, struct command *command, out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -7830,7 +7929,7 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, struct plugin *plugin) { char *desc = "Clear Assert Dump Present Status."; - int fd; + struct nvme_dev *dev; int ret = -1; nvme_root_t r; __le32 assert_status = cpu_to_le32(0xFFFFFFFF); @@ -7841,18 +7940,18 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CLEAR_ASSERT) != WDC_DRIVE_CAP_CLEAR_ASSERT) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; goto out; } - if (!wdc_nvme_get_dev_status_log_data(r, fd, &assert_status, + if (!wdc_nvme_get_dev_status_log_data(r, dev, &assert_status, WDC_C2_ASSERT_DUMP_PRESENT_ID)) { fprintf(stderr, "ERROR : WDC : Get Assert Status Failed\n"); ret = -1; @@ -7866,25 +7965,27 @@ static int wdc_clear_assert_dump(int argc, char **argv, struct command *command, admin_cmd.cdw12 = ((WDC_NVME_CLEAR_ASSERT_DUMP_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_CLEAR_ASSERT_DUMP_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, + NULL); nvme_show_status(ret); } else fprintf(stderr, "INFO : WDC : No Assert Dump Present\n"); out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } -static int wdc_get_fw_act_history(nvme_root_t r, int fd, char *format) +static int wdc_get_fw_act_history(nvme_root_t r, struct nvme_dev *dev, + char *format) { int ret = 0; int fmt = -1; __u8 *data; struct wdc_fw_act_history_log_hdr *fw_act_history_hdr; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); @@ -7894,7 +7995,7 @@ static int wdc_get_fw_act_history(nvme_root_t r, int fd, char *format) } /* verify the FW Activate History log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == false) { + if (wdc_nvme_check_supported_log_page(r, dev, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID) == false) { fprintf(stderr, "ERROR : WDC : %d Log Page not supported\n", WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID); return -1; } @@ -7906,8 +8007,9 @@ static int wdc_get_fw_act_history(nvme_root_t r, int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, - WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), + WDC_NVME_GET_FW_ACT_HISTORY_LOG_ID, + WDC_FW_ACT_HISTORY_LOG_BUF_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); @@ -7935,13 +8037,13 @@ static int wdc_get_fw_act_history(nvme_root_t r, int fd, char *format) return ret; } -static __u32 wdc_get_fw_cust_id(nvme_root_t r, int fd) +static __u32 wdc_get_fw_cust_id(nvme_root_t r, struct nvme_dev *dev) { __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))) { + if (!(get_dev_mgment_cbs_data(r, dev, 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; @@ -7951,7 +8053,8 @@ static __u32 wdc_get_fw_cust_id(nvme_root_t r, int fd) return cust_id; } -static int wdc_get_fw_act_history_C2(nvme_root_t r, int fd, char *format) +static int wdc_get_fw_act_history_C2(nvme_root_t r, struct nvme_dev *dev, + char *format) { int ret = 0; int fmt = -1; @@ -7961,7 +8064,7 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, int fd, char *format) __u32 tot_entries = 0, num_entries = 0; __u32 vendor_id = 0, device_id = 0; - if (!wdc_check_device(r, fd)) + if (!wdc_check_device(r, dev)) return -1; fmt = validate_output_format(format); @@ -7970,7 +8073,7 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, int fd, char *format) return fmt; } - ret = wdc_get_pci_ids(r, &device_id, &vendor_id); + ret = wdc_get_pci_ids(r, dev, &device_id, &vendor_id); if ((data = (__u8*) malloc(sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN)) == NULL) { fprintf(stderr, "ERROR : WDC : malloc : %s\n", strerror(errno)); @@ -7979,8 +8082,9 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, int fd, char *format) memset(data, 0, sizeof (__u8) * WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN); - ret = nvme_get_log_simple(fd, WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID, - WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data); + ret = nvme_get_log_simple(dev_fd(dev), + WDC_NVME_GET_FW_ACT_HISTORY_C2_LOG_ID, + WDC_FW_ACT_HISTORY_C2_LOG_BUF_LEN, data); if (strcmp(format, "json")) nvme_show_status(ret); @@ -7992,7 +8096,7 @@ static int wdc_get_fw_act_history_C2(nvme_root_t r, int fd, char *format) if (tot_entries > 0) { /* get the FW customer id */ - cust_id = wdc_get_fw_cust_id(r, fd); + cust_id = wdc_get_fw_cust_id(r, dev); if (cust_id == WDC_INVALID_CUSTOMER_ID) { fprintf(stderr, "%s: ERROR : WDC : invalid customer id\n", __func__); ret = -1; @@ -8018,12 +8122,11 @@ freeData: static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *command, struct plugin *plugin) { - int fd; - int ret = 0; - nvme_root_t r; - __u64 capabilities = 0; const char *desc = "Retrieve FW activate history table."; - + __u64 capabilities = 0; + struct nvme_dev *dev; + nvme_root_t r; + int ret; struct config { char *output_format; @@ -8038,13 +8141,12 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -8068,8 +8170,8 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com /* Get the 0xC0 log data */ struct nvme_get_log_args args = { .args_size = sizeof(args), - .fd = fd, - .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_OPCODE, + .fd = dev_fd(dev), + .lid = WDC_NVME_GET_SMART_CLOUD_ATTR_LOG_ID, .nsid = 0xFFFFFFFF, .lpo = 0, .lsp = NVME_LOG_LSP_NONE, @@ -8101,21 +8203,22 @@ static int wdc_vs_fw_activate_history(int argc, char **argv, struct command *com free(data); if (c0GuidMatch) { - ret = wdc_get_fw_act_history_C2(r, fd, + ret = wdc_get_fw_act_history_C2(r, dev, cfg.output_format); } else { - ret = wdc_get_fw_act_history(r, fd, cfg.output_format); + ret = wdc_get_fw_act_history(r, dev, + cfg.output_format); } } else { - ret = wdc_get_fw_act_history_C2(r, fd, cfg.output_format); + ret = wdc_get_fw_act_history_C2(r, dev, cfg.output_format); } if (ret) fprintf(stderr, "ERROR : WDC : Failure reading the FW Activate History, ret = %d\n", ret); out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -8152,21 +8255,21 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * struct plugin *plugin) { char *desc = "Clear FW activate history table."; - int fd; - int ret = -1; - nvme_root_t r; __u64 capabilities = 0; + struct nvme_dev *dev; + nvme_root_t r; + int ret; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY_MASK) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -8174,13 +8277,13 @@ static int wdc_clear_fw_activate_history(int argc, char **argv, struct command * } if (capabilities & WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY) - ret = wdc_do_clear_fw_activate_history_vuc(fd); + ret = wdc_do_clear_fw_activate_history_vuc(dev_fd(dev)); else - ret = wdc_do_clear_fw_activate_history_fid(fd); + ret = wdc_do_clear_fw_activate_history_fid(dev_fd(dev)); out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -8191,11 +8294,11 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm char *disable = "Disable controller option of the telemetry log page."; char *enable = "Enable controller option of the telemetry log page."; char *status = "Displays the current state of the controller initiated log page."; - int fd; - int ret = -1; - nvme_root_t r; __u64 capabilities = 0; + struct nvme_dev *dev; + nvme_root_t r; __u32 result; + int ret = -1; struct config { @@ -8217,12 +8320,12 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) != WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -8238,19 +8341,22 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm } if (cfg.disable) { - ret = nvme_set_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 1, - false, &result); + ret = nvme_set_features_simple(dev_fd(dev), + WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + 0, 1, false, &result); - wdc_clear_reason_id(fd); + wdc_clear_reason_id(dev); } else { if (cfg.enable) { - ret = nvme_set_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, 0, - false, &result); + ret = nvme_set_features_simple(dev_fd(dev), + WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + 0, 0, false, &result); } else if (cfg.status) { - ret = nvme_get_features_simple(fd, WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, 0, - &result); + ret = nvme_get_features_simple(dev_fd(dev), + WDC_VU_DISABLE_CNTLR_TELEMETRY_OPTION_FEATURE_ID, + 0, &result); if (ret == 0) { if (result) fprintf(stderr, "Controller Option Telemetry Log Page State: Disabled\n"); @@ -8271,12 +8377,12 @@ static int wdc_vs_telemetry_controller_option(int argc, char **argv, struct comm out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } -static int wdc_get_serial_and_fw_rev(int fd, char *sn, char *fw_rev) +static int wdc_get_serial_and_fw_rev(struct nvme_dev *dev, char *sn, char *fw_rev) { int i; int ret; @@ -8286,7 +8392,7 @@ static int wdc_get_serial_and_fw_rev(int fd, char *sn, char *fw_rev) memset(sn, 0, WDC_SERIAL_NO_LEN); memset(fw_rev, 0, WDC_NVME_FIRMWARE_REV_LEN); memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(fd, &ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", ret); @@ -8303,7 +8409,7 @@ static int wdc_get_serial_and_fw_rev(int fd, char *sn, char *fw_rev) return 0; } -static int wdc_get_max_transfer_len(int fd, __u32 *maxTransferLen) +static int wdc_get_max_transfer_len(struct nvme_dev *dev, __u32 *maxTransferLen) { int ret = 0; struct nvme_id_ctrl ctrl; @@ -8311,7 +8417,7 @@ static int wdc_get_max_transfer_len(int fd, __u32 *maxTransferLen) __u32 maxTransferLenDevice = 0; memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(fd, &ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed 0x%x\n", ret); return -1; @@ -8323,12 +8429,13 @@ static int wdc_get_max_transfer_len(int fd, __u32 *maxTransferLen) return ret; } -static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logSize) +static int wdc_de_VU_read_size(struct nvme_dev *dev, __u32 fileId, + __u16 spiDestn, __u32* logSize) { int ret = WDC_STATUS_FAILURE; struct nvme_passthru_cmd cmd; - if(!fd || !logSize ) + if(!dev || !logSize ) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; @@ -8340,7 +8447,7 @@ static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logS cmd.cdw13 = fileId<<16; cmd.cdw14 = spiDestn; - ret = nvme_submit_admin_passthru(fd, &cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); if (!ret && logSize) *logSize = cmd.result; @@ -8353,13 +8460,15 @@ static int wdc_de_VU_read_size(int fd, __u32 fileId, __u16 spiDestn, __u32* logS return ret; } -static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 offsetInDwords, __u8* dataBuffer, __u32* bufferSize) +static int wdc_de_VU_read_buffer(struct nvme_dev *dev, __u32 fileId, + __u16 spiDestn, __u32 offsetInDwords, + __u8* dataBuffer, __u32* bufferSize) { int ret = WDC_STATUS_FAILURE; struct nvme_passthru_cmd cmd; __u32 noOfDwordExpected = 0; - if(!fd || !dataBuffer || !bufferSize) + if(!dev || !dataBuffer || !bufferSize) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; @@ -8377,7 +8486,7 @@ static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 off cmd.addr = (__u64)(__u64)(uintptr_t)dataBuffer; cmd.data_len = *bufferSize; - ret = nvme_submit_admin_passthru(fd, &cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &cmd, NULL); if( ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR : WDC : VUReadBuffer() failed, "); @@ -8388,7 +8497,7 @@ static int wdc_de_VU_read_buffer(int fd, __u32 fileId, __u16 spiDestn, __u32 off return ret; } -static int wdc_get_log_dir_max_entries(int fd, __u32* maxNumOfEntries) +static int wdc_get_log_dir_max_entries(struct nvme_dev *dev, __u32* maxNumOfEntries) { int ret = WDC_STATUS_FAILURE; __u32 headerPayloadSize = 0; @@ -8398,13 +8507,13 @@ static int wdc_get_log_dir_max_entries(int fd, __u32* maxNumOfEntries) __u16 fileOffset = 0; - if (!fd || !maxNumOfEntries) + if (!dev || !maxNumOfEntries) { ret = WDC_STATUS_INVALID_PARAMETER; return ret; } /* 1.Get log directory first four bytes */ - if (WDC_STATUS_SUCCESS != (ret = wdc_de_VU_read_size(fd, 0, 5, (__u32*)&headerPayloadSize))) + if (WDC_STATUS_SUCCESS != (ret = wdc_de_VU_read_size(dev, 0, 5, (__u32*)&headerPayloadSize))) { fprintf(stderr, "ERROR : WDC : %s: Failed to get headerPayloadSize from file directory 0x%x\n", __func__, ret); @@ -8415,7 +8524,7 @@ static int wdc_get_log_dir_max_entries(int fd, __u32* maxNumOfEntries) fileIdOffsetsBuffer = (__u8*)calloc(1, fileIdOffsetsBufferSize); /* 2.Read to get file offsets */ - if (WDC_STATUS_SUCCESS != (ret = wdc_de_VU_read_buffer(fd, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize))) + if (WDC_STATUS_SUCCESS != (ret = wdc_de_VU_read_buffer(dev, 0, 5, 0, fileIdOffsetsBuffer, &fileIdOffsetsBufferSize))) { fprintf(stderr, "ERROR : WDC : %s: Failed to get fileIdOffsets from file directory 0x%x\n", __func__, ret); @@ -8455,7 +8564,7 @@ static WDC_DRIVE_ESSENTIAL_TYPE wdc_get_essential_type(__u8 fileName[]) return essentialType; } -static int wdc_fetch_log_directory(int fd, PWDC_DE_VU_LOG_DIRECTORY directory) +static int wdc_fetch_log_directory(struct nvme_dev *dev, PWDC_DE_VU_LOG_DIRECTORY directory) { int ret = WDC_STATUS_FAILURE; __u8 *fileOffset = NULL; @@ -8466,12 +8575,12 @@ static int wdc_fetch_log_directory(int fd, PWDC_DE_VU_LOG_DIRECTORY directory) __u32 entryId = 0; __u32 fileDirectorySize = 0; - if (!fd || !directory) { + if (!dev || !directory) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } - ret = wdc_de_VU_read_size(fd, 0, 5, &fileDirectorySize); + ret = wdc_de_VU_read_size(dev, 0, 5, &fileDirectorySize); if (WDC_STATUS_SUCCESS != ret) { fprintf(stderr, "ERROR : WDC : %s: Failed to get filesystem directory size, ret = %d\n", @@ -8480,7 +8589,7 @@ static int wdc_fetch_log_directory(int fd, PWDC_DE_VU_LOG_DIRECTORY directory) } fileDirectory = (__u8*)calloc(1, fileDirectorySize); - ret = wdc_de_VU_read_buffer(fd, 0, 5, 0, fileDirectory, &fileDirectorySize); + ret = wdc_de_VU_read_buffer(dev, 0, 5, 0, fileDirectory, &fileDirectorySize); if (WDC_STATUS_SUCCESS != ret) { fprintf(stderr, "ERROR : WDC : %s: Failed to get filesystem directory, ret = %d\n", @@ -8533,7 +8642,8 @@ end: return ret; } -static int wdc_fetch_log_file_from_device(int fd, __u32 fileId, __u16 spiDestn, __u64 fileSize, __u8* dataBuffer) +static int wdc_fetch_log_file_from_device(struct nvme_dev *dev, __u32 fileId, + __u16 spiDestn, __u64 fileSize, __u8* dataBuffer) { int ret = WDC_STATUS_FAILURE; __u32 chunckSize = WDC_DE_VU_READ_BUFFER_STANDARD_OFFSET; @@ -8541,13 +8651,13 @@ static int wdc_fetch_log_file_from_device(int fd, __u32 fileId, __u16 spiDestn, __u32 buffSize = 0; __u64 offsetIdx = 0; - if (!fd || !dataBuffer || !fileSize) + if (!dev || !dataBuffer || !fileSize) { ret = WDC_STATUS_INVALID_PARAMETER; goto end; } - if (wdc_get_max_transfer_len(fd, &maximumTransferLength) < 0) { + if (wdc_get_max_transfer_len(dev, &maximumTransferLength) < 0) { ret = WDC_STATUS_FAILURE; goto end; } @@ -8565,7 +8675,7 @@ static int wdc_fetch_log_file_from_device(int fd, __u32 fileId, __u16 spiDestn, if (((offsetIdx * chunckSize) + buffSize) > fileSize) buffSize = (__u32)(fileSize - (offsetIdx * chunckSize)); /* Limitation in VU read buffer - offsetIdx and bufferSize are not greater than u32 */ - ret = wdc_de_VU_read_buffer(fd, fileId, spiDestn, + ret = wdc_de_VU_read_buffer(dev, fileId, spiDestn, (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer + (offsetIdx * chunckSize), &buffSize); if (ret != WDC_STATUS_SUCCESS) { @@ -8576,7 +8686,7 @@ static int wdc_fetch_log_file_from_device(int fd, __u32 fileId, __u16 spiDestn, } } else { buffSize = (__u32)fileSize; - ret = wdc_de_VU_read_buffer(fd, fileId, spiDestn, + ret = wdc_de_VU_read_buffer(dev, fileId, spiDestn, (__u32)((offsetIdx * chunckSize) / sizeof(__u32)), dataBuffer, &buffSize); if (ret != WDC_STATUS_SUCCESS) { @@ -8589,7 +8699,7 @@ static int wdc_fetch_log_file_from_device(int fd, __u32 fileId, __u16 spiDestn, return ret; } -static int wdc_de_get_dump_trace(int fd, char * filePath, __u16 binFileNameLen, char *binFileName) +static int wdc_de_get_dump_trace(struct nvme_dev *dev, char * filePath, __u16 binFileNameLen, char *binFileName) { int ret = WDC_STATUS_FAILURE; __u8 *readBuffer = NULL; @@ -8604,19 +8714,19 @@ static int wdc_de_get_dump_trace(int fd, char * filePath, __u16 binFileNameLen, __u16 i = 0; __u32 maximumTransferLength = 0; - if (!fd || !binFileName || !filePath) + if (!dev || !binFileName || !filePath) { ret = WDC_STATUS_INVALID_PARAMETER; return ret; } - if (wdc_get_max_transfer_len(fd, &maximumTransferLength) < 0) + if (wdc_get_max_transfer_len(dev, &maximumTransferLength) < 0) return WDC_STATUS_FAILURE; do { /* Get dumptrace size */ - ret = wdc_de_VU_read_size(fd, 0, WDC_DE_DUMPTRACE_DESTINATION, &dumptraceSize); + ret = wdc_de_VU_read_size(dev, 0, WDC_DE_DUMPTRACE_DESTINATION, &dumptraceSize); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR : WDC : %s: wdc_de_VU_read_size failed with ret = %d\n", @@ -8665,7 +8775,7 @@ static int wdc_de_get_dump_trace(int fd, char * filePath, __u16 binFileNameLen, readBufferLen = lastPktReadBufferLen; } - ret = wdc_de_VU_read_buffer(fd, 0, WDC_DE_DUMPTRACE_DESTINATION, 0, readBuffer + offset, &readBufferLen); + ret = wdc_de_VU_read_buffer(dev, 0, WDC_DE_DUMPTRACE_DESTINATION, 0, readBuffer + offset, &readBufferLen); if (ret != WDC_STATUS_SUCCESS) { fprintf(stderr, "ERROR : WDC : %s: wdc_de_VU_read_buffer failed, ret = %d on offset 0x%x\n", @@ -8692,7 +8802,8 @@ static int wdc_de_get_dump_trace(int fd, char * filePath, __u16 binFileNameLen, return ret; } -static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) +static int wdc_do_drive_essentials(nvme_root_t r, struct nvme_dev *dev, + char *dir, char *key) { int ret = 0; void *retPtr; @@ -8732,7 +8843,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) memset(tarCmd,0,sizeof(tarCmd)); memset(&timeInfo,0,sizeof(timeInfo)); - if (wdc_get_serial_and_fw_rev(fd, (char *)idSerialNo, (char *)idFwRev)) + if (wdc_get_serial_and_fw_rev(dev, (char *)idSerialNo, (char *)idFwRev)) { fprintf(stderr, "ERROR : WDC : get serial # and fw revision failed\n"); return -1; @@ -8785,7 +8896,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) /* Get Identify Controller Data */ memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(fd, &ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed, ret = %d\n", ret); return -1; @@ -8796,7 +8907,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) } memset(&ns, 0, sizeof (struct nvme_id_ns)); - ret = nvme_identify_ns(fd, 1, &ns); + ret = nvme_identify_ns(dev_fd(dev), 1, &ns); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ns() failed, ret = %d\n", ret); } else { @@ -8811,7 +8922,8 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) dataBuffer = calloc(1, elogBufferSize); elogBuffer = (struct nvme_error_log_page *)dataBuffer; - ret = nvme_get_log_error(fd, elogNumEntries, false, elogBuffer); + ret = nvme_get_log_error(dev_fd(dev), elogNumEntries, false, + elogBuffer); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_error_log() failed, ret = %d\n", ret); } else { @@ -8825,7 +8937,8 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) /* Get Smart log page */ memset(&smart_log, 0, sizeof (struct nvme_smart_log)); - ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart_log); + ret = nvme_get_log_smart(dev_fd(dev), NVME_NSID_ALL, false, + &smart_log); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_smart_log() failed, ret = %d\n", ret); } else { @@ -8836,7 +8949,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) /* Get FW Slot log page */ memset(&fw_log, 0, sizeof (struct nvme_firmware_slot)); - ret = nvme_get_log_fw_slot(fd, false, &fw_log); + ret = nvme_get_log_fw_slot(dev_fd(dev), false, &fw_log); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_fw_log() failed, ret = %d\n", ret); } else { @@ -8856,8 +8969,9 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) dataBuffer = calloc(1, dataBufferSize); memset(dataBuffer, 0, dataBufferSize); - ret = nvme_get_log_simple(fd, deVULogPagesList[vuLogIdx].logPageId, - dataBufferSize, dataBuffer); + ret = nvme_get_log_simple(dev_fd(dev), + deVULogPagesList[vuLogIdx].logPageId, + dataBufferSize, dataBuffer); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_get_log() for log page 0x%x failed, ret = %d\n", deVULogPagesList[vuLogIdx].logPageId, ret); @@ -8881,8 +8995,11 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) /* skipping LbaRangeType as it is an optional nvme command and not supported */ if (deFeatureIdList[listIdx].featureId == FID_LBA_RANGE_TYPE) continue; - ret = nvme_get_features_data(fd, deFeatureIdList[listIdx].featureId, WDC_DE_GLOBAL_NSID, - sizeof(featureIdBuff), &featureIdBuff, &result); + ret = nvme_get_features_data(dev_fd(dev), + (enum nvme_features_id)deFeatureIdList[listIdx].featureId, + WDC_DE_GLOBAL_NSID, + sizeof(featureIdBuff), + &featureIdBuff, &result); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_get_feature id 0x%x failed, ret = %d\n", @@ -8896,7 +9013,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) } /* Read Debug Directory */ - ret = wdc_get_log_dir_max_entries(fd, &maxNumOfVUFiles); + ret = wdc_get_log_dir_max_entries(dev, &maxNumOfVUFiles); if (ret == WDC_STATUS_SUCCESS) { memset(&deEssentialsList, 0, sizeof(deEssentialsList)); @@ -8904,7 +9021,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) deEssentialsList.maxNumLogEntries = maxNumOfVUFiles; /* Fetch VU File Directory */ - ret = wdc_fetch_log_directory(fd, &deEssentialsList); + ret = wdc_fetch_log_directory(dev, &deEssentialsList); if (ret == WDC_STATUS_SUCCESS) { /* Get Debug Data Files */ @@ -8918,7 +9035,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) } else { /* Fetch Log File Data */ dataBuffer = (char *)calloc(1, (size_t)deEssentialsList.logEntry[listIdx].metaData.fileSize); - ret = wdc_fetch_log_file_from_device(fd, deEssentialsList.logEntry[listIdx].metaData.fileID, WDC_DE_DESTN_SPI, deEssentialsList.logEntry[listIdx].metaData.fileSize, + ret = wdc_fetch_log_file_from_device(dev, deEssentialsList.logEntry[listIdx].metaData.fileID, WDC_DE_DESTN_SPI, deEssentialsList.logEntry[listIdx].metaData.fileSize, (__u8 *)dataBuffer); /* Write databuffer to file */ @@ -8954,7 +9071,7 @@ static int wdc_do_drive_essentials(nvme_root_t r, int fd, char *dir, char *key) /* Get Dump Trace Data */ wdc_UtilsSnprintf(fileName, MAX_PATH_LEN, "%s%s%s_%s_%s.bin", (char*)bufferFolderPath, WDC_DE_PATH_SEPARATOR, "dumptrace", serialNo, timeString); - if (WDC_STATUS_SUCCESS != (ret = wdc_de_get_dump_trace(fd, (char*)bufferFolderPath, 0, fileName))) + if (WDC_STATUS_SUCCESS != (ret = wdc_de_get_dump_trace(dev, (char*)bufferFolderPath, 0, fileName))) { fprintf(stderr, "ERROR : WDC : wdc_de_get_dump_trace failed, ret = %d\n", ret); } @@ -8987,10 +9104,11 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, char *dirName = "Output directory pathname."; char d[PATH_MAX] = {0}; char k[PATH_MAX] = {0}; - char *d_ptr; - int fd, ret; - nvme_root_t r; __u64 capabilities = 0; + struct nvme_dev *dev; + nvme_root_t r; + char *d_ptr; + int ret; struct config { char *dirName; @@ -9006,12 +9124,12 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_DRIVE_ESSENTIALS) != WDC_DRIVE_CAP_DRIVE_ESSENTIALS) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -9025,14 +9143,14 @@ static int wdc_drive_essentials(int argc, char **argv, struct command *command, d_ptr = NULL; } - ret = wdc_do_drive_essentials(r, fd, d_ptr, k); + ret = wdc_do_drive_essentials(r, dev, d_ptr, k); out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } -static int wdc_do_drive_resize(int fd, uint64_t new_size) +static int wdc_do_drive_resize(struct nvme_dev *dev, uint64_t new_size) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -9043,11 +9161,11 @@ static int wdc_do_drive_resize(int fd, uint64_t new_size) WDC_NVME_DRIVE_RESIZE_CMD); admin_cmd.cdw13 = new_size; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); return ret; } -static int wdc_do_namespace_resize(int fd, __u32 nsid, __u32 op_option) +static int wdc_do_namespace_resize(struct nvme_dev *dev, __u32 nsid, __u32 op_option) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -9057,11 +9175,11 @@ static int wdc_do_namespace_resize(int fd, __u32 nsid, __u32 op_option) admin_cmd.nsid = nsid; admin_cmd.cdw10 = op_option; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); return ret; } -static int wdc_do_drive_info(int fd, __u32 *result) +static int wdc_do_drive_info(struct nvme_dev *dev, __u32 *result) { int ret; struct nvme_passthru_cmd admin_cmd; @@ -9071,7 +9189,7 @@ static int wdc_do_drive_info(int fd, __u32 *result) admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD << WDC_NVME_SUBCMD_SHIFT) | WDC_NVME_DRIVE_INFO_CMD); - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); if (!ret && result) *result = admin_cmd.result; @@ -9084,9 +9202,10 @@ static int wdc_drive_resize(int argc, char **argv, { const char *desc = "Send a Resize command."; const char *size = "The new size (in GB) to resize the drive to."; - nvme_root_t r; uint64_t capabilities = 0; - int fd, ret; + struct nvme_dev *dev; + nvme_root_t r; + int ret; struct config { uint64_t size; @@ -9101,15 +9220,15 @@ static int wdc_drive_resize(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - wdc_check_device(r, fd); - capabilities = wdc_get_drive_capabilities(r, fd); + wdc_check_device(r, dev); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_RESIZE) == WDC_DRIVE_CAP_RESIZE) { - ret = wdc_do_drive_resize(fd, cfg.size); + ret = wdc_do_drive_resize(dev, cfg.size); } else { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -9120,7 +9239,7 @@ static int wdc_drive_resize(int argc, char **argv, nvme_show_status(ret); nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -9130,9 +9249,10 @@ static int wdc_namespace_resize(int argc, char **argv, const char *desc = "Send a Namespace Resize command."; const char *namespace_id = "The namespace id to resize."; const char *op_option = "The over provisioning option to set for namespace."; - nvme_root_t r; uint64_t capabilities = 0; - int fd, ret; + struct nvme_dev *dev; + nvme_root_t r; + int ret; struct config { __u32 namespace_id; @@ -9150,9 +9270,9 @@ static int wdc_namespace_resize(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; if ((cfg.op_option != 0x1) && (cfg.op_option != 0x2) && @@ -9160,15 +9280,16 @@ static int wdc_namespace_resize(int argc, char **argv, (cfg.op_option != 0xF)) { fprintf(stderr, "ERROR : WDC: unsupported OP option parameter\n"); - close(fd); + dev_close(dev); return -1; } r = nvme_scan(NULL); - wdc_check_device(r, fd); - capabilities = wdc_get_drive_capabilities(r, fd); + wdc_check_device(r, dev); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_NS_RESIZE) == WDC_DRIVE_CAP_NS_RESIZE) { - ret = wdc_do_namespace_resize(fd, cfg.namespace_id, cfg.op_option); + ret = wdc_do_namespace_resize(dev, cfg.namespace_id, + cfg.op_option); if (ret != 0) printf("ERROR : WDC: Namespace Resize of namespace id 0x%x, op option 0x%x failed\n", cfg.namespace_id, cfg.op_option); @@ -9179,7 +9300,7 @@ static int wdc_namespace_resize(int argc, char **argv, nvme_show_status(ret); nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -9189,8 +9310,8 @@ static int wdc_reason_identifier(int argc, char **argv, const char *desc = "Retrieve telemetry log reason identifier."; const char *log_id = "Log ID to retrieve - host - 7 or controller - 8"; const char *fname = "File name to save raw binary identifier"; + struct nvme_dev *dev; nvme_root_t r; - int fd; int ret; uint64_t capabilities = 0; char f[PATH_MAX] = {0}; @@ -9214,10 +9335,10 @@ static int wdc_reason_identifier(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); + ret = parse_and_open(&dev, argc, argv, desc, opts); - if (fd < 0) - return fd; + if (ret) + return ret; r = nvme_scan(NULL); @@ -9250,7 +9371,7 @@ static int wdc_reason_identifier(int argc, char **argv, else snprintf(fileSuffix, PATH_MAX, "_error_reason_identifier_host_%s", (char*)timeStamp); - if (wdc_get_serial_name(fd, f, PATH_MAX, fileSuffix) == -1) { + if (wdc_get_serial_name(dev, f, PATH_MAX, fileSuffix) == -1) { fprintf(stderr, "ERROR : WDC: failed to generate file name\n"); ret = -1; goto close_fd; @@ -9265,9 +9386,9 @@ static int wdc_reason_identifier(int argc, char **argv, fprintf(stderr, "%s: filename = %s\n", __func__, f); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_REASON_ID) == WDC_DRIVE_CAP_REASON_ID) { - ret = wdc_do_get_reason_id(fd, f, cfg.log_id); + ret = wdc_do_get_reason_id(dev, f, cfg.log_id); } else { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -9276,7 +9397,7 @@ static int wdc_reason_identifier(int argc, char **argv, nvme_show_status(ret); close_fd: - close(fd); + dev_close(dev); nvme_free_tree(r); return ret; } @@ -9328,7 +9449,7 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command struct plugin *plugin) { const char *desc = "Retrieve Log Page Directory."; - int fd; + struct nvme_dev *dev; int ret = 0; nvme_root_t r; __u64 capabilities = 0; @@ -9350,36 +9471,36 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; ret = validate_output_format(cfg.output_format); if (ret < 0) { fprintf(stderr, "%s: ERROR : WDC : invalid output format\n", __func__); - close(fd); + dev_close(dev); return ret; } ret = 0; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_LOG_PAGE_DIR) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; } else { - ret = wdc_get_pci_ids(r, &device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, dev, &device_id, &read_vendor_id); log_id = (device_id == WDC_NVME_ZN350_DEV_ID || device_id == WDC_NVME_ZN350_DEV_ID_1) ? WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE_C8 : WDC_NVME_GET_DEV_MGMNT_LOG_PAGE_OPCODE; /* verify the 0xC2 Device Manageability log page is supported */ - if (wdc_nvme_check_supported_log_page(r, fd, log_id) == false) { + if (wdc_nvme_check_supported_log_page(r, dev, log_id) == false) { fprintf(stderr, "%s: ERROR : WDC : 0x%x Log Page not supported\n", __func__, log_id); ret = -1; goto out; } - if (get_dev_mgment_cbs_data(r, fd, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { + if (get_dev_mgment_cbs_data(r, dev, WDC_C2_LOG_PAGES_SUPPORTED_ID, (void *)&cbs_data)) { if (cbs_data != NULL) { printf("Log Page Directory\n"); /* print the supported pages */ @@ -9416,11 +9537,11 @@ static int wdc_log_page_directory(int argc, char **argv, struct command *command out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } -static int wdc_get_drive_reason_id(int fd, char *drive_reason_id, size_t len) +static int wdc_get_drive_reason_id(struct nvme_dev *dev, char *drive_reason_id, size_t len) { int i, j; int ret; @@ -9432,7 +9553,7 @@ static int wdc_get_drive_reason_id(int fd, char *drive_reason_id, size_t len) j = sizeof (ctrl.mn) - 1; memset(drive_reason_id, 0, len); memset(&ctrl, 0, sizeof (struct nvme_id_ctrl)); - ret = nvme_identify_ctrl(fd, &ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC : nvme_identify_ctrl() failed " "0x%x\n", ret); @@ -9459,7 +9580,7 @@ static int wdc_get_drive_reason_id(int fd, char *drive_reason_id, size_t len) return 0; } -static int wdc_save_reason_id(int fd, __u8 *rsn_ident, int size) +static int wdc_save_reason_id(struct nvme_dev *dev, __u8 *rsn_ident, int size) { int ret = 0; char *reason_id_file; @@ -9467,7 +9588,7 @@ static int wdc_save_reason_id(int fd, __u8 *rsn_ident, int size) char reason_id_path[PATH_MAX] = WDC_REASON_ID_PATH_NAME; struct stat st = {0}; - if (wdc_get_drive_reason_id(fd, drive_reason_id, PATH_MAX) == -1) { + if (wdc_get_drive_reason_id(dev, drive_reason_id, PATH_MAX) == -1) { fprintf(stderr, "%s: ERROR : failed to get drive reason id\n", __func__); return -1; } @@ -9494,14 +9615,14 @@ static int wdc_save_reason_id(int fd, __u8 *rsn_ident, int size) return ret; } -static int wdc_clear_reason_id(int fd) +static int wdc_clear_reason_id(struct nvme_dev *dev) { int ret = -1; int verify_file; char *reason_id_file; char drive_reason_id[PATH_MAX] = {0}; - if (wdc_get_drive_reason_id(fd, drive_reason_id, PATH_MAX) == -1) { + if (wdc_get_drive_reason_id(dev, drive_reason_id, PATH_MAX) == -1) { fprintf(stderr, "%s: ERROR : failed to get drive reason id\n", __func__); return -1; } @@ -9527,14 +9648,15 @@ static int wdc_clear_reason_id(int fd) return ret; } -static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log *log_hdr) +static int wdc_dump_telemetry_hdr(struct nvme_dev *dev, int log_id, struct nvme_telemetry_log *log_hdr) { int ret = 0; if (log_id == NVME_LOG_LID_TELEMETRY_HOST) - ret = nvme_get_log_create_telemetry_host(fd, log_hdr); + ret = nvme_get_log_create_telemetry_host(dev_fd(dev), log_hdr); else - ret = nvme_get_log_telemetry_ctrl(fd, false, 0, 512, (void *)log_hdr); + ret = nvme_get_log_telemetry_ctrl(dev_fd(dev), false, 0, 512, + (void *)log_hdr); if (ret < 0) perror("get-telemetry-log"); @@ -9546,7 +9668,7 @@ static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log return ret; } -static int wdc_do_get_reason_id(int fd, char *file, int log_id) +static int wdc_do_get_reason_id(struct nvme_dev *dev, char *file, int log_id) { int ret; struct nvme_telemetry_log *log_hdr; @@ -9561,7 +9683,7 @@ static int wdc_do_get_reason_id(int fd, char *file, int log_id) } memset(log_hdr, 0, log_hdr_size); - ret = wdc_dump_telemetry_hdr(fd, log_id, log_hdr); + ret = wdc_dump_telemetry_hdr(dev, log_id, log_hdr); if (ret != 0) { fprintf(stderr, "%s: ERROR : get telemetry header failed, ret : %d\n", __func__, ret); ret = -1; @@ -9571,7 +9693,7 @@ static int wdc_do_get_reason_id(int fd, char *file, int log_id) reason_id_size = sizeof(log_hdr->rsnident); if (log_id == NVME_LOG_LID_TELEMETRY_CTRL) - wdc_save_reason_id(fd, log_hdr->rsnident, reason_id_size); + wdc_save_reason_id(dev, log_hdr->rsnident, reason_id_size); ret = wdc_create_log_file(file, (__u8 *)log_hdr->rsnident, reason_id_size); @@ -9592,10 +9714,12 @@ static void wdc_print_nand_stats_normal(__u16 version, void *data) { case 0: printf(" NAND Statistics :- \n"); - printf(" NAND Writes TLC (Bytes) %.0Lf\n", - int128_to_double(nand_stats->nand_write_tlc)); - printf(" NAND Writes SLC (Bytes) %.0Lf\n", - int128_to_double(nand_stats->nand_write_slc)); + printf(" NAND Writes TLC (Bytes) %s\n", + uint128_t_to_string( + le128_to_cpu(nand_stats->nand_write_tlc))); + printf(" NAND Writes SLC (Bytes) %s\n", + uint128_t_to_string( + le128_to_cpu(nand_stats->nand_write_slc))); printf(" NAND Program Failures %"PRIu32"\n", (uint32_t)le32_to_cpu(nand_stats->nand_prog_failure)); printf(" NAND Erase Failures %"PRIu32"\n", @@ -9613,10 +9737,12 @@ static void wdc_print_nand_stats_normal(__u16 version, void *data) break; case 3: printf(" NAND Statistics V3:- \n"); - printf(" TLC Units Written %.0Lf\n", - int128_to_double(nand_stats_v3->nand_write_tlc)); - printf(" SLC Units Written %.0Lf\n", - int128_to_double(nand_stats_v3->nand_write_slc)); + printf(" TLC Units Written %s\n", + uint128_t_to_string( + le128_to_cpu(nand_stats_v3->nand_write_tlc))); + printf(" SLC Units Written %s\n", + uint128_t_to_string( + le128_to_cpu(nand_stats_v3->nand_write_slc))); temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count; temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF); temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16); @@ -9666,8 +9792,9 @@ static void wdc_print_nand_stats_normal(__u16 version, void *data) le64_to_cpu(nand_stats_v3->security_version_number)); printf(" %% Free Blocks (System) %u\n", nand_stats_v3->percent_free_blocks_system); - printf(" Data Set Management Commands %.0Lf\n", - int128_to_double(nand_stats_v3->trim_completions)); + printf(" Data Set Management Commands %s\n", + uint128_t_to_string( + le128_to_cpu(nand_stats_v3->trim_completions))); printf(" Estimate of Incomplete Trim Data %"PRIu64"\n", le64_to_cpu(nand_stats_v3->trim_completions[16])); printf(" %% of completed trim %u\n", @@ -9685,16 +9812,18 @@ static void wdc_print_nand_stats_normal(__u16 version, void *data) le16_to_cpu(temp_norm)); printf(" Bad System Nand Block Count - Raw %"PRIu64"\n", le64_to_cpu(temp_raw)); - printf(" Endurance Estimate %.0Lf\n", - int128_to_double(nand_stats_v3->endurance_estimate)); + printf(" Endurance Estimate %s\n", + uint128_t_to_string( + le128_to_cpu(nand_stats_v3->endurance_estimate))); printf(" Thermal Throttling Count %u\n", nand_stats_v3->thermal_throttling_st_ct[0]); printf(" Thermal Throttling Status %u\n", nand_stats_v3->thermal_throttling_st_ct[1]); printf(" Unaligned I/O %"PRIu64"\n", le64_to_cpu(nand_stats_v3->unaligned_IO)); - printf(" Physical Media Units Read %.0Lf\n", - int128_to_double(nand_stats_v3->physical_media_units)); + printf(" Physical Media Units Read %s\n", + uint128_t_to_string( + le128_to_cpu(nand_stats_v3->physical_media_units))); printf(" log page version %"PRIu16"\n", le16_to_cpu(nand_stats_v3->log_page_version)); break; @@ -9721,10 +9850,10 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) case 0: - json_object_add_value_double(root, "NAND Writes TLC (Bytes)", - int128_to_double(nand_stats->nand_write_tlc)); - json_object_add_value_double(root, "NAND Writes SLC (Bytes)", - int128_to_double(nand_stats->nand_write_slc)); + json_object_add_value_uint128(root, "NAND Writes TLC (Bytes)", + le128_to_cpu(nand_stats->nand_write_tlc)); + json_object_add_value_uint128(root, "NAND Writes SLC (Bytes)", + le128_to_cpu(nand_stats->nand_write_slc)); json_object_add_value_uint(root, "NAND Program Failures", le32_to_cpu(nand_stats->nand_prog_failure)); json_object_add_value_uint(root, "NAND Erase Failures", @@ -9744,10 +9873,10 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) case 3: - json_object_add_value_double(root, "NAND Writes TLC (Bytes)", - int128_to_double(nand_stats_v3->nand_write_tlc)); - json_object_add_value_double(root, "NAND Writes SLC (Bytes)", - int128_to_double(nand_stats_v3->nand_write_slc)); + json_object_add_value_uint128(root, "NAND Writes TLC (Bytes)", + le128_to_cpu(nand_stats_v3->nand_write_tlc)); + json_object_add_value_uint128(root, "NAND Writes SLC (Bytes)", + le128_to_cpu(nand_stats_v3->nand_write_slc)); temp_ptr = (__u64 *)nand_stats_v3->bad_nand_block_count; temp_norm = (__u16)(*temp_ptr & 0x000000000000FFFF); temp_raw = ((*temp_ptr & 0xFFFFFFFFFFFF0000) >> 16); @@ -9797,8 +9926,8 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) le64_to_cpu(nand_stats_v3->security_version_number)); json_object_add_value_uint(root, "% Free Blocks (System)", nand_stats_v3->percent_free_blocks_system); - json_object_add_value_double(root, "Data Set Management Commands", - int128_to_double(nand_stats_v3->trim_completions)); + json_object_add_value_uint128(root, "Data Set Management Commands", + le128_to_cpu(nand_stats_v3->trim_completions)); json_object_add_value_uint64(root, "Estimate of Incomplete Trim Data", le64_to_cpu(nand_stats_v3->trim_completions[16])); json_object_add_value_uint(root, "%% of completed trim", @@ -9816,16 +9945,16 @@ static void wdc_print_nand_stats_json(__u16 version, void *data) le16_to_cpu(temp_norm)); json_object_add_value_uint64(root, "Bad System Nand Block Count - Raw", le64_to_cpu(temp_raw)); - json_object_add_value_double(root, "Endurance Estimate", - int128_to_double(nand_stats_v3->endurance_estimate)); + json_object_add_value_uint128(root, "Endurance Estimate", + le128_to_cpu(nand_stats_v3->endurance_estimate)); json_object_add_value_uint(root, "Thermal Throttling Status", nand_stats_v3->thermal_throttling_st_ct[0]); json_object_add_value_uint(root, "Thermal Throttling Count", nand_stats_v3->thermal_throttling_st_ct[1]); json_object_add_value_uint64(root, "Unaligned I/O", le64_to_cpu(nand_stats_v3->unaligned_IO)); - json_object_add_value_double(root, "Physical Media Units Read", - int128_to_double(nand_stats_v3->physical_media_units)); + json_object_add_value_uint128(root, "Physical Media Units Read", + le128_to_cpu(nand_stats_v3->physical_media_units)); json_object_add_value_uint(root, "log page version", le16_to_cpu(nand_stats_v3->log_page_version)); @@ -9926,14 +10055,15 @@ static void wdc_print_pcie_stats_json(struct wdc_vs_pcie_stats *pcie_stats) json_free_object(root); } -static int wdc_do_vs_nand_stats_sn810_2(int fd, char *format) +static int wdc_do_vs_nand_stats_sn810_2(struct nvme_dev *dev, char *format) { int ret; int fmt = -1; uint8_t *data = NULL; data = NULL; - ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, NVME_NSID_ALL); + ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, + NVME_NSID_ALL); if (ret) { fprintf(stderr, "ERROR : WDC : %s : Failed to retreive NAND stats\n", __func__); @@ -9963,7 +10093,7 @@ out: return ret; } -static int wdc_do_vs_nand_stats(int fd, char *format) +static int wdc_do_vs_nand_stats(struct nvme_dev *dev, char *format) { int ret; int fmt = -1; @@ -9976,8 +10106,8 @@ static int wdc_do_vs_nand_stats(int fd, char *format) goto out; } - ret = nvme_get_log_simple(fd, WDC_NVME_NAND_STATS_LOG_ID, - WDC_NVME_NAND_STATS_SIZE, (void*)output); + ret = nvme_get_log_simple(dev_fd(dev), WDC_NVME_NAND_STATS_LOG_ID, + WDC_NVME_NAND_STATS_SIZE, (void*)output); if (ret) { fprintf(stderr, "ERROR : WDC : %s : Failed to retreive NAND stats\n", __func__); goto out; @@ -10011,12 +10141,11 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Retrieve NAND statistics."; - - int fd; - int ret = 0; + struct nvme_dev *dev; nvme_root_t r; __u64 capabilities = 0; uint32_t read_device_id = 0, read_vendor_id = 0; + int ret; struct config { char *output_format; @@ -10031,18 +10160,18 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_NAND_STATS) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; } else { - ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); if (ret < 0) { fprintf(stderr, "ERROR : WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret); @@ -10051,10 +10180,11 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, switch (read_device_id) { case WDC_NVME_SN820CL_DEV_ID: - ret = wdc_do_vs_nand_stats_sn810_2(fd, cfg.output_format); + ret = wdc_do_vs_nand_stats_sn810_2(dev, + cfg.output_format); break; default: - ret = wdc_do_vs_nand_stats(fd, cfg.output_format); + ret = wdc_do_vs_nand_stats(dev, cfg.output_format); break; } } @@ -10063,11 +10193,11 @@ static int wdc_vs_nand_stats(int argc, char **argv, struct command *command, fprintf(stderr, "ERROR : WDC : Failure reading NAND statistics, ret = %d\n", ret); nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } -static int wdc_do_vs_pcie_stats(int fd, +static int wdc_do_vs_pcie_stats(struct nvme_dev *dev, struct wdc_vs_pcie_stats *pcieStatsPtr) { int ret; @@ -10079,7 +10209,7 @@ static int wdc_do_vs_pcie_stats(int fd, admin_cmd.addr = (__u64)(uintptr_t)pcieStatsPtr; admin_cmd.data_len = pcie_stats_size; - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, NULL); return ret; } @@ -10088,8 +10218,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Retrieve PCIE statistics."; - - int fd; + struct nvme_dev *dev; int ret = 0; nvme_root_t r; __u64 capabilities = 0; @@ -10111,9 +10240,9 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); @@ -10133,13 +10262,13 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, memset((void *)pcieStatsPtr, 0, pcie_stats_size); - capabilities = wdc_get_drive_capabilities(r, fd); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_PCIE_STATS) == 0) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; } else { - ret = wdc_do_vs_pcie_stats(fd, pcieStatsPtr); + ret = wdc_do_vs_pcie_stats(dev, pcieStatsPtr); if (ret) fprintf(stderr, "ERROR : WDC : Failure reading PCIE statistics, ret = 0x%x\n", ret); else { @@ -10159,7 +10288,7 @@ static int wdc_vs_pcie_stats(int argc, char **argv, struct command *command, out: nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -10169,7 +10298,8 @@ static int wdc_vs_drive_info(int argc, char **argv, const char *desc = "Send a vs-drive-info command."; nvme_root_t r; uint64_t capabilities = 0; - int fd, ret; + struct nvme_dev *dev; + int ret; __le32 result; __u16 size; double rev; @@ -10199,31 +10329,31 @@ static int wdc_vs_drive_info(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; fmt = validate_output_format(cfg.output_format); if (fmt < 0) { fprintf(stderr, "ERROR : WDC %s invalid output format\n", __func__); - close(fd); + dev_close(dev); return fmt; } /* get the id ctrl data used to fill in drive info below */ - ret = nvme_identify_ctrl(fd, &ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (ret) { fprintf(stderr, "ERROR : WDC %s: Identify Controller failed\n", __func__); - close(fd); + dev_close(dev); return ret; } r = nvme_scan(NULL); - wdc_check_device(r, fd); - capabilities = wdc_get_drive_capabilities(r, fd); + wdc_check_device(r, dev); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_INFO) == WDC_DRIVE_CAP_INFO) { - ret = wdc_get_pci_ids(r, &read_device_id, &read_vendor_id); + ret = wdc_get_pci_ids(r, dev, &read_device_id, &read_vendor_id); if (ret < 0) { fprintf(stderr, "ERROR : WDC: %s: failure to get pci ids, ret = %d\n", __func__, ret); @@ -10247,7 +10377,7 @@ static int wdc_vs_drive_info(int argc, char **argv, case WDC_NVME_SN550_DEV_ID: case WDC_NVME_ZN350_DEV_ID: case WDC_NVME_ZN350_DEV_ID_1: - ret = wdc_do_drive_info(fd, &result); + ret = wdc_do_drive_info(dev, &result); if (!ret) { size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16); @@ -10299,7 +10429,8 @@ static int wdc_vs_drive_info(int argc, char **argv, break; case WDC_NVME_SN820CL_DEV_ID: /* Get the Drive HW Rev from the C6 Log page */ - ret = nvme_get_hw_rev_log(fd, &data, 0, NVME_NSID_ALL); + ret = nvme_get_hw_rev_log(dev_fd(dev), &data, 0, + NVME_NSID_ALL); if (ret == 0) { wdc_nvme_hw_rev_log *log_data = (wdc_nvme_hw_rev_log *)data; major_rev = log_data->hw_rev_gdr; @@ -10319,7 +10450,8 @@ static int wdc_vs_drive_info(int argc, char **argv, goto out; } - ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, NVME_NSID_ALL); + ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, + 0, NVME_NSID_ALL); if (ret == 0) { ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data; @@ -10376,7 +10508,7 @@ static int wdc_vs_drive_info(int argc, char **argv, out: nvme_show_status(ret); nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -10386,12 +10518,12 @@ static int wdc_vs_temperature_stats(int argc, char **argv, const char *desc = "Send a vs-temperature-stats command."; struct nvme_smart_log smart_log; struct nvme_id_ctrl id_ctrl; + struct nvme_dev *dev; nvme_root_t r; uint64_t capabilities = 0; __u32 hctm_tmt; - int fd, ret; int temperature, temp_tmt1, temp_tmt2; - int fmt = -1; + int ret, fmt = -1; struct config { char *output_format; @@ -10406,9 +10538,9 @@ static int wdc_vs_temperature_stats(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; r = nvme_scan(NULL); fmt = validate_output_format(cfg.output_format); @@ -10419,8 +10551,8 @@ static int wdc_vs_temperature_stats(int argc, char **argv, } /* check if command is supported */ - wdc_check_device(r, fd); - capabilities = wdc_get_drive_capabilities(r, fd); + wdc_check_device(r, dev); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_TEMP_STATS) != WDC_DRIVE_CAP_TEMP_STATS) { fprintf(stderr, "ERROR : WDC: unsupported device for this command\n"); ret = -1; @@ -10428,10 +10560,11 @@ static int wdc_vs_temperature_stats(int argc, char **argv, } /* get the temperature stats or report errors */ - ret = nvme_identify_ctrl(fd, &id_ctrl); + ret = nvme_identify_ctrl(dev_fd(dev), &id_ctrl); if (ret != 0) goto out; - ret = nvme_get_log_smart(fd, NVME_NSID_ALL, false, &smart_log); + ret = nvme_get_log_smart(dev_fd(dev), NVME_NSID_ALL, false, + &smart_log); if (ret != 0) goto out; @@ -10439,14 +10572,14 @@ static int wdc_vs_temperature_stats(int argc, char **argv, temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]) - 273; /* retrieve HCTM Thermal Management Temperatures */ - nvme_get_features_simple(fd, 0x10, 0, &hctm_tmt); + nvme_get_features_simple(dev_fd(dev), 0x10, 0, &hctm_tmt); temp_tmt1 = ((hctm_tmt >> 16) & 0xffff) ? ((hctm_tmt >> 16) & 0xffff) - 273 : 0; temp_tmt2 = (hctm_tmt & 0xffff) ? (hctm_tmt & 0xffff) - 273 : 0; if (fmt == NORMAL) { /* print the temperature stats */ printf("Temperature Stats for NVME device:%s namespace-id:%x\n", - devicename, WDC_DE_GLOBAL_NSID); + dev->name, WDC_DE_GLOBAL_NSID); printf("Current Composite Temperature : %d °C\n", temperature); printf("WCTEMP : %"PRIu16" °C\n", id_ctrl.wctemp - 273); @@ -10493,7 +10626,7 @@ static int wdc_vs_temperature_stats(int argc, char **argv, out: nvme_show_status(ret); nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -10501,26 +10634,27 @@ static int wdc_capabilities(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Send a capabilities command."; - nvme_root_t r; uint64_t capabilities = 0; - int fd; + struct nvme_dev *dev; + nvme_root_t r; + int ret; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; /* get capabilities */ r = nvme_scan(NULL); - wdc_check_device(r, fd); - capabilities = wdc_get_drive_capabilities(r, fd); + wdc_check_device(r, dev); + capabilities = wdc_get_drive_capabilities(r, dev); /* print command and supported status */ - printf("WDC Plugin Capabilities for NVME device:%s\n", devicename); + printf("WDC Plugin Capabilities for NVME device:%s\n", dev->name); printf("cap-diag : %s\n", capabilities & WDC_DRIVE_CAP_CAP_DIAG ? "Supported" : "Not Supported"); printf("drive-log : %s\n", @@ -10598,7 +10732,7 @@ static int wdc_capabilities(int argc, char **argv, capabilities & WDC_DRIVE_CAP_DEVICE_WAF ? "Supported" : "Not Supported"); printf("capabilities : Supported\n"); nvme_free_tree(r); - close(fd); + dev_close(dev); return 0; } @@ -10606,22 +10740,23 @@ static int wdc_cloud_ssd_plugin_version(int argc, char **argv, struct command *command, struct plugin *plugin) { const char *desc = "Get Cloud SSD Plugin Version command."; - nvme_root_t r; uint64_t capabilities = 0; - int fd; + struct nvme_dev *dev; + nvme_root_t r; + int ret; OPT_ARGS(opts) = { OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; /* get capabilities */ r = nvme_scan(NULL); - wdc_check_device(r, fd); - capabilities = wdc_get_drive_capabilities(r, fd); + wdc_check_device(r, dev); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CLOUD_SSD_VERSION) == WDC_DRIVE_CAP_CLOUD_SSD_VERSION) { /* print command and supported status */ @@ -10631,7 +10766,7 @@ static int wdc_cloud_ssd_plugin_version(int argc, char **argv, } nvme_free_tree(r); - close(fd); + dev_close(dev); return 0; } @@ -10642,7 +10777,8 @@ static int wdc_cloud_boot_SSD_version(int argc, char **argv, const char *namespace_id = "desired namespace id"; nvme_root_t r; uint64_t capabilities = 0; - int fd, ret = -1; + struct nvme_dev *dev; + int ret; int major = 0, minor = 0; __u8 *data = NULL; wdc_nvme_ext_smart_log *ext_smart_log_ptr = NULL; @@ -10660,18 +10796,19 @@ static int wdc_cloud_boot_SSD_version(int argc, char **argv, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; /* get capabilities */ r = nvme_scan(NULL); - wdc_check_device(r, fd); - capabilities = wdc_get_drive_capabilities(r, fd); + wdc_check_device(r, dev); + capabilities = wdc_get_drive_capabilities(r, dev); if ((capabilities & WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION) == WDC_DRIVE_CAP_CLOUD_BOOT_SSD_VERSION) { /* Get the 0xC0 Smart Cloud Attribute V1 log data */ - ret = nvme_get_ext_smart_cloud_log(fd, &data, 0, cfg.namespace_id); + ret = nvme_get_ext_smart_cloud_log(dev_fd(dev), &data, 0, + cfg.namespace_id); ext_smart_log_ptr = (wdc_nvme_ext_smart_log *)data; if (ret == 0) { @@ -10693,7 +10830,7 @@ static int wdc_cloud_boot_SSD_version(int argc, char **argv, } nvme_free_tree(r); - close(fd); + dev_close(dev); return ret; } @@ -10704,9 +10841,9 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, char *file = "Output file pathname."; char *size = "Data retrieval transfer size."; char *log = "Enclosure Log Page ID."; + struct nvme_dev *dev; FILE *output_fd; int xfer_size = 0; - int fd; int len; int err = 0; @@ -10729,12 +10866,11 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) { + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) goto ret; - } - if (!wdc_enc_check_model(fd)) { + if (!wdc_enc_check_model(dev)) { err = -EINVAL; goto closed_fd; } @@ -10770,10 +10906,15 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, if (cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_1 || cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_2 || cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_3 || cfg.log_id == WDC_ENC_NIC_CRASH_DUMP_ID_SLOT_4) { fprintf(stderr, "args - sz:%x logid:%x of:%s\n",xfer_size,cfg.log_id,cfg.file); - err = wdc_enc_get_nic_log(fd, cfg.log_id, xfer_size, WDC_NVME_ENC_NIC_LOG_SIZE, output_fd); + err = wdc_enc_get_nic_log(dev, cfg.log_id, + xfer_size, + WDC_NVME_ENC_NIC_LOG_SIZE, + output_fd); } else { fprintf(stderr, "args - sz:%x logid:%x of:%s\n",xfer_size,cfg.log_id,cfg.file); - err = wdc_enc_submit_move_data(fd, NULL, 0, xfer_size, output_fd, cfg.log_id, 0, 0); + err = wdc_enc_submit_move_data(dev, NULL, 0, + xfer_size, output_fd, + cfg.log_id, 0, 0); } if (err == WDC_RESULT_NOT_AVAILABLE) { @@ -10784,12 +10925,14 @@ static int wdc_enc_get_log(int argc, char **argv, struct command *command, } } closed_fd: - close(fd); + dev_close(dev); ret: return err; } -static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, FILE *out, int log_id, int cdw14, int cdw15) +static int wdc_enc_submit_move_data(struct nvme_dev *dev, char *cmd, int len, + int xfer_size, FILE *out, int log_id, + int cdw14, int cdw15) { struct timespec time; uint32_t response_size, more; @@ -10840,8 +10983,8 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F d); #endif nvme_cmd.result = 0; - err = nvme_submit_admin_passthru(fd, &nvme_cmd, NULL); - if (err == NVME_SC_INTERNAL) { + err = nvme_submit_admin_passthru(dev_fd(dev), &nvme_cmd, NULL); + if (nvme_status_equals(err, NVME_STATUS_TYPE_NVME, NVME_SC_INTERNAL)) { fprintf(stderr, "%s: WARNING : WDC : No log ID:x%x available\n", __func__, log_id); } @@ -10868,7 +11011,8 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F nvme_cmd.cdw14 = cdw14; nvme_cmd.cdw15 = cdw15; nvme_cmd.result = 0; /* returned result !=0 indicates more data available */ - err = nvme_submit_admin_passthru(fd, &nvme_cmd, NULL); + err = nvme_submit_admin_passthru(dev_fd(dev), + &nvme_cmd, NULL); if (err != 0) { more = 0; fprintf(stderr, "%s: ERROR : WDC : NVMe Rcv Mgmt ", __func__); @@ -10890,7 +11034,7 @@ static int wdc_enc_submit_move_data(int fd, char *cmd, int len, int xfer_size, F return err; } -static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out) +static int wdc_enc_get_nic_log(struct nvme_dev *dev, __u8 log_id, __u32 xfer_size, __u32 data_len, FILE *out) { __u8 *dump_data; __u32 curr_data_offset, curr_data_len; @@ -10925,7 +11069,8 @@ static int wdc_enc_get_nic_log(int fd, __u8 log_id, __u32 xfer_size, __u32 data_ #ifdef WDC_NVME_CLI_DEBUG fprintf(stderr, "nsid 0x%08x addr 0x%08llx, data_len 0x%08x, cdw10 0x%08x, cdw11 0x%08x, cdw12 0x%08x, cdw13 0x%08x, cdw14 0x%08x \n", admin_cmd.nsid, admin_cmd.addr, admin_cmd.data_len, admin_cmd.cdw10, admin_cmd.cdw11, admin_cmd.cdw12, admin_cmd.cdw13, admin_cmd.cdw14); #endif - ret = nvme_submit_admin_passthru(fd, &admin_cmd, NULL); + ret = nvme_submit_admin_passthru(dev_fd(dev), &admin_cmd, + NULL); if (ret != 0) { nvme_show_status(ret); fprintf(stderr, "%s: ERROR : WDC : Get chunk %d, size = 0x%x, offset = 0x%x, addr = 0x%lx\n", diff --git a/plugins/wdc/wdc-nvme.h b/plugins/wdc/wdc-nvme.h index c7b7f4c..242cf9a 100644 --- a/plugins/wdc/wdc-nvme.h +++ b/plugins/wdc/wdc-nvme.h @@ -5,7 +5,7 @@ #if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ) #define WDC_NVME -#define WDC_PLUGIN_VERSION "2.0.3" +#define WDC_PLUGIN_VERSION "2.1.2" #include "cmd.h" PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION), diff --git a/plugins/ymtc/ymtc-nvme.c b/plugins/ymtc/ymtc-nvme.c index cfbf6a6..d04481c 100644 --- a/plugins/ymtc/ymtc-nvme.c +++ b/plugins/ymtc/ymtc-nvme.c @@ -21,8 +21,8 @@ static void get_ymtc_smart_info(struct nvme_ymtc_smart_log *smart, int index, u8 memcpy(raw_val, smart->itemArr[index].rawVal, RAW_SIZE); } -static int show_ymtc_smart_log(int fd, __u32 nsid, const char *devname, - struct nvme_ymtc_smart_log *smart) +static int show_ymtc_smart_log(struct nvme_dev *dev, __u32 nsid, + struct nvme_ymtc_smart_log *smart) { struct nvme_id_ctrl ctrl; char fw_ver[10]; @@ -40,7 +40,7 @@ static int show_ymtc_smart_log(int fd, __u32 nsid, const char *devname, free(nm); return -1; } - err = nvme_identify_ctrl(fd, &ctrl); + err = nvme_identify_ctrl(dev_fd(dev), &ctrl); if (err) { free(nm); free(raw); @@ -52,7 +52,8 @@ static int show_ymtc_smart_log(int fd, __u32 nsid, const char *devname, ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]); /* Table Title */ - printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); + printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", + dev->name, nsid); /* Clumn Name*/ printf("key normalized raw\n"); /* 00 SI_VD_PROGRAM_FAIL */ @@ -119,15 +120,16 @@ static int show_ymtc_smart_log(int fd, __u32 nsid, const char *devname, static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) { struct nvme_ymtc_smart_log smart_log; - int err, fd; char *desc = "Get Ymtc vendor specific additional smart log (optionally, "\ "for the specified namespace), and show it."; const char *namespace = "(optional) desired namespace"; const char *raw = "dump output in binary format"; + struct nvme_dev *dev; struct config { __u32 namespace_id; bool raw_binary; }; + int err; struct config cfg = { .namespace_id = NVME_NSID_ALL, @@ -139,21 +141,21 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) - return fd; + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) + return err; - err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id, + err = nvme_get_nsid_log(dev_fd(dev), false, 0xca, cfg.namespace_id, sizeof(smart_log), &smart_log); if (!err) { if (!cfg.raw_binary) - err = show_ymtc_smart_log(fd, cfg.namespace_id, devicename, &smart_log); + err = show_ymtc_smart_log(dev, cfg.namespace_id, &smart_log); else d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } if (err > 0) nvme_show_status(err); - close(fd); + dev_close(dev); return err; } diff --git a/plugins/zns/zns.c b/plugins/zns/zns.c index 0b96346..f8809ba 100644 --- a/plugins/zns/zns.c +++ b/plugins/zns/zns.c @@ -120,7 +120,8 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl enum nvme_print_flags flags; struct nvme_zns_id_ctrl ctrl; - int fd, err = -1; + struct nvme_dev *dev; + int err = -1; struct config { char *output_format; @@ -135,15 +136,15 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; err = flags = validate_output_format(cfg.output_format); if (flags < 0) goto close_fd; - err = nvme_zns_identify_ctrl(fd, &ctrl); + err = nvme_zns_identify_ctrl(dev_fd(dev), &ctrl); if (!err) nvme_show_zns_id_ctrl(&ctrl, flags); else if (err > 0) @@ -151,7 +152,7 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl else perror("zns identify controller"); close_fd: - close(fd); + dev_close(dev); return err; } @@ -166,7 +167,8 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug enum nvme_print_flags flags; struct nvme_zns_id_ns ns; struct nvme_id_ns id_ns; - int fd, err = -1; + struct nvme_dev *dev; + int err = -1; struct config { char *output_format; @@ -187,8 +189,8 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; flags = validate_output_format(cfg.output_format); @@ -200,20 +202,20 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug flags |= VERBOSE; if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; } } - err = nvme_identify_ns(fd, cfg.namespace_id, &id_ns); + err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id, &id_ns); if (err) { nvme_show_status(err); goto close_fd; } - err = nvme_zns_identify_ns(fd, cfg.namespace_id, &ns); + err = nvme_zns_identify_ns(dev_fd(dev), cfg.namespace_id, &ns); if (!err) nvme_show_zns_id_ns(&ns, &id_ns, flags); else if (err > 0) @@ -221,7 +223,7 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug else perror("zns identify namespace"); close_fd: - close(fd); + dev_close(dev); return err; } @@ -231,8 +233,8 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug const char *zslba = "starting LBA of the zone for this command"; const char *select_all = "send command to all zones"; const char *timeout = "timeout value, in milliseconds"; - - int err, fd, zcapc = 0; + struct nvme_dev *dev; + int err, zcapc = 0; char *command; __u32 result; @@ -253,16 +255,16 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug OPT_END() }; - err = fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) goto ret; err = asprintf(&command, "%s-%s", plugin->name, cmd->name); if (err < 0) - goto close_fd; + goto close_dev; if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto free; @@ -271,7 +273,7 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug struct nvme_zns_mgmt_send_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .nsid = cfg.namespace_id, .slba = cfg.zslba, .zsa = zsa, @@ -297,8 +299,8 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug perror(desc); free: free(command); -close_fd: - close(fd); +close_dev: + dev_close(dev); ret: return err; } @@ -344,7 +346,8 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu const char *data = "optional file for data (default stdin)"; const char *timeout = "timeout value, in milliseconds"; - int fd, ffd = STDIN_FILENO, err = -1; + int ffd = STDIN_FILENO, err = -1; + struct nvme_dev *dev; void *buf = NULL; struct config { @@ -372,41 +375,42 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_fd; + goto close_dev; } } if (!cfg.zsa) { fprintf(stderr, "zone send action must be specified\n"); err = -EINVAL; - goto close_fd; + goto close_dev; } if (cfg.zsa == NVME_ZNS_ZSA_SET_DESC_EXT) { if(!cfg.data_len) { - int data_len = get_zdes_bytes(fd, cfg.namespace_id); + int data_len = get_zdes_bytes(dev_fd(dev), + cfg.namespace_id); if (data_len == 0) { fprintf(stderr, "Zone Descriptor Extensions are not supported\n"); - goto close_fd; + goto close_dev; } else if (data_len < 0) { err = data_len; - goto close_fd; + goto close_dev; } cfg.data_len = data_len; } if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { fprintf(stderr, "can not allocate feature payload\n"); - goto close_fd; + goto close_dev; } memset(buf, 0, cfg.data_len); @@ -428,13 +432,13 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu fprintf(stderr, "data, data_len only valid with set extended descriptor\n"); err = -EINVAL; - goto close_fd; + goto close_dev; } } struct nvme_zns_mgmt_send_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .nsid = cfg.namespace_id, .slba = cfg.zslba, .zsa = cfg.zsa, @@ -461,8 +465,8 @@ close_ffd: close(ffd); free: free(buf); -close_fd: - close(fd); +close_dev: + dev_close(dev); return err; } @@ -487,8 +491,8 @@ static int open_zone(int argc, char **argv, struct command *cmd, struct plugin * const char *zrwaa = "Allocate Zone Random Write Area to zone"; const char *select_all = "send command to all zones"; const char *timeout = "timeout value, in milliseconds"; - - int err, fd; + struct nvme_dev *dev; + int err; struct config { __u64 zslba; @@ -510,21 +514,21 @@ static int open_zone(int argc, char **argv, struct command *cmd, struct plugin * OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_fd; + goto close_dev; } } struct nvme_zns_mgmt_send_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .nsid = cfg.namespace_id, .slba = cfg.zslba, .zsa = NVME_ZNS_ZSA_OPEN, @@ -541,8 +545,8 @@ static int open_zone(int argc, char **argv, struct command *cmd, struct plugin * (uint64_t)cfg.zslba, cfg.namespace_id); else nvme_show_status(err); -close_fd: - close(fd); +close_dev: + dev_close(dev); return err; } @@ -568,7 +572,8 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug const char *data = "optional file for zone extention data (default stdin)"; const char *timeout = "timeout value, in milliseconds"; - int fd, ffd = STDIN_FILENO, err; + int ffd = STDIN_FILENO, err; + struct nvme_dev *dev; void *buf = NULL; int data_len; @@ -591,33 +596,33 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_fd; + goto close_dev; } } - data_len = get_zdes_bytes(fd, cfg.namespace_id); + data_len = get_zdes_bytes(dev_fd(dev), cfg.namespace_id); if (!data_len || data_len < 0) { fprintf(stderr, "zone format does not provide descriptor extention\n"); errno = EINVAL; err = -1; - goto close_fd; + goto close_dev; } buf = calloc(1, data_len); if (!buf) { perror("could not alloc memory for zone desc"); err = -ENOMEM; - goto close_fd; + goto close_dev; } if (cfg.file) { @@ -637,7 +642,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug struct nvme_zns_mgmt_send_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .nsid = cfg.namespace_id, .slba = cfg.zslba, .zsa = NVME_ZNS_ZSA_SET_DESC_EXT, @@ -661,8 +666,8 @@ close_ffd: close(ffd); free: free(buf); -close_fd: - close(fd); +close_dev: + dev_close(dev); return err; } @@ -672,8 +677,8 @@ static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct pl const char *desc = "Flush Explicit ZRWA Range"; const char *slba = "LBA to flush up to"; const char *timeout = "timeout value, in milliseconds"; - - int err, fd; + struct nvme_dev *dev; + int err; struct config { __u64 lba; @@ -690,21 +695,21 @@ static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct pl OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_fd; + goto close_dev; } } struct nvme_zns_mgmt_send_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .nsid = cfg.namespace_id, .slba = cfg.lba, .zsa = NVME_ZNS_ZSA_ZRWA_FLUSH, @@ -721,8 +726,8 @@ static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct pl (uint64_t)cfg.lba, cfg.namespace_id); else nvme_show_status(err); -close_fd: - close(fd); +close_dev: + dev_close(dev); return err; } @@ -736,8 +741,9 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu const char *data_len = "length of data in bytes"; enum nvme_print_flags flags; - int fd, err = -1; + struct nvme_dev *dev; void *data = NULL; + int err = -1; struct config { char *output_format; @@ -764,39 +770,39 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; flags = validate_output_format(cfg.output_format); if (flags < 0) - goto close_fd; + goto close_dev; if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_fd; + goto close_dev; } } if (cfg.zra == NVME_ZNS_ZRA_REPORT_ZONES && !cfg.data_len) { fprintf(stderr, "error: data len is needed for NVME_ZRA_ZONE_REPORT\n"); err = -EINVAL; - goto close_fd; + goto close_dev; } if (cfg.data_len) { data = calloc(1, cfg.data_len); if (!data) { perror("could not alloc memory for zone mgmt receive data"); err = -ENOMEM; - goto close_fd; + goto close_dev; } } struct nvme_zns_mgmt_recv_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .nsid = cfg.namespace_id, .slba = cfg.zslba, .zra = cfg.zra, @@ -817,8 +823,8 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu perror("zns zone-mgmt-recv"); free(data); -close_fd: - close(fd); +close_dev: + dev_close(dev); return err; } @@ -833,11 +839,11 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi const char *verbose = "show report zones verbosity"; enum nvme_print_flags flags; - int fd, zdes = 0, err = -1; + int zdes = 0, err = -1; + struct nvme_dev *dev; __u32 report_size; - void *report; bool huge = false; - struct nvme_zone_report *buff; + struct nvme_zone_report *report, *buff; unsigned int nr_zones_chunks = 1024, /* 1024 entries * 64 bytes per entry = 64k byte transfer */ nr_zones_retrieved = 0, @@ -879,39 +885,39 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; flags = validate_output_format(cfg.output_format); if (flags < 0) - goto close_fd; + goto close_dev; if (cfg.verbose) flags |= VERBOSE; if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_fd; + goto close_dev; } } if (cfg.extended) { - zdes = get_zdes_bytes(fd, cfg.namespace_id); + zdes = get_zdes_bytes(dev_fd(dev), cfg.namespace_id); if (zdes < 0) { err = zdes; - goto close_fd; + goto close_dev; } } - err = nvme_identify_ns(fd, cfg.namespace_id, &id_ns); + err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id, &id_ns); if (err) { nvme_show_status(err); - goto close_fd; + goto close_dev; } - err = nvme_zns_identify_ns(fd, cfg.namespace_id, &id_zns); + err = nvme_zns_identify_ns(dev_fd(dev), cfg.namespace_id, &id_zns); if (!err) { /* get zsze field from zns id ns data - needed for offset calculation */ nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf); @@ -919,17 +925,17 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi } else { nvme_show_status(err); - goto close_fd; + goto close_dev; } log_len = sizeof(struct nvme_zone_report); buff = calloc(1, log_len); if (!buff) { err = -ENOMEM; - goto close_fd; + goto close_dev; } - err = nvme_zns_report_zones(fd, cfg.namespace_id, 0, + err = nvme_zns_report_zones(dev_fd(dev), cfg.namespace_id, 0, cfg.state, false, false, log_len, buff, NVME_DEFAULT_IOCTL_TIMEOUT, NULL); @@ -959,7 +965,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi if (!report) { perror("alloc"); err = -ENOMEM; - goto close_fd; + goto close_dev; } offset = cfg.zslba; @@ -977,7 +983,8 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi log_len = sizeof(struct nvme_zone_report) + ((sizeof(struct nvme_zns_desc) * nr_zones_chunks) + (nr_zones_chunks * zdes)); } - err = nvme_zns_report_zones(fd, cfg.namespace_id, offset, + err = nvme_zns_report_zones(dev_fd(dev), cfg.namespace_id, + offset, cfg.state, cfg.extended, cfg.partial, log_len, report, NVME_DEFAULT_IOCTL_TIMEOUT, NULL); @@ -991,7 +998,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi zdes, log_len, flags, zone_list); nr_zones_retrieved += nr_zones_chunks; - offset = (nr_zones_retrieved * zsze); + offset = le64_to_cpu(report->entries[nr_zones_chunks-1].zslba) + zsze; } if (flags & JSON) @@ -1001,8 +1008,8 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi free_buff: free(buff); -close_fd: - close(fd); +close_dev: + dev_close(dev); return err; } @@ -1025,10 +1032,11 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin const char *data_size = "size of data in bytes"; const char *latency = "output latency statistics"; - int err = -1, fd, dfd = STDIN_FILENO, mfd = STDIN_FILENO; + int err = -1, dfd = STDIN_FILENO, mfd = STDIN_FILENO; unsigned int lba_size, meta_size; void *buf = NULL, *mbuf = NULL; __u16 nblocks, control = 0; + struct nvme_dev *dev; __u64 result; __u8 lba_index; struct timeval start_time, end_time; @@ -1072,28 +1080,28 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; if (!cfg.data_size) { fprintf(stderr, "Append size not provided\n"); errno = EINVAL; - goto close_fd; + goto close_dev; } if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); - goto close_fd; + goto close_dev; } } - err = nvme_identify_ns(fd, cfg.namespace_id, &ns); + err = nvme_identify_ns(dev_fd(dev), cfg.namespace_id, &ns); if (err) { nvme_show_status(err); - goto close_fd; + goto close_dev; } nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index); @@ -1103,7 +1111,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin "Data size:%#"PRIx64" not aligned to lba size:%#x\n", (uint64_t)cfg.data_size, lba_size); errno = EINVAL; - goto close_fd; + goto close_dev; } meta_size = ns.lbaf[lba_index].ms; @@ -1113,20 +1121,20 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin "Metadata size:%#"PRIx64" not aligned to metadata size:%#x\n", (uint64_t)cfg.metadata_size, meta_size); errno = EINVAL; - goto close_fd; + goto close_dev; } if (cfg.prinfo > 0xf) { fprintf(stderr, "Invalid value for prinfo:%#x\n", cfg.prinfo); errno = EINVAL; - goto close_fd; + goto close_dev; } if (cfg.data) { dfd = open(cfg.data, O_RDONLY); if (dfd < 0) { perror(cfg.data); - goto close_fd; + goto close_dev; } } @@ -1179,7 +1187,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin struct nvme_zns_append_args args = { .args_size = sizeof(args), - .fd = fd, + .fd = dev_fd(dev), .nsid = cfg.namespace_id, .zslba = cfg.zslba, .nlb = nblocks, @@ -1219,8 +1227,8 @@ free_data: close_dfd: if (cfg.data) close(dfd); -close_fd: - close(fd); +close_dev: + dev_close(dev); return err; } @@ -1231,7 +1239,8 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct struct nvme_zns_changed_zone_log log; enum nvme_print_flags flags; - int fd, err = -1; + struct nvme_dev *dev; + int err = -1; struct config { char *output_format; @@ -1250,8 +1259,8 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct OPT_END() }; - fd = parse_and_open(argc, argv, desc, opts); - if (fd < 0) + err = parse_and_open(&dev, argc, argv, desc, opts); + if (err) return errno; flags = validate_output_format(cfg.output_format); @@ -1259,14 +1268,15 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct goto close_fd; if (!cfg.namespace_id) { - err = nvme_get_nsid(fd, &cfg.namespace_id); + err = nvme_get_nsid(dev_fd(dev), &cfg.namespace_id); if (err < 0) { perror("get-namespace-id"); goto close_fd; } } - err = nvme_get_log_zns_changed_zones(fd, cfg.namespace_id, cfg.rae, &log); + err = nvme_get_log_zns_changed_zones(dev_fd(dev), cfg.namespace_id, + cfg.rae, &log); if (!err) nvme_show_zns_changed(&log, flags); else if (err > 0) @@ -1275,6 +1285,6 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct perror("zns changed-zone-list"); close_fd: - close(fd); + dev_close(dev); return err; } |