1
0
Fork 0

Merging upstream version 2.2.1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-16 12:18:36 +01:00
parent c6eb8bc90e
commit 965e6654c3
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
446 changed files with 8369 additions and 4059 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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;
}

View file

@ -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, &param1, &param2)) {
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;
}

View file

@ -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);

View file

@ -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) {

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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)
)
);

View file

@ -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,

View file

@ -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')

View file

@ -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;
}

View file

@ -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(&lt);
if (err){
close(lt.fd);
dev_close(dev);
return err;
}
err = latency_tracker_get_log(&lt);
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;
}

View file

@ -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);
}

View file

@ -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)
)
);

View file

@ -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;
}

View 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;
}

View 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);

View 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);
}
}
}

View 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);

View 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;
}

View 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);

View 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;
}

View 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);

View 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;
}

View 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);

View 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',
]

View 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 */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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),

View file

@ -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;
}

View file

@ -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;
}