Merging upstream version 2.2.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
c6eb8bc90e
commit
965e6654c3
446 changed files with 8369 additions and 4059 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
__u16 SuperCapCurrentTemperature;
|
||||
__u16 SuperCapMaximumTemperature;
|
||||
__u8 SuperCapStatus;
|
||||
__u8 Reserved5to7[3];
|
||||
U128 DataUnitsReadToDramNamespace;
|
||||
U128 DataUnitsWrittenToDramNamespace;
|
||||
__u64 DramCorrectableErrorCount;
|
||||
__u64 DramUncorrectableErrorCount;
|
||||
} vendor_log_page_CF_Attr;
|
||||
|
||||
typedef struct _vendor_log_page_CF
|
||||
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 */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
183
plugins/solidigm/solidigm-telemetry.c
Normal file
183
plugins/solidigm/solidigm-telemetry.c
Normal file
|
@ -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;
|
||||
}
|
8
plugins/solidigm/solidigm-telemetry.h
Normal file
8
plugins/solidigm/solidigm-telemetry.h
Normal file
|
@ -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);
|
194
plugins/solidigm/solidigm-telemetry/cod.c
Normal file
194
plugins/solidigm/solidigm-telemetry/cod.c
Normal file
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
9
plugins/solidigm/solidigm-telemetry/cod.h
Normal file
9
plugins/solidigm/solidigm-telemetry/cod.h
Normal file
|
@ -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);
|
44
plugins/solidigm/solidigm-telemetry/config.c
Normal file
44
plugins/solidigm/solidigm-telemetry/config.c
Normal file
|
@ -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;
|
||||
}
|
10
plugins/solidigm/solidigm-telemetry/config.h
Normal file
10
plugins/solidigm/solidigm-telemetry/config.h
Normal file
|
@ -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);
|
424
plugins/solidigm/solidigm-telemetry/data-area.c
Normal file
424
plugins/solidigm/solidigm-telemetry/data-area.c
Normal file
|
@ -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;
|
||||
}
|
11
plugins/solidigm/solidigm-telemetry/data-area.h
Normal file
11
plugins/solidigm/solidigm-telemetry/data-area.h
Normal file
|
@ -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);
|
199
plugins/solidigm/solidigm-telemetry/header.c
Normal file
199
plugins/solidigm/solidigm-telemetry/header.c
Normal file
|
@ -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;
|
||||
}
|
9
plugins/solidigm/solidigm-telemetry/header.h
Normal file
9
plugins/solidigm/solidigm-telemetry/header.h
Normal file
|
@ -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);
|
6
plugins/solidigm/solidigm-telemetry/meson.build
Normal file
6
plugins/solidigm/solidigm-telemetry/meson.build
Normal file
|
@ -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',
|
||||
]
|
31
plugins/solidigm/solidigm-telemetry/telemetry-log.h
Normal file
31
plugins/solidigm/solidigm-telemetry/telemetry-log.h
Normal file
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue