1
0
Fork 0

Merging upstream version 2.1~rc0 (Closes: #1015722).

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-16 12:16:19 +01:00
parent 9489161ac8
commit 316e846c86
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
504 changed files with 6751 additions and 2957 deletions

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/amzn/amzn-nvme

54
plugins/dell/dell-nvme.c Normal file
View file

@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright © 2022 Dell Inc. or its subsidiaries. All Rights Reserved.
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include "common.h"
#include "nvme.h"
#include "libnvme.h"
#include "plugin.h"
#define CREATE_CMD
#include "dell-nvme.h"
#define ARRAY_NAME_LEN 80
struct nvme_vu_id_ctrl_field {
__u16 dell_mjr;
__u16 dell_mnr;
__u16 dell_ter;
__u8 reserved0[1018];
};
static void dell_id_ctrl(__u8 *vs, struct json_object *root)
{
struct nvme_vu_id_ctrl_field *id = (struct nvme_vu_id_ctrl_field *)vs;
char array_ver[16] = { 0 };
char array_name[ARRAY_NAME_LEN + 1] = {0};
snprintf(array_ver, sizeof(array_ver), "0x%04x%04x%04x",
le16_to_cpu(id->dell_mjr),
le16_to_cpu(id->dell_mnr),
le16_to_cpu(id->dell_ter));
memcpy(array_name, vs + sizeof(array_ver), ARRAY_NAME_LEN);
if (root) {
json_object_add_value_string(root, "array_name", strlen(array_name) > 1 ? array_name : "NULL");
json_object_add_value_string(root, "array_ver", array_ver);
return;
}
printf("array_name : %s\n", strlen(array_name) > 1 ? array_name : "NULL");
printf("array_ver : %s\n", array_ver);
}
static int id_ctrl(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
return __id_ctrl(argc, argv, cmd, plugin, dell_id_ctrl);
}

18
plugins/dell/dell-nvme.h Normal file
View file

@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/dell/dell-nvme
#if !defined(DELL_NVME) || defined(CMD_HEADER_MULTI_READ)
#define DELL_NVME
#include "cmd.h"
PLUGIN(NAME("dell", "DELL vendor specific extensions", NVME_VERSION),
COMMAND_LIST(
ENTRY("id-ctrl", "Send NVMe Identify Controller", id_ctrl)
)
);
#endif
#include "define_cmd.h"

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -186,7 +187,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin
printf("fw_loader_version : %.*s\n", 8, log.fw_loader_version);
printf("uefi_driver_version : %.*s\n", 8, log.uefi_driver_version);
if (log.pcie_volt_status <= sizeof(volt_status) / sizeof(const char *)){
if (log.pcie_volt_status < sizeof(volt_status) / sizeof(const char *)){
printf("pcie_volt_status : %s\n", volt_status[log.pcie_volt_status]);
}
else{
@ -204,6 +205,7 @@ exit:
if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/dera/dera-nvme

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017-2019 Huawei Corporation or its affiliates.
*
@ -92,7 +93,8 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha
if (err < 0)
return err;
strcpy(item->node, node);
strncpy(item->node, node, sizeof(item->node));
item->node[sizeof(item->node) - 1] = '\0';
item->block = S_ISBLK(nvme_stat_info.st_mode);
if (item->ns.vs[0] == 0) {
@ -204,20 +206,20 @@ static void huawei_print_list_head(struct huawei_list_element_len element_len)
element_len.usage, dash, element_len.array_name, dash);
}
static void huawei_print_list_item(struct huawei_list_item list_item,
struct huawei_list_element_len element_len)
static void huawei_print_list_item(struct huawei_list_item *list_item,
struct huawei_list_element_len element_len)
{
__u8 lba_index;
nvme_id_ns_flbas_to_lbaf_inuse(list_item.ns.flbas, &lba_index);
long long int lba = 1 << list_item.ns.lbaf[lba_index].ds;
double nsze = le64_to_cpu(list_item.ns.nsze) * lba;
double nuse = le64_to_cpu(list_item.ns.nuse) * lba;
nvme_id_ns_flbas_to_lbaf_inuse(list_item->ns.flbas, &lba_index);
unsigned long long int lba = 1ULL << list_item->ns.lbaf[lba_index].ds;
double nsze = le64_to_cpu(list_item->ns.nsze) * lba;
double nuse = le64_to_cpu(list_item->ns.nuse) * lba;
const char *s_suffix = suffix_si_get(&nsze);
const char *u_suffix = suffix_si_get(&nuse);
char usage[128];
char nguid_buf[2 * sizeof(list_item.ns.nguid) + 1];
char nguid_buf[2 * sizeof(list_item->ns.nguid) + 1];
char *nguid = nguid_buf;
int i;
@ -225,16 +227,17 @@ static void huawei_print_list_item(struct huawei_list_item list_item,
nsze, s_suffix);
memset(nguid, 0, sizeof(nguid_buf));
for (i = 0; i < sizeof(list_item.ns.nguid); i++)
nguid += sprintf(nguid, "%02x", list_item.ns.nguid[i]);
for (i = 0; i < sizeof(list_item->ns.nguid); i++)
nguid += sprintf(nguid, "%02x", list_item->ns.nguid[i]);
printf("%-*.*s %-*.*s %-*.*s %-*d %-*.*s %-*.*s\n",
element_len.node, element_len.node, list_item.node,
element_len.ns_name, element_len.ns_name, list_item.ns_name,
element_len.node, element_len.node, list_item->node,
element_len.ns_name, element_len.ns_name, list_item->ns_name,
element_len.nguid, element_len.nguid, nguid_buf,
element_len.ns_id, list_item.nsid,
element_len.ns_id, list_item->nsid,
element_len.usage, element_len.usage, usage,
element_len.array_name, element_len.array_name, list_item.array_name);
element_len.array_name, element_len.array_name,
list_item->array_name);
}
@ -287,7 +290,7 @@ static void huawei_print_list_items(struct huawei_list_item *list_items, unsigne
huawei_print_list_head(element_len);
for (i = 0 ; i < len ; i++)
huawei_print_list_item(list_items[i], element_len);
huawei_print_list_item(&list_items[i], element_len);
}
static int huawei_list(int argc, char **argv, struct command *command,
@ -296,7 +299,7 @@ static int huawei_list(int argc, char **argv, struct command *command,
char path[264];
struct dirent **devices;
struct huawei_list_item *list_items;
unsigned int i, n, fd, ret;
unsigned int i, n, ret;
unsigned int huawei_num = 0;
int fmt;
const char *desc = "Retrieve basic information for the given huawei device";
@ -313,7 +316,10 @@ static int huawei_list(int argc, char **argv, struct command *command,
OPT_END()
};
argconfig_parse(argc, argv, desc, opts);
ret = argconfig_parse(argc, argv, desc, opts);
if (ret)
return ret;
fmt = validate_output_format(cfg.output_format);
if (fmt != JSON && fmt != NORMAL)
return -EINVAL;
@ -325,18 +331,29 @@ static int huawei_list(int argc, char **argv, struct command *command,
list_items = calloc(n, sizeof(*list_items));
if (!list_items) {
fprintf(stderr, "can not allocate controller list payload\n");
return ENOMEM;
ret = ENOMEM;
goto out_free_devices;
}
for (i = 0; i < n; i++) {
int fd;
snprintf(path, sizeof(path), "/dev/%s", devices[i]->d_name);
fd = open(path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Cannot open device %s: %s\n",
path, strerror(errno));
continue;
}
ret = huawei_get_nvme_info(fd, &list_items[huawei_num], path);
if (ret)
return ret;
if (ret) {
close(fd);
goto out_free_list_items;
}
if (list_items[huawei_num].huawei_device == true) {
huawei_num++;
}
close(fd);
}
if (huawei_num > 0){
@ -345,13 +362,14 @@ static int huawei_list(int argc, char **argv, struct command *command,
else
huawei_print_list_items(list_items, huawei_num);
}
out_free_list_items:
free(list_items);
out_free_devices:
for (i = 0; i < n; i++)
free(devices[i]);
free(devices);
free(list_items);
return 0;
return ret;
}
static void huawei_do_id_ctrl(__u8 *vs, struct json_object *root)

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/huawei/huawei-nvme

View file

@ -0,0 +1,402 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include "common.h"
#include "nvme.h"
#include "libnvme.h"
#include "nvme-print.h"
#include "typedef.h"
#define CREATE_CMD
#include "innogrit-nvme.h"
static int innogrit_smart_log_additional(int argc, char **argv,
struct command *command,
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 config {
__u32 namespace_id;
};
struct config cfg = {
.namespace_id = NVME_NSID_ALL,
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
nvme_get_log_smart(fd, cfg.namespace_id, true, &smart_log);
nvme_show_smart_log(&smart_log, cfg.namespace_id, devicename, 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);
printf("DW1 Slc Total Ec Cnt : %u\n", pvsc_smart->slc_total_ec_cnt);
printf("DW2 Slc Max Ec Cnt : %u\n", pvsc_smart->slc_max_ec_cnt);
printf("DW3 Slc Min Ec Cnt : %u\n", pvsc_smart->slc_min_ec_cnt);
printf("DW4 Slc Avg Ec Cnt : %u\n", pvsc_smart->slc_avg_ec_cnt);
printf("DW5 Total Ec Cnt : %u\n", pvsc_smart->total_ec_cnt);
printf("DW6 Max Ec Cnt : %u\n", pvsc_smart->max_ec_cnt);
printf("DW7 Min Ec Cnt : %u\n", pvsc_smart->min_ec_cnt);
printf("DW8 Avg Ec Cnt : %u\n", pvsc_smart->avg_ec_cnt);
printf("DW9 Mrd Rr Good Cnt : %u\n", pvsc_smart->mrd_rr_good_cnt);
printf("DW10 Ard Rr Good Cnt : %u\n", pvsc_smart->ard_rr_good_cnt);
printf("DW11 Preset Cnt : %u\n", pvsc_smart->preset_cnt);
printf("DW12 Nvme Reset Cnt : %u\n", pvsc_smart->nvme_reset_cnt);
printf("DW13 Low Pwr Cnt : %u\n", pvsc_smart->low_pwr_cnt);
printf("DW14 Wa : %u\n", pvsc_smart->wa);
printf("DW15 Ps3 Entry Cnt : %u\n", pvsc_smart->ps3_entry_cnt);
printf("DW16[0] highest_temp[0] : %u\n", pvsc_smart->highest_temp[0]);
printf("DW16[1] highest_temp[1] : %u\n", pvsc_smart->highest_temp[1]);
printf("DW16[2] highest_temp[2] : %u\n", pvsc_smart->highest_temp[2]);
printf("DW16[3] highest_temp[3] : %u\n", pvsc_smart->highest_temp[3]);
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]);
iindex++;
}
return 0;
}
static int sort_eventlog_fn(const void *a, const void *b)
{
const struct eventlog_addindex *l = a;
const struct eventlog_addindex *r = b;
int rc;
if (l->ms > r->ms) {
rc = 1;
} else if (l->ms < r->ms) {
rc = -1;
} else {
if (l->iindex < r->iindex)
rc = -1;
else
rc = 1;
}
return rc;
}
static void sort_eventlog(struct eventlog *data16ksrc, unsigned int icount)
{
struct eventlog_addindex peventlogadd[512];
unsigned int i;
for (i = 0; i < icount; i++) {
memcpy(&peventlogadd[i], &data16ksrc[i], sizeof(struct eventlog));
peventlogadd[i].iindex = i;
}
qsort(peventlogadd, icount, sizeof(struct eventlog_addindex), sort_eventlog_fn);
for (i = 0; i < icount; i++)
memcpy(&data16ksrc[i], &peventlogadd[i], sizeof(struct eventlog));
}
static unsigned char setfilecontent(char *filenamea, unsigned char *buffer,
unsigned int buffersize)
{
FILE *fp = NULL;
int rc;
if (buffersize == 0)
return true;
fp = fopen(filenamea, "a+");
rc = fwrite(buffer, 1, buffersize, fp);
fclose(fp);
if (rc != buffersize)
return false;
return true;
}
static int nvme_vucmd(int fd, unsigned char opcode, unsigned int cdw12,
unsigned int cdw13, unsigned int cdw14,
unsigned int cdw15, char *data, int data_len)
{
struct nvme_passthru_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = opcode;
cmd.cdw12 = cdw12;
cmd.cdw13 = cdw13;
cmd.cdw14 = cdw14;
cmd.cdw15 = cdw15;
cmd.nsid = 0;
cmd.addr = (__u64)(__u64)(uintptr_t)data;
cmd.data_len = data_len;
return nvme_submit_admin_passthru(fd, &cmd, NULL);
}
static int innogrit_vsc_geteventlog(int argc, char **argv,
struct command *command,
struct plugin *plugin)
{
time_t timep;
struct tm *logtime;
int icount, ioffset16k, iblock;
char currentdir[128], filename[512];
unsigned char data[4096], data16k[SIZE_16K], zerob[32];
unsigned int *pcheckdata;
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 config {
__u32 clean_flg;
};
struct config cfg = {
.clean_flg = 0,
};
OPT_ARGS(opts) = {
OPT_UINT("clean_flg", 'c', &cfg.clean_flg, clean_opt),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
if (getcwd(currentdir, 128) == NULL)
return -1;
time(&timep);
logtime = localtime(&timep);
sprintf(filename, "%s/eventlog_%02d%02d-%02d%02d%02d.elog", currentdir, logtime->tm_mon+1,
logtime->tm_mday, logtime->tm_hour, logtime->tm_min, logtime->tm_sec);
iblock = 0;
ioffset16k = 0;
memset(data16k, 0, SIZE_16K);
memset(zerob, 0, 32);
icount = 0;
while (bget_nextlog) {
if (icount % 100 == 0) {
printf("\rWait for Dump EventLog " XCLEAN_LINE);
fflush(stdout);
icount = 0;
} else if (icount % 5 == 0) {
printf(".");
fflush(stdout);
}
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);
if (ret == -1)
return ret;
pcheckdata = (unsigned int *)&data[4096 - 32];
icheck_stopvalue = pcheckdata[1];
if (icheck_stopvalue == 0xFFFFFFFF) {
isize = pcheckdata[0];
if (isize == 0) {
/* Finish Log */
bget_nextlog = false;
} else if (bSortLog) {
/* No Full 4K Package */
for (iend = 0; iend < isize - 32; iend += sizeof(struct eventlog)) {
if (memcmp(&data[iend], zerob, sizeof(struct eventlog)) != 0) {
memcpy(&data16k[ioffset16k], &data[iend], sizeof(struct eventlog));
ioffset16k += sizeof(struct eventlog);
}
}
} else {
setfilecontent(filename, data, isize);
}
} else {
/* Full 4K Package */
if ((pevlog->signature == EVLOG_SIG) && (pevlog->log_type == 1))
bSortLog = true;
if (bSortLog) {
for (iend = 0; iend < SIZE_4K; iend += sizeof(struct eventlog)) {
if (memcmp(&data[iend], zerob, sizeof(struct eventlog)) != 0) {
memcpy(&data16k[ioffset16k], &data[iend], sizeof(struct eventlog));
ioffset16k += sizeof(struct eventlog);
}
}
iblock++;
if (iblock == 4) {
sort_eventlog((struct eventlog *)(data16k + sizeof(struct evlg_flush_hdr)),
(ioffset16k - sizeof(struct evlg_flush_hdr))/sizeof(struct eventlog));
setfilecontent(filename, data16k, ioffset16k);
ioffset16k = 0;
iblock = 0;
memset(data16k, 0, SIZE_16K);
}
} else {
setfilecontent(filename, data, SIZE_4K);
}
}
}
if (bSortLog) {
if (ioffset16k > 0) {
sort_eventlog((struct eventlog *)(data16k + sizeof(struct evlg_flush_hdr)),
(ioffset16k - sizeof(struct evlg_flush_hdr))/sizeof(struct eventlog));
setfilecontent(filename, data16k, ioffset16k);
}
}
printf("\r" XCLEAN_LINE "Dump eventLog finish to %s\n", filename);
chmod(filename, 0666);
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);
}
return ret;
}
static int innogrit_vsc_getcdump(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
time_t timep;
struct tm *logtime;
char currentdir[128], filename[512], fname[128];
unsigned int itotal, icur;
unsigned char data[4096];
struct cdumpinfo cdumpinfo;
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 ";
OPT_ARGS(opts) = {
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
if (getcwd(currentdir, 128) == NULL)
return -1;
time(&timep);
logtime = localtime(&timep);
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) {
memcpy(&cdumpinfo, &data[3072], sizeof(cdumpinfo));
if (cdumpinfo.sig == 0x5a5b5c5d) {
busevsc = true;
ipackcount = cdumpinfo.ipackcount;
if (ipackcount == 0) {
itotal = 0;
} else {
itotal = cdumpinfo.cdumppack[ipackindex].ilenth;
memset(fwvera, 0, sizeof(fwvera));
memcpy(fwvera, cdumpinfo.cdumppack[ipackindex].fwver, 8);
sprintf(fname, "cdump_%02d%02d-%02d%02d%02d_%d_%s.cdp", logtime->tm_mon+1,
logtime->tm_mday, logtime->tm_hour, logtime->tm_min, logtime->tm_sec,
ipackindex, fwvera);
sprintf(filename, "%s/%s", currentdir, fname);
}
}
}
if (busevsc == false) {
memset(data, 0, 4096);
ret = nvme_get_nsid_log(fd, true, 0x07, NVME_NSID_ALL, 4096, data);
if (ret != 0)
return ret;
ipackcount = 1;
memcpy(&itotal, &data[4092], 4);
sprintf(fname, "cdump_%02d%02d-%02d%02d%02d.cdp", logtime->tm_mon+1, logtime->tm_mday,
logtime->tm_hour, logtime->tm_min, logtime->tm_sec);
sprintf(filename, "%s/%s", currentdir, fname);
}
if (itotal == 0) {
printf("no cdump data\n");
return 0;
}
while (ipackindex < ipackcount) {
memset(data, 0, 4096);
strcpy((char *)data, "cdumpstart");
setfilecontent(filename, data, strlen((char *)data));
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);
else
ret = nvme_get_nsid_log(fd, true, 0x07, NVME_NSID_ALL, 4096, data);
if (ret != 0)
return ret;
setfilecontent(filename, data, 4096);
printf("\rWait for dump data %d%%" XCLEAN_LINE, ((icur+4096) * 100/itotal));
}
memset(data, 0, 4096);
strcpy((char *)data, "cdumpend");
setfilecontent(filename, data, strlen((char *)data));
printf("\r%s\n", fname);
ipackindex++;
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);
else
ret = nvme_get_nsid_log(fd, true, 0x07, NVME_NSID_ALL, 4096, data);
if (ret != 0)
return ret;
itotal = cdumpinfo.cdumppack[ipackindex].ilenth;
memset(fwvera, 0, sizeof(fwvera));
memcpy(fwvera, cdumpinfo.cdumppack[ipackindex].fwver, 8);
sprintf(fname, "cdump_%02d%02d-%02d%02d%02d_%d_%s.cdp", logtime->tm_mon+1,
logtime->tm_mday, logtime->tm_hour, logtime->tm_min, logtime->tm_sec,
ipackindex, fwvera);
sprintf(filename, "%s/%s", currentdir, fname);
}
}
printf("\n");
return ret;
}

View file

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/innogrit/innogrit-nvme
#if !defined(INNOGRIT_NVME) || defined(CMD_HEADER_MULTI_READ)
#define INNOGRIT_NVME
#include "cmd.h"
PLUGIN(NAME("innogrit", "innogrit vendor specific extensions", NVME_VERSION),
COMMAND_LIST(
ENTRY("smart-log-add", "Retrieve innogrit SMART Log, show it", innogrit_smart_log_additional)
ENTRY("get-eventlog", "get event log", innogrit_vsc_geteventlog)
ENTRY("get-cdump", "get cdump data", innogrit_vsc_getcdump)
)
);
#endif
#include "define_cmd.h"

View file

@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#define SIZE_4K 4096
#define SIZE_16K 16384
#define NVME_VSC_GET_EVENT_LOG 0xC2
#define NVME_VSC_CLEAN_EVENT_LOG 0xD8
#define NVME_VSC_GET 0xE6
#define VSC_FN_GET_CDUMP 0x08
#define EVLOG_SIG 0x65766C67
#define SRB_SIGNATURE 0x544952474F4E4E49ULL
#define XCLEAN_LINE "\033[K"
struct evlg_flush_hdr {
unsigned int signature;
unsigned int fw_ver[2];
unsigned int fw_type : 8;
unsigned int log_type : 8;
unsigned int project : 16;
unsigned int trace_cnt;
unsigned int sout_crc;
unsigned int reserved[2];
};
struct eventlog {
unsigned int ms;
unsigned int param[7];
};
struct eventlog_addindex {
unsigned int ms;
unsigned int param[7];
unsigned int iindex;
};
#pragma pack(push)
#pragma pack(1)
struct vsc_smart_log {
unsigned short defect_cnt;
unsigned short slc_spb_cnt;
unsigned int slc_total_ec_cnt;
unsigned int slc_max_ec_cnt;
unsigned int slc_min_ec_cnt;
unsigned int slc_avg_ec_cnt;
unsigned int total_ec_cnt;
unsigned int max_ec_cnt;
unsigned int min_ec_cnt;
unsigned int avg_ec_cnt;
unsigned int mrd_rr_good_cnt;
unsigned int ard_rr_good_cnt;
unsigned int preset_cnt;
unsigned int nvme_reset_cnt;
unsigned int low_pwr_cnt;
unsigned int wa;
unsigned int ps3_entry_cnt;
u_char highest_temp[4];
unsigned int weight_ec;
unsigned int slc_cap_mb;
unsigned long long nand_page_write_cnt;
unsigned int reserved2[49];
};
#pragma pack(pop)
struct cdump_pack {
unsigned int ilenth;
char fwver[8];
};
struct cdumpinfo {
unsigned int sig;
unsigned int ipackcount;
struct cdump_pack cdumppack[32];
};

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -179,7 +180,7 @@ static void show_intel_smart_log_jsn(struct nvme_additional_smart_log *smart,
entry_stats = json_create_object();
json_object_add_value_int(entry_stats, "normalized", smart->timed_workload_media_wear.norm);
json_object_add_value_float(entry_stats, "raw", ((long double)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024);
json_object_add_value_double(entry_stats, "raw", ((long double)int48_to_long(smart->timed_workload_media_wear.raw)) / 1024);
json_object_add_value_object(dev_stats, "timed_workload_media_wear", entry_stats);
entry_stats = json_create_object();
@ -377,6 +378,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
}
else if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -412,6 +414,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);
return err;
}
@ -472,6 +475,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);
return err;
}
@ -1105,21 +1109,19 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
sizeof(struct intel_lat_stats));
}
if (!err) {
if (cfg.json)
json_lat_stats(cfg.write);
else if (!cfg.raw_binary)
show_lat_stats(cfg.write);
else {
if (media_version[0] == 1000)
d_raw((unsigned char *)&v1000_stats,
sizeof(v1000_stats));
else
d_raw((unsigned char *)&stats,
sizeof(stats));
}
} else if (err > 0)
nvme_show_status(err);
if (cfg.json)
json_lat_stats(cfg.write);
else if (!cfg.raw_binary)
show_lat_stats(cfg.write);
else {
if (media_version[0] == 1000)
d_raw((unsigned char *)&v1000_stats,
sizeof(v1000_stats));
else
d_raw((unsigned char *)&stats,
sizeof(stats));
}
close_fd:
close(fd);
return err;
@ -1385,14 +1387,14 @@ static int get_internal_log(int argc, char **argv, struct command *command,
}
if (cfg.log > 2 || cfg.core > 4 || cfg.lnum > 255) {
free(intel);
return EINVAL;
err = -EINVAL;
goto out_free;
}
if (!cfg.file) {
err = setup_file(f, cfg.file, fd, cfg.log);
if (err)
goto out;
goto out_free;
cfg.file = f;
}
@ -1403,6 +1405,10 @@ static int get_internal_log(int argc, char **argv, struct command *command,
cdlog.u.fields.selectNlog = cfg.lnum < 0 ? 0 : cfg.lnum;
output = open(cfg.file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (output < 0) {
err = output;
goto out_free;
}
err = read_header(&cmd, buf, fd, cdlog.u.entireDword, cfg.namespace_id);
if (err)
@ -1494,7 +1500,7 @@ static int get_internal_log(int argc, char **argv, struct command *command,
}
}
err = 0;
out:
out:
if (err > 0) {
nvme_show_status(err);
} else if (err < 0) {
@ -1502,7 +1508,10 @@ static int get_internal_log(int argc, char **argv, struct command *command,
err = EIO;
} else
printf("Successfully wrote log to %s\n", cfg.file);
close(output);
out_free:
free(intel);
close(fd);
return err;
}
@ -1597,6 +1606,7 @@ static int enable_lat_stats_tracking(int argc, char **argv,
fid, result);
} else {
printf("Could not read feature id 0xE2.\n");
close(fd);
return err;
}
break;
@ -1617,6 +1627,7 @@ static int enable_lat_stats_tracking(int argc, char **argv,
printf("%d not supported.\n", option);
return EINVAL;
}
close(fd);
return fd;
}

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/intel/intel-nvme

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -161,6 +162,15 @@ static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s,
u8 *nm = malloc(NM_SIZE * sizeof(u8));
u8 *raw = malloc(RAW_SIZE * sizeof(u8));
if (!nm) {
if (raw)
free(raw);
return;
}
if (!raw) {
free(nm);
return;
}
/* Table Title */
printf("%s:%s %s:%x\n", STRN2_01, devname, STRN2_02, nsid);
/* Clumn Name*/
@ -242,11 +252,11 @@ static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s,
static void show_memblaze_smart_log_old(struct nvme_memblaze_smart_log *smart,
unsigned int nsid, const char *devname, const char *fw_ver)
{
char fw_ver_local[STR_VER_SIZE];
char fw_ver_local[STR_VER_SIZE + 1];
struct nvme_memblaze_smart_log_item *item;
strncpy(fw_ver_local, fw_ver, STR_VER_SIZE);
*(fw_ver_local + STR_VER_SIZE - 1) = '\0';
*(fw_ver_local + STR_VER_SIZE) = '\0';
printf("Additional Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid);
@ -342,6 +352,15 @@ static void show_memblaze_smart_log_old(struct nvme_memblaze_smart_log *smart,
u8 *nm = malloc(NM_SIZE * sizeof(u8));
u8 *raw = malloc(RAW_SIZE * sizeof(u8));
if (!nm) {
if (raw)
free(raw);
return;
}
if (!raw) {
free(nm);
return;
}
/* 00 RAISIN_SI_VD_PROGRAM_FAIL */
get_memblaze_new_smart_info(s, PROGRAM_FAIL, nm, raw);
printf("%-32s : %3d%% %"PRIu64"\n",
@ -407,11 +426,13 @@ int parse_params(char *str, int number, ...)
c = strtok(str, ",");
if ( c == NULL) {
printf("No enough parameters. abort...\n");
exit(EINVAL);
va_end(argp);
return 1;
}
if (isalnum((int)*c) == 0) {
printf("%s is not a valid number\n", c);
va_end(argp);
return 1;
}
value = atoi(c);
@ -467,6 +488,7 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm
if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -517,6 +539,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);
return err;
}
@ -574,6 +597,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd
} else if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -613,11 +637,13 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s
if (parse_params(cfg.param, 2, &param1, &param2)) {
printf("setfeature: invalid formats %s\n", cfg.param);
exit(EINVAL);
close(fd);
return EINVAL;
}
if ((param1 == 1) && (param2 < P2MIN || param2 > P2MAX)) {
printf("setfeature: invalid high io latency threshold %d\n", param2);
exit(EINVAL);
close(fd);
return EINVAL;
}
cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2;
@ -646,6 +672,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);
return err;
}
@ -726,9 +753,14 @@ static int glp_high_latency(FILE *fdi, char *buf, int buflen, int print)
1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, millisec);
}
fprintf(fdi, "%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n",
string, logEntry->opcode, logEntry->sqe, logEntry->cid, logEntry->nsid,
(__u32)(logEntry->sLBA >> 32), (__u32)logEntry->sLBA, logEntry->numLBA, logEntry->latency);
if (fdi) {
fprintf(fdi, "%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n",
string, logEntry->opcode, logEntry->sqe,
logEntry->cid, logEntry->nsid,
(__u32)(logEntry->sLBA >> 32),
(__u32)logEntry->sLBA, logEntry->numLBA,
logEntry->latency);
}
if (print)
{
printf("%-32s %-7x %-6x %-6x %-8x %4x%08x %-8x %-d\n",
@ -746,7 +778,6 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd,
char buf[LOG_PAGE_SIZE];
FILE *fdi = NULL;
fdi = fopen(FID_C3_LOG_FILENAME, "w+");
OPT_ARGS(opts) = {
OPT_END()
};
@ -754,6 +785,8 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd,
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
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);
@ -767,6 +800,7 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd,
}
if (NULL != fdi) fclose(fdi);
close(fd);
return err;
}
@ -852,23 +886,26 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str
if (err < 0) {
perror("fstat");
err = errno;
goto out_close;
}
fw_size = sb.st_size;
if (fw_size & 0x3) {
fprintf(stderr, "Invalid size:%d for f/w image\n", fw_size);
err = EINVAL;
goto out;
goto out_close;
}
if (posix_memalign(&fw_buf, getpagesize(), fw_size)) {
fprintf(stderr, "No memory for f/w size:%d\n", fw_size);
err = ENOMEM;
goto out;
goto out_close;
}
if (read(fw_fd, fw_buf, fw_size) != ((ssize_t)(fw_size)))
return EIO;
if (read(fw_fd, fw_buf, fw_size) != ((ssize_t)(fw_size))) {
err = errno;
goto out_free;
}
while (fw_size > 0) {
xfer = min(xfer, fw_size);
@ -885,10 +922,10 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str
err = nvme_fw_download(&args);
if (err < 0) {
perror("fw-download");
goto out;
goto out_free;
} else if (err != 0) {
nvme_show_status(err);
goto out;
goto out_free;
}
fw_buf += xfer;
fw_size -= xfer;
@ -902,7 +939,12 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str
fprintf(stderr, "Update successful! Please power cycle for changes to take effect\n");
}
out_free:
free(fw_buf);
out_close:
close(fw_fd);
out:
close(fd);
return err;
}
@ -912,22 +954,17 @@ static void ioLatencyHistogramOutput(FILE *fd, int index, int start, int end, ch
int len;
char string[64], subString0[12], subString1[12];
len = snprintf(subString0, sizeof(subString0), "%d%s", start, unit0);
snprintf(subString0, sizeof(subString0), "%d%s", start, unit0);
if (end != 0x7FFFFFFF)
{
len = snprintf(subString1, sizeof(subString1), "%d%s", end, unit1);
}
snprintf(subString1, sizeof(subString1), "%d%s", end, unit1);
else
{
len = snprintf(subString1, sizeof(subString1), "%s", "+INF");
}
len = snprintf(string, sizeof(string), "%-11d %-11s %-11s %-11u\n", index, subString0, subString1,
snprintf(subString1, sizeof(subString1), "%s", "+INF");
len = snprintf(string, sizeof(string), "%-11d %-11s %-11s %-11u\n",
index, subString0, subString1,
pHistogram[index]);
fwrite(string, 1, len, fd);
if (print)
{
printf("%s", string);
}
}
int io_latency_histogram(char *file, char *buf, int print, int logid)
@ -1006,7 +1043,8 @@ int io_latency_histogram(char *file, char *buf, int print, int logid)
fPRINT_PARAM1("Unsupported io latency histogram revision\n");
}
fclose(fdi);
if (fdi)
fclose(fdi);
return 1;
}
@ -1116,6 +1154,7 @@ 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);
return err;
}
@ -1208,6 +1247,7 @@ static int mb_set_lat_stats(int argc, char **argv,
fid, result);
} else {
printf("Could not read feature id 0xE2.\n");
close(fd);
return err;
}
break;
@ -1226,8 +1266,9 @@ static int mb_set_lat_stats(int argc, char **argv,
break;
default:
printf("%d not supported.\n", option);
return EINVAL;
err = EINVAL;
}
return fd;
close(fd);
return err;
}

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/memblaze/memblaze-nvme

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef __MEMBLAZE_UTILS_H__
#define __MEMBLAZE_UTILS_H__
@ -199,28 +200,24 @@ struct nvme_p4_smart_log
printf("=Memblaze= %s[%d]-%s():%d=%s\n", \
__FILE__, __LINE__, __func__, ip, argv[ip]); }while(0)
#define fPRINT_PARAM1(format) \
{ \
do \
{ \
fprintf(fdi, format);\
if (print) \
{ \
printf(format); \
} \
} while (0); \
#define fPRINT_PARAM1(format) \
{ \
do { \
if (fdi) \
fprintf(fdi, format); \
if (print) \
printf(format); \
} while (0); \
}
#define fPRINT_PARAM2(format, value) \
{ \
do \
{ \
fprintf(fdi, format, value);\
if (print) \
{ \
printf(format, value); \
} \
} while (0); \
#define fPRINT_PARAM2(format, value) \
{ \
do { \
if (fdi) \
fprintf(fdi, format, value); \
if (print) \
printf(format, value); \
} while (0); \
}
#endif // __MEMBLAZE_UTILS_H__

View file

@ -1,8 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-or-later
sources += [
'plugins/amzn/amzn-nvme.c',
'plugins/dell/dell-nvme.c',
'plugins/dera/dera-nvme.c',
'plugins/huawei/huawei-nvme.c',
'plugins/intel/intel-nvme.c',
'plugins/innogrit/innogrit-nvme.c',
'plugins/memblaze/memblaze-nvme.c',
'plugins/micron/micron-nvme.c',
'plugins/netapp/netapp-nvme.c',
@ -10,6 +14,7 @@ sources += [
'plugins/scaleflux/sfx-nvme.c',
'plugins/seagate/seagate-nvme.c',
'plugins/shannon/shannon-nvme.c',
'plugins/solidigm/solidigm-nvme.c',
'plugins/toshiba/toshiba-nvme.c',
'plugins/transcend/transcend-nvme.c',
'plugins/virtium/virtium-nvme.c',
@ -19,3 +24,4 @@ sources += [
'plugins/zns/zns.c',
'plugins/ocp/ocp-nvme.c',
]
subdir('solidigm')

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/micron/micron-nvme

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2018 NetApp, Inc.
*
@ -103,12 +104,12 @@ static void netapp_nguid_to_str(char *str, __u8 *nguid)
str += sprintf(str, "%02x", nguid[i]);
}
static void netapp_get_ns_size(char *size, long long *lba,
static void netapp_get_ns_size(char *size, unsigned long long *lba,
struct nvme_id_ns *ns)
{
__u8 lba_index;
nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index);
*lba = 1 << ns->lbaf[lba_index].ds;
*lba = 1ULL << ns->lbaf[lba_index].ds;
double nsze = le64_to_cpu(ns->nsze) * (*lba);
const char *s_suffix = suffix_si_get(&nsze);
@ -263,7 +264,7 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
for (i = 0; i < count; i++) {
nvme_id_ns_flbas_to_lbaf_inuse(devices[i].ns.flbas, &lba_index);
long long int lba = 1 << devices[i].ns.lbaf[lba_index].ds;
unsigned long long int lba = 1ULL << devices[i].ns.lbaf[lba_index].ds;
double nsze = le64_to_cpu(devices[i].ns.nsze) * lba;
const char *s_suffix = suffix_si_get(&nsze);
char size[128];
@ -302,7 +303,7 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices,
struct json_object *json_devices = NULL;
char vsname[ONTAP_LABEL_LEN] = " ";
char nspath[ONTAP_NS_PATHLEN] = " ";
long long lba;
unsigned long long lba;
char size[128];
char uuid_str[37] = " ";
int i;
@ -392,8 +393,10 @@ static int netapp_smdevices_get_info(int fd, struct smdevice_info *item,
err = nvme_identify_ctrl(fd, &item->ctrl);
if (err) {
fprintf(stderr, "Identify Controller failed to %s (%s)\n", dev,
strerror(err));
fprintf(stderr,
"Identify Controller failed to %s (%s)\n", dev,
err < 0 ? strerror(-err) :
nvme_status_to_string(err, false));
return 0;
}
@ -403,11 +406,13 @@ static int netapp_smdevices_get_info(int fd, struct smdevice_info *item,
err = nvme_get_nsid(fd, &item->nsid);
err = nvme_identify_ns(fd, item->nsid, &item->ns);
if (err) {
fprintf(stderr, "Unable to identify namespace for %s (%s)\n",
dev, strerror(err));
fprintf(stderr,
"Unable to identify namespace for %s (%s)\n",
dev, err < 0 ? strerror(-err) :
nvme_status_to_string(err, false));
return 0;
}
strncpy(item->dev, dev, sizeof(item->dev));
strncpy(item->dev, dev, sizeof(item->dev) - 1);
return 1;
}
@ -421,7 +426,8 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
err = nvme_identify_ctrl(fd, &item->ctrl);
if (err) {
fprintf(stderr, "Identify Controller failed to %s (%s)\n",
dev, strerror(err));
dev, err < 0 ? strerror(-err) :
nvme_status_to_string(err, false));
return 0;
}
@ -434,7 +440,8 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
err = nvme_identify_ns(fd, item->nsid, &item->ns);
if (err) {
fprintf(stderr, "Unable to identify namespace for %s (%s)\n",
dev, strerror(err));
dev, err < 0 ? strerror(-err) :
nvme_status_to_string(err, false));
return 0;
}
@ -446,7 +453,9 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
err = nvme_identify_ns_descs(fd, item->nsid, nsdescs);
if (err) {
fprintf(stderr, "Unable to identify namespace descriptor for %s (%s)\n",
dev, strerror(err));
dev, err < 0 ? strerror(-err) :
nvme_status_to_string(err, false));
free(nsdescs);
return 0;
}
@ -456,11 +465,12 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
err = nvme_get_ontap_c2_log(fd, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE);
if (err) {
fprintf(stderr, "Unable to get log page data for %s (%s)\n",
dev, strerror(err));
dev, err < 0 ? strerror(-err):
nvme_status_to_string(err, false));
return 0;
}
strncpy(item->dev, dev, sizeof(item->dev));
strncpy(item->dev, dev, sizeof(item->dev) - 1);
return 1;
}

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/netapp/netapp-nvme

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/nvidia/nvidia-nvme

View file

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-License-Identifier: GPL-2.0-or-later
/* Copyright (c) 2022 Meta Platforms, Inc.
*
* Authors: Arthur Shau <arthurshau@fb.com>,
@ -380,11 +380,6 @@ static int get_c0_log_page(int fd, char *format)
}
/* print the data */
if (!data) {
fprintf(stderr, "ERROR : OCP : Invalid buffer to read 0xC0 log\n");
ret = -1;
goto out;
}
switch (fmt) {
case NORMAL:
ocp_print_C0_log_normal(data);
@ -430,7 +425,7 @@ static int ocp_smart_add_log(int argc, char **argv, struct command *cmd,
if (ret)
fprintf(stderr, "ERROR : OCP : Failure reading the C0 Log Page, ret = %d\n",
ret);
close(fd);
return ret;
}
@ -728,13 +723,6 @@ static int get_c3_log_page(int fd, char *format)
}
}
/* print the data */
if (!log_data) {
fprintf(stderr,
"ERROR : OCP : Invalid C3 log data buffer\n");
ret = -1;
goto out;
}
switch (fmt) {
case NORMAL:
ocp_print_C3_log_normal(fd, log_data);
@ -783,6 +771,6 @@ static int ocp_latency_monitor_log(int argc, char **argv, struct command *comman
fprintf(stderr,
"ERROR : OCP : Failure reading the C3 Log Page, ret = %d\n",
ret);
close(fd);
return ret;
}

View file

@ -1,4 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Copyright (c) 2022 Meta Platforms, Inc.
*
* Authors: Arthur Shau <arthurshau@fb.com>,

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -29,6 +30,12 @@
#define IDEMA_CAP(exp_GB) (((__u64)exp_GB - 50ULL) * 1953504ULL + 97696368ULL)
#define IDEMA_CAP2GB(exp_sector) (((__u64)exp_sector - 97696368ULL) / 1953504ULL + 50ULL)
#define VANDA_MAJOR_IDX 0
#define VANDA_MINOR_IDX 0
#define MYRTLE_MAJOR_IDX 4
#define MYRTLE_MINOR_IDX 1
enum {
SFX_LOG_LATENCY_READ_STATS = 0xc1,
SFX_LOG_SMART = 0xc2,
@ -58,6 +65,7 @@ struct sfx_freespace_ctx
__u64 user_space; /* user required space, in unit of sector*/
__u64 hw_used; /* hw space used in 4K */
__u64 app_written; /* app data written in 4K */
__u64 out_of_space;
};
struct nvme_capacity_info {
@ -66,25 +74,26 @@ struct nvme_capacity_info {
__u64 used_space;
__u64 free_space;
};
struct __attribute__((packed)) nvme_additional_smart_log_item {
uint8_t key;
uint8_t _kp[2];
uint8_t norm;
uint8_t _np;
union {
uint8_t raw[6];
struct wear_level {
uint16_t min;
uint16_t max;
uint16_t avg;
} wear_level ;
struct thermal_throttle {
uint8_t pct;
uint32_t count;
struct __attribute__((packed)) nvme_additional_smart_log_item {
__u8 key;
__u8 _kp[2];
__u8 norm;
__u8 _np;
union __attribute__((packed)) {
__u8 raw[6];
struct __attribute__((packed)) wear_level {
__le16 min;
__le16 max;
__le16 avg;
} wear_level;
struct __attribute__((packed)) thermal_throttle {
__u8 pct;
__u32 count;
} thermal_throttle;
};
uint8_t _rp;
};
} ;
__u8 _rp;
} ;
struct nvme_additional_smart_log {
struct nvme_additional_smart_log_item program_fail_cnt;
@ -105,8 +114,26 @@ struct nvme_additional_smart_log {
struct nvme_additional_smart_log_item erase_timeout_cnt;
struct nvme_additional_smart_log_item read_timeout_cnt;
struct nvme_additional_smart_log_item read_ecc_cnt;//retry cnt
struct nvme_additional_smart_log_item non_media_crc_err_cnt;
struct nvme_additional_smart_log_item compression_path_err_cnt;
struct nvme_additional_smart_log_item out_of_space_flag;
struct nvme_additional_smart_log_item physical_usage_ratio;
struct nvme_additional_smart_log_item grown_bb; //grown bad block
};
int nvme_query_cap(int fd, __u32 nsid, __u32 data_len, void *data)
{
int rc = 0;
struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_query_cap_info,
.nsid = nsid,
.addr = (__u64)(uintptr_t) data,
.data_len = data_len,
};
rc = ioctl(fd, SFX_GET_FREESPACE, data);
return rc == 0 ? 0 : nvme_submit_admin_passthru(fd, &cmd, NULL);
}
int nvme_change_cap(int fd, __u32 nsid, __u64 capacity)
{
struct nvme_passthru_cmd cmd = {
@ -255,6 +282,31 @@ static void show_sfx_smart_log_jsn(struct nvme_additional_smart_log *smart,
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->read_ecc_cnt.raw));
json_object_add_value_object(dev_stats, "read_ecc_cnt", entry_stats);
entry_stats = json_create_object();
json_object_add_value_int(entry_stats, "normalized", smart->non_media_crc_err_cnt.norm);
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->non_media_crc_err_cnt.raw));
json_object_add_value_object(dev_stats, "non_media_crc_err_cnt", entry_stats);
entry_stats = json_create_object();
json_object_add_value_int(entry_stats, "normalized", smart->compression_path_err_cnt.norm);
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->compression_path_err_cnt.raw));
json_object_add_value_object(dev_stats, "compression_path_err_cnt", entry_stats);
entry_stats = json_create_object();
json_object_add_value_int(entry_stats, "normalized", smart->out_of_space_flag.norm);
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->out_of_space_flag.raw));
json_object_add_value_object(dev_stats, "out_of_space_flag", entry_stats);
entry_stats = json_create_object();
json_object_add_value_int(entry_stats, "normalized", smart->physical_usage_ratio.norm);
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->physical_usage_ratio.raw));
json_object_add_value_object(dev_stats, "physical_usage_ratio", entry_stats);
entry_stats = json_create_object();
json_object_add_value_int(entry_stats, "normalized", smart->grown_bb.norm);
json_object_add_value_int(entry_stats, "raw", int48_to_long(smart->grown_bb.raw));
json_object_add_value_object(dev_stats, "grown_bb", entry_stats);
json_object_add_value_object(root, "Device stats", dev_stats);
json_print_object(root, NULL);
@ -325,6 +377,22 @@ static void show_sfx_smart_log(struct nvme_additional_smart_log *smart,
printf("read_timeout_cnt : %3d%% %"PRIu64"\n",
smart->read_timeout_cnt.norm,
int48_to_long(smart->read_timeout_cnt.raw));
printf("non_media_crc_err_cnt : %3d%% %" PRIu64 "\n",
smart->non_media_crc_err_cnt.norm,
int48_to_long(smart->non_media_crc_err_cnt.raw));
printf("compression_path_err_cnt : %3d%% %" PRIu64 "\n",
smart->compression_path_err_cnt.norm,
int48_to_long(smart->compression_path_err_cnt.raw));
printf("out_of_space_flag : %3d%% %" PRIu64 "\n",
smart->out_of_space_flag.norm,
int48_to_long(smart->out_of_space_flag.raw));
printf("phy_capacity_used_ratio : %3d%% %" PRIu64 "\n",
smart->physical_usage_ratio.norm,
int48_to_long(smart->physical_usage_ratio.raw));
printf("grown_bb_count : %3d%% %" PRIu64 "\n",
smart->grown_bb.norm, int48_to_long(smart->grown_bb.raw));
}
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@ -355,6 +423,9 @@ 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 = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
sizeof(smart_log), (void *)&smart_log);
@ -368,12 +439,13 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
}
else if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
struct sfx_lat_stats {
__u16 maj;
__u16 min;
struct __attribute__((__packed__)) sfx_lat_stats_vanda {
__u16 maj;
__u16 min;
__u32 bucket_1[32]; /* 0~1ms, step 32us */
__u32 bucket_2[31]; /* 1~32ms, step 1ms */
__u32 bucket_3[31]; /* 32ms~1s, step 32ms */
@ -382,11 +454,50 @@ struct sfx_lat_stats {
__u32 bucket_6[1]; /* 4s+, specifically 4096ms+ */
};
static void show_lat_stats(struct sfx_lat_stats *stats, int write)
struct __attribute__((__packed__)) sfx_lat_stats_myrtle {
__u16 maj;
__u16 min;
__u32 bucket_1[64]; /* 0us~63us, step 1us */
__u32 bucket_2[64]; /* 63us~127us, step 1us */
__u32 bucket_3[64]; /* 127us~255us, step 2us */
__u32 bucket_4[64]; /* 255us~510us, step 4us */
__u32 bucket_5[64]; /* 510us~1.02ms step 8us */
__u32 bucket_6[64]; /* 1.02ms~2.04ms step 16us */
__u32 bucket_7[64]; /* 2.04ms~4.08ms step 32us */
__u32 bucket_8[64]; /* 4.08ms~8.16ms step 64us */
__u32 bucket_9[64]; /* 8.16ms~16.32ms step 128us */
__u32 bucket_10[64]; /* 16.32ms~32.64ms step 256us */
__u32 bucket_11[64]; /* 32.64ms~65.28ms step 512us */
__u32 bucket_12[64]; /* 65.28ms~130.56ms step 1.024ms */
__u32 bucket_13[64]; /* 130.56ms~261.12ms step 2.048ms */
__u32 bucket_14[64]; /* 261.12ms~522.24ms step 4.096ms */
__u32 bucket_15[64]; /* 522.24ms~1.04s step 8.192ms */
__u32 bucket_16[64]; /* 1.04s~2.09s step 16.384ms */
__u32 bucket_17[64]; /* 2.09s~4.18s step 32.768ms */
__u32 bucket_18[64]; /* 4.18s~8.36s step 65.536ms */
__u32 bucket_19[64]; /* 8.36s~ step 131.072ms */
__u64 average; /* average latency statistics */
};
struct __attribute__((__packed__)) sfx_lat_status_ver {
__u16 maj;
__u16 min;
};
struct sfx_lat_stats {
union {
struct sfx_lat_status_ver ver;
struct sfx_lat_stats_vanda vanda;
struct sfx_lat_stats_myrtle myrtle;
};
};
static void show_lat_stats_vanda(struct sfx_lat_stats_vanda *stats, int write)
{
int i;
printf(" ScaleFlux IO %s Command Latency Statistics\n", write ? "Write" : "Read");
printf("ScaleFlux IO %s Command Latency Statistics\n", write ? "Write" : "Read");
printf("-------------------------------------\n");
printf("Major Revision : %u\n", stats->maj);
printf("Minor Revision : %u\n", stats->min);
@ -413,6 +524,95 @@ static void show_lat_stats(struct sfx_lat_stats *stats, int write)
printf("Bucket %2d: %u\n", 0, stats->bucket_6[0]);
}
static void show_lat_stats_myrtle(struct sfx_lat_stats_myrtle *stats, int write)
{
int i;
printf("ScaleFlux IO %s Command Latency Statistics\n", write ? "Write" : "Read");
printf("-------------------------------------\n");
printf("Major Revision : %u\n", stats->maj);
printf("Minor Revision : %u\n", stats->min);
printf("\nGroup 1: Range is 0us~63us, step 1us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_1[i]);
printf("\nGroup 2: Range is 63us~127us, step 1us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_2[i]);
printf("\nGroup 3: Range is 127us~255us, step 2us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_3[i]);
printf("\nGroup 4: Range is 255us~510us, step 4us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_4[i]);
printf("\nGroup 5: Range is 510us~1.02ms step\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_5[i]);
printf("\nGroup 6: Range is 1.02ms~2.04ms step 16us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_6[i]);
printf("\nGroup 7: Range is 2.04ms~4.08ms step 32us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_7[i]);
printf("\nGroup 8: Range is 4.08ms~8.16ms step 64us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_8[i]);
printf("\nGroup 9: Range is 8.16ms~16.32ms step 128us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_9[i]);
printf("\nGroup 10: Range is 16.32ms~32.64ms step 256us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_10[i]);
printf("\nGroup 11: Range is 32.64ms~65.28ms step 512us\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_11[i]);
printf("\nGroup 12: Range is 65.28ms~130.56ms step 1.024ms\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_12[i]);
printf("\nGroup 13: Range is 130.56ms~261.12ms step 2.048ms\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_13[i]);
printf("\nGroup 14: Range is 261.12ms~522.24ms step 4.096ms\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_14[i]);
printf("\nGroup 15: Range is 522.24ms~1.04s step 8.192ms\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_15[i]);
printf("\nGroup 16: Range is 1.04s~2.09s step 16.384ms\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_16[i]);
printf("\nGroup 17: Range is 2.09s~4.18s step 32.768ms\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_17[i]);
printf("\nGroup 18: Range is 4.18s~8.36s step 65.536ms\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_18[i]);
printf("\nGroup 19: Range is 8.36s~ step 131.072ms\n");
for (i = 0; i < 64; i++)
printf("Bucket %2d: %u\n", i, stats->bucket_19[i]);
printf("\nAverage latency statistics %lld\n", stats->average);
}
static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
struct sfx_lat_stats stats;
@ -436,15 +636,31 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
return fd;
}
err = nvme_get_log_simple(fd, cfg.write ? 0xc3 : 0xc1, sizeof(stats), (void *)&stats);
if (!err) {
if (!cfg.raw_binary)
show_lat_stats(&stats, cfg.write);
else
d_raw((unsigned char *)&stats, sizeof(stats));
if ((stats.ver.maj == VANDA_MAJOR_IDX) && (stats.ver.min == VANDA_MINOR_IDX)) {
if (!cfg.raw_binary) {
show_lat_stats_vanda(&stats.vanda, cfg.write);
} else {
d_raw((unsigned char *)&stats.vanda, sizeof(struct sfx_lat_stats_vanda));
}
} else if ((stats.ver.maj == MYRTLE_MAJOR_IDX) && (stats.ver.min == MYRTLE_MINOR_IDX)) {
if (!cfg.raw_binary) {
show_lat_stats_myrtle(&stats.myrtle, cfg.write);
} else {
d_raw((unsigned char *)&stats.myrtle, sizeof(struct sfx_lat_stats_myrtle));
}
} else {
printf("ScaleFlux IO %s Command Latency Statistics Invalid Version Maj %d Min %d\n",
write ? "Write" : "Read", stats.ver.maj, stats.ver.min);
}
} else if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -560,7 +776,6 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
return fd;
}
@ -568,6 +783,7 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct
data_buf = malloc(buf_size);
if (!data_buf) {
fprintf(stderr, "malloc fail, errno %d\r\n", errno);
close(fd);
return -1;
}
@ -582,6 +798,7 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct
}
free(data_buf);
close(fd);
return 0;
}
@ -603,18 +820,15 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu
{
struct sfx_freespace_ctx ctx = { 0 };
int err = 0, fd;
char *desc = "query current capacity info of vanda";
char *desc = "query current capacity info";
const char *raw = "dump output in binary format";
const char *json= "Dump output in json format";
struct config {
bool raw_binary;
bool json;
};
struct config cfg;
OPT_ARGS(opts) = {
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_FLAG("json", 'j', &cfg.json, json),
OPT_END()
};
@ -623,12 +837,19 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu
return fd;
}
if (ioctl(fd, SFX_GET_FREESPACE, &ctx)) {
fprintf(stderr, "vu ioctl fail, errno %d\r\n", errno);
return -1;
if (nvme_query_cap(fd, 0xffffffff, sizeof(ctx), &ctx)) {
perror("sfx-query-cap");
err = -1;
}
show_cap_info(&ctx);
if (!err) {
if (!cfg.raw_binary) {
show_cap_info(&ctx);
} else {
d_raw((unsigned char *)&ctx, sizeof(ctx));
}
}
close(fd);
return err;
}
@ -639,14 +860,10 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
__u64 mem_need = 0;
__u64 cur_in_4k = 0;
__u64 provisoned_cap_4k = 0;
__u32 cnt_ms = 0;
int extend = 0;
while (ioctl(fd, SFX_GET_FREESPACE, &freespace_ctx)) {
if (cnt_ms++ > 600) {//1min
return -1;
}
usleep(100000);
if (nvme_query_cap(fd, 0xffffffff, sizeof(freespace_ctx), &freespace_ctx)) {
return -1;
}
/*
@ -706,12 +923,12 @@ static int change_sanity_check(int fd, __u64 trg_in_4k, int *shrink)
*/
static int sfx_confirm_change(const char *str)
{
char confirm;
unsigned char confirm;
fprintf(stderr, "WARNING: %s.\n"
"Use the force [--force] option to suppress this warning.\n", str);
fprintf(stderr, "Confirm Y/y, Others cancel:\n");
confirm = fgetc(stdin);
confirm = (unsigned char)fgetc(stdin);
if (confirm != 'y' && confirm != 'Y') {
fprintf(stderr, "Cancled.\n");
return 0;
@ -723,9 +940,7 @@ 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 = "query current capacity info of vanda";
const char *raw = "dump output in binary format";
const char *json= "Dump output in json format";
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";
@ -736,8 +951,6 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
struct config {
__u64 cap_in_byte;
__u32 capacity_in_gb;
bool raw_binary;
bool json;
bool force;
};
@ -751,8 +964,6 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
OPT_UINT("cap", 'c', &cfg.capacity_in_gb, cap_gb),
OPT_SUFFIX("cap-byte", 'z', &cfg.cap_in_byte, cap_byte),
OPT_FLAG("force", 'f', &cfg.force, force),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_FLAG("json", 'j', &cfg.json, json),
OPT_END()
};
@ -770,10 +981,12 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
if (change_sanity_check(fd, cap_in_4k, &shrink)) {
printf("ScaleFlux change-capacity: fail\n");
close(fd);
return err;
}
if (!cfg.force && shrink && !sfx_confirm_change("Changing Cap may irrevocably delete this device's data")) {
close(fd);
return 0;
}
@ -786,6 +999,7 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
printf("ScaleFlux change-capacity: success\n");
ioctl(fd, BLKRRPART);
}
close(fd);
return err;
}
@ -877,12 +1091,14 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
if (!cfg.feature_id) {
fprintf(stderr, "feature-id required param\n");
close(fd);
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);
return 0;
} else {
return sfx_clean_card(fd);
@ -898,6 +1114,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
perror("identify-namespace");
else
nvme_show_status(err);
close(fd);
return err;
}
/*
@ -905,17 +1122,20 @@ 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);
return EFAULT;
}
}
} else if (cfg.feature_id == SFX_FEAT_UP_P_CAP) {
if (cfg.value <= 0) {
fprintf(stderr, "Invalid Param\n");
close(fd);
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);
return 0;
}
}
@ -924,6 +1144,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
if (err < 0) {
perror("ScaleFlux-set-feature");
close(fd);
return errno;
} else if (!err) {
printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id,
@ -931,6 +1152,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
} else if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -959,19 +1181,20 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
return fd;
}
if (!cfg.feature_id) {
fprintf(stderr, "feature-id required param\n");
close(fd);
return EINVAL;
}
err = nvme_sfx_get_features(fd, cfg.namespace_id, cfg.feature_id, &result);
if (err < 0) {
perror("ScaleFlux-get-feature");
close(fd);
return errno;
} else if (!err) {
printf("ScaleFlux get-feature:%02x (%s), value:%d\n", cfg.feature_id,
@ -979,6 +1202,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);
return err;
}

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/scaleflux/sfx-nvme

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Do NOT modify or remove this copyright and license
*

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Do NOT modify or remove this copyright and license
*
@ -147,6 +148,7 @@ static void json_log_pages_supp(log_page_map *logPageMap)
}
json_print_object(root, NULL);
printf("\n");
json_free_object(root);
}
static int log_pages_supp(int argc, char **argv, struct command *cmd,
@ -174,6 +176,8 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd,
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
err = nvme_get_log_simple(fd, 0xc5, sizeof(logPageMap), &logPageMap);
if (!err) {
if (strcmp(cfg.output_format,"json")) {
@ -199,6 +203,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd,
if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -732,6 +737,11 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
printf ("\nDevice not found \n");
return -1;
}
if (strcmp(cfg.output_format,"json"))
printf("Seagate Extended SMART Information :\n");
@ -774,6 +784,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
} else if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -889,6 +900,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin
if(!strcmp(cfg.output_format,"json"))
json_temp_stats(temperature, PcbTemp, SocTemp, maxTemperature, MaxSocTemp, cf_err, scCurrentTemp, scMaxTemp);
close(fd);
return err;
}
/* EOF Temperature Stats information */
@ -1000,6 +1012,11 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
printf ("\nDevice not found \n");;
return -1;
}
if(strcmp(cfg.output_format,"json"))
printf("Seagate PCIe error counters Information :\n");
@ -1013,6 +1030,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct
} else if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
/* EOF PCIE error-log information */
@ -1038,14 +1056,18 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
printf ("\nDevice not found \n");;
return -1;
}
err = nvme_set_features_simple(fd, 0xE1, 0, 0xCB, cfg.save, &result);
if (err < 0) {
perror("set-feature");
return errno;
}
close(fd);
return err;
}
@ -1113,19 +1135,25 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
blkCnt = 0;
while(blkCnt < maxBlk) {
unsigned long long bytesToGet;
blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt);
if(blksToGet == 0)
if(blksToGet == 0) {
close(fd);
return err;
}
log = malloc(blksToGet * 512);
bytesToGet = (unsigned long long)blksToGet * 512;
log = malloc(bytesToGet);
if (!log) {
fprintf(stderr, "could not alloc buffer for log\n");
close(fd);
return EINVAL;
}
memset(log, 0, blksToGet * 512);
memset(log, 0, bytesToGet);
struct nvme_get_log_args args = {
.args_size = sizeof(args),
@ -1139,21 +1167,21 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
.uuidx = 0,
.csi = NVME_CSI_NVM,
.ot = false,
.len = blksToGet * 512,
.len = bytesToGet,
.log = (void *)log,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = NULL,
};
err = nvme_get_log(&args);
if (!err) {
offset += blksToGet * 512;
offset += (__le64)bytesToGet;
if (!cfg.raw_binary) {
printf("\nBlock # :%d to %d\n", blkCnt + 1, blkCnt + blksToGet);
d((unsigned char *)log, blksToGet * 512, 16, 1);
d((unsigned char *)log, bytesToGet, 16, 1);
} else
seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd);
seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd);
} else if (err > 0)
nvme_show_status(err);
else
@ -1164,6 +1192,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
free(log);
}
close(fd);
return err;
}
@ -1225,19 +1254,22 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
blkCnt = 0;
while(blkCnt < maxBlk) {
unsigned long long bytesToGet;
blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt);
if(blksToGet == 0)
return err;
log = malloc(blksToGet * 512);
bytesToGet = (unsigned long long)blksToGet * 512;
log = malloc(bytesToGet);
if (!log) {
fprintf(stderr, "could not alloc buffer for log\n");
return EINVAL;
}
memset(log, 0, blksToGet * 512);
memset(log, 0, bytesToGet);
struct nvme_get_log_args args = {
.args_size = sizeof(args),
@ -1251,21 +1283,21 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
.uuidx = 0,
.csi = NVME_CSI_NVM,
.ot = false,
.len = blksToGet * 512,
.len = bytesToGet,
.log = (void *)log,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = NULL,
};
err = nvme_get_log(&args);
if (!err) {
offset += blksToGet * 512;
offset += (__le64)bytesToGet;
if (!cfg.raw_binary) {
printf("\nBlock # :%d to %d\n", blkCnt + 1, blkCnt + blksToGet);
d((unsigned char *)log, blksToGet * 512, 16, 1);
d((unsigned char *)log, bytesToGet, 16, 1);
} else
seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd);
seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd);
} else if (err > 0)
nvme_show_status(err);
else
@ -1275,8 +1307,9 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
free(log);
}
return err;
close(fd);
return err;
}
void seaget_d_raw(unsigned char *buf, int len, int fd)
@ -1334,6 +1367,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
dump_fd = open(cfg.file, flags, mode);
if (dump_fd < 0) {
perror(cfg.file);
close(fd);
return EINVAL;
}
}
@ -1358,20 +1392,24 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
blkCnt = 0;
while(blkCnt < maxBlk) {
unsigned long long bytesToGet;
blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt);
if(blksToGet == 0) {
return err;
goto out;
}
log = malloc(blksToGet * 512);
bytesToGet = (unsigned long long)blksToGet * 512;
log = malloc(bytesToGet);
if (!log) {
fprintf(stderr, "could not alloc buffer for log\n");
return EINVAL;
err = EINVAL;
goto out;
}
memset(log, 0, blksToGet * 512);
memset(log, 0, bytesToGet);
struct nvme_get_log_args args = {
.args_size = sizeof(args),
@ -1385,16 +1423,16 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
.uuidx = 0,
.csi = NVME_CSI_NVM,
.ot = false,
.len = blksToGet * 512,
.len = bytesToGet,
.log = (void *)log,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = NULL,
};
err = nvme_get_log(&args);
if (!err) {
offset += blksToGet * 512;
offset += (__le64)bytesToGet;
seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd);
seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd);
} else if (err > 0)
nvme_show_status(err);
@ -1405,10 +1443,11 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
free(log);
}
out:
if(strlen(cfg.file))
close(dump_fd);
close(fd);
return err;
}

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Do NOT modify or remove this copyright and license
*

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -137,6 +138,8 @@ 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 = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
sizeof(smart_log), &smart_log);
if (!err) {
@ -147,6 +150,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
}
else if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -156,7 +160,7 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
"specified controller. Operating parameters are grouped "\
"and identified by Feature Identifiers; each Feature "\
"Identifier contains one or more attributes that may affect "\
"behaviour of the feature. Each Feature has three possible "\
"behavior of the feature. Each Feature has three possible "\
"settings: default, saveable, and current. If a Feature is "\
"saveable, it may be modified by set-feature. Default values "\
"are vendor-specific and not changeable. Use set-feature to "\

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/shannon/shannon-nvme

View file

@ -0,0 +1,5 @@
sources += [
'plugins/solidigm/solidigm-smart.c',
'plugins/solidigm/solidigm-garbage-collection.c',
'plugins/solidigm/solidigm-latency-tracking.c',
]

View file

@ -0,0 +1,111 @@
// 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 <inttypes.h>
#include "common.h"
#include "nvme.h"
#include "libnvme.h"
#include "plugin.h"
#include "linux/types.h"
#include "nvme-print.h"
#include "solidigm-garbage-collection.h"
typedef struct __attribute__((packed)) gc_item {
__le32 timer_type;
__le64 timestamp;
} gc_item_t;
#define VU_GC_MAX_ITEMS 100
typedef struct garbage_control_collection_log {
__le16 version_major;
__le16 version_minor;
gc_item_t item[VU_GC_MAX_ITEMS];
__u8 reserved[2892];
} garbage_control_collection_log_t;
static void vu_gc_log_show_json(garbage_control_collection_log_t *payload, const char *devname)
{
struct json_object *gc_entries = json_create_array();
for (int i = 0; i < VU_GC_MAX_ITEMS; i++) {
gc_item_t item = payload->item[i];
struct json_object *entry = json_create_object();
json_object_add_value_int(entry, "timestamp", le64_to_cpu(item.timestamp));
json_object_add_value_int(entry, "timer_type", le32_to_cpu(item.timer_type));
json_array_add_value_object(gc_entries, entry);
}
json_print_object(gc_entries, NULL);
json_free_object(gc_entries);
}
static void vu_gc_log_show(garbage_control_collection_log_t *payload, const char *devname)
{
printf("Solidigm Garbage Collection Log for NVME device: %s\n", devname);
printf("Timestamp Timer Type\n");
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));
}
}
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 config {
char *output_format;
};
struct config cfg = {
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_END()
};
int fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
return fd;
}
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 fd;
}
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);
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);
} else {
vu_gc_log_show(&gc_log, devicename);
}
}
else if (err > 0) {
nvme_show_status(err);
}
close(fd);
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_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin);

View file

@ -0,0 +1,470 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022 Solidigm.
*
* Author: leonardo.da.cunha@solidigm.com
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include "common.h"
#include "nvme.h"
#include "libnvme.h"
#include "plugin.h"
#include "linux/types.h"
#include "nvme-print.h"
#define BUCKET_LIST_SIZE_4_0 152
#define BUCKET_LIST_SIZE_4_1 1216
#define BASE_RANGE_BITS_4_0 3
#define BASE_RANGE_BITS_4_1 6
struct latency_statistics {
__u16 version_major;
__u16 version_minor;
__u32 data[BUCKET_LIST_SIZE_4_1];
__u64 average_latency;
};
struct config {
bool enable;
bool disable;
bool read;
bool write;
unsigned char type;
char *output_format;
};
struct latency_tracker {
int fd;
struct config cfg;
enum nvme_print_flags print_flags;
struct latency_statistics stats;
struct json_object *bucket_list;
__u32 bucket_list_size;
__u8 base_range_bits;
bool has_average_latency_field;
};
/* COL_WIDTH controls width of columns in NORMAL output. */
#define COL_WIDTH 12
#define BUCKET_LABEL_MAX_SIZE 10
#define US_IN_S 1000000
#define US_IN_MS 1000
/*
* Edge buckets may have range [#s, inf) in some
* latency statistics formats.
*/
static void get_time_unit_label(char *label, __u32 microseconds,
bool bonded)
{
char *string = "us";
int divisor = 1;
if (!bonded) {
snprintf(label, BUCKET_LABEL_MAX_SIZE, "%s", "+INF");
return;
}
if (microseconds > US_IN_S) {
string = "s";
divisor = US_IN_S;
} else if (microseconds > US_IN_MS) {
string = "ms";
divisor = US_IN_MS;
}
snprintf(label, BUCKET_LABEL_MAX_SIZE, "%4.2f%s", (float) microseconds / divisor,
string);
}
static void latency_tracker_bucket_parse(const struct latency_tracker *lt, int id,
__u32 lower_us, __u32 upper_us, bool upper_bounded)
{
char buffer[BUCKET_LABEL_MAX_SIZE] = "";
__u32 bucket_data = le32_to_cpu(lt->stats.data[id]);
if (lt->print_flags == NORMAL) {
printf("%-*d", COL_WIDTH, id);
get_time_unit_label(buffer, lower_us, true);
printf("%-*s", COL_WIDTH, buffer);
get_time_unit_label(buffer, upper_us, upper_bounded);
printf("%-*s", COL_WIDTH, buffer);
printf("%-*d\n", COL_WIDTH, bucket_data);
}
if (lt->print_flags == JSON) {
/*
* Creates a bucket under the "values" json_object. Format is:
* "values" : {
* "bucket" : {
* "id" : #,
* "start" : string,
* "end" : string,
* "value" : 0,
* },
*/
struct json_object *bucket = json_create_object();
json_object_array_add(lt->bucket_list, bucket);
json_object_add_value_int(bucket, "id", id);
get_time_unit_label(buffer, lower_us, true);
json_object_add_value_string(bucket, "start", buffer);
get_time_unit_label(buffer, upper_us, upper_bounded);
json_object_add_value_string(bucket, "end", buffer);
json_object_add_value_int(bucket, "value", bucket_data);
}
}
static void latency_tracker_parse_linear(const struct latency_tracker *lt,
__u32 start_offset, __u32 end_offset,
__u32 bytes_per, __u32 us_step,
bool nonzero_print)
{
for (int i = (start_offset / bytes_per) - 1;
i < end_offset / bytes_per; i++) {
if (nonzero_print && lt->stats.data[i] == 0)
continue;
latency_tracker_bucket_parse(lt, i, us_step * i,
us_step * (i + 1), true);
}
}
/*
* Calculates bucket time slot. Valid starting on 4.0 revision.
*/
static int latency_tracker_bucket_pos2us(const struct latency_tracker *lt, int i)
{
__u32 base_val = 1 << lt->base_range_bits;
if (i < (base_val << 1))
return i;
int error_bits = (i >> lt->base_range_bits) - 1;
int base = 1 << (error_bits + lt->base_range_bits);
int k = i % base_val;
return base + ((k + 0.5) * (1 << error_bits));
}
/*
* Creates a subroot in the following manner:
* {
* "latstats" : {
* "type" : "write" or "read",
* "values" : {
*/
static void latency_tracker_populate_json_root(const struct latency_tracker *lt,
struct json_object *root)
{
struct json_object *subroot = json_create_object();
json_object_add_value_object(root, "latstats", subroot);
json_object_add_value_string(subroot, "type", lt->cfg.write ? "write" : "read");
if (lt->has_average_latency_field) {
json_object_add_value_uint64(subroot, "average_latency", le64_to_cpu(lt->stats.average_latency));
}
json_object_add_value_object(subroot, "values", lt->bucket_list);
}
static void latency_tracker_parse_3_0(const struct latency_tracker *lt)
{
latency_tracker_parse_linear(lt, 4, 131, 4, 32, false);
latency_tracker_parse_linear(lt, 132, 255, 4, 1024, false);
latency_tracker_parse_linear(lt, 256, 379, 4, 32768, false);
latency_tracker_parse_linear(lt, 380, 383, 4, 32, true);
latency_tracker_parse_linear(lt, 384, 387, 4, 32, true);
latency_tracker_parse_linear(lt, 388, 391, 4, 32, true);
}
static void latency_tracker_parse_4_0(const struct latency_tracker *lt)
{
for (unsigned int i = 0; i < lt->bucket_list_size; i++) {
int lower_us = latency_tracker_bucket_pos2us(lt, i);
int upper_us = latency_tracker_bucket_pos2us(lt, i + 1);
latency_tracker_bucket_parse(lt, i, lower_us,
upper_us,
i < (lt->bucket_list_size - 1));
}
}
static void print_dash_separator()
{
printf("--------------------------------------------------\n");
}
static void latency_tracker_pre_parse(struct latency_tracker *lt)
{
if (lt->print_flags == NORMAL) {
printf("Solidigm IO %s Command Latency Tracking Statistics type %d\n",
lt->cfg.write ? "Write" : "Read", lt->cfg.type);
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));
}
print_dash_separator();
printf("%-12s%-12s%-12s%-20s\n", "Bucket", "Start", "End", "Value");
print_dash_separator();
}
if (lt->print_flags == JSON) {
lt->bucket_list = json_object_new_array();
}
}
static void latency_tracker_post_parse(struct latency_tracker *lt)
{
if (lt->print_flags == JSON) {
struct json_object *root = json_create_object();
latency_tracker_populate_json_root(lt, root);
json_print_object(root, NULL);
json_free_object(root);
printf("\n");
}
}
static void latency_tracker_parse(struct latency_tracker *lt)
{
__u16 version_major = le16_to_cpu(lt->stats.version_major);
__u16 version_minor = le16_to_cpu(lt->stats.version_minor);
switch (version_major) {
case 3:
latency_tracker_pre_parse(lt);
latency_tracker_parse_3_0(lt);
break;
case 4:
if (version_minor >= 8){
lt->has_average_latency_field = true;
}
latency_tracker_pre_parse(lt);
if (version_minor == 0){
lt->base_range_bits = BASE_RANGE_BITS_4_0;
lt->bucket_list_size = BUCKET_LIST_SIZE_4_0;
}
latency_tracker_parse_4_0(lt);
break;
default:
printf("Unsupported revision (%u.%u)\n",
version_major, version_minor);
break;
}
latency_tracker_post_parse(lt);
}
#define LATENCY_TRACKING_FID 0xe2
#define LATENCY_TRACKING_FID_DATA_LEN 32
static int latency_tracking_is_enable(struct latency_tracker *lt, __u32 * enabled)
{
struct nvme_get_features_args args_get = {
.args_size = sizeof(args_get),
.fd = lt->fd,
.fid = LATENCY_TRACKING_FID,
.nsid = 0,
.sel = 0,
.cdw11 = 0,
.uuidx = 0,
.data_len = LATENCY_TRACKING_FID_DATA_LEN,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = enabled,
};
return nvme_get_features(&args_get);
}
static int latency_tracking_enable(struct latency_tracker *lt)
{
__u32 result;
int err;
if (!(lt->cfg.enable || lt->cfg.disable)){
return 0;
}
if (lt->cfg.enable && lt->cfg.disable){
fprintf(stderr,"Cannot enable and disable simultaneously.\n");
return EINVAL;
}
struct nvme_set_features_args args_set = {
.args_size = sizeof(args_set),
.fd = lt->fd,
.fid = LATENCY_TRACKING_FID,
.nsid = 0,
.cdw11 = lt->cfg.enable,
.cdw12 = 0,
.save = 0,
.uuidx = 0,
.cdw15 = 0,
.data_len = LATENCY_TRACKING_FID_DATA_LEN,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_set_features(&args_set);
if (err > 0) {
nvme_show_status(err);
} else if (err < 0) {
perror("Enable latency tracking");
fprintf(stderr, "Command failed while parsing.\n");
} else {
if (lt->print_flags == NORMAL) {
printf("Successfully set enable bit for FID (0x%X) to %i.\n",
LATENCY_TRACKING_FID, lt->cfg.enable);
}
}
return err;
}
#define READ_LOG_ID 0xc1
#define WRITE_LOG_ID 0xc2
static int latency_tracker_get_log(struct latency_tracker *lt)
{
int err;
if (lt->cfg.read && lt->cfg.write){
fprintf(stderr,"Cannot capture read and write logs simultaneously.\n");
return EINVAL;
}
if (!(lt->cfg.read || lt->cfg.write))
return 0;
struct nvme_get_log_args args = {
.lpo = 0,
.result = NULL,
.log = &lt->stats,
.args_size = sizeof(args),
.fd = lt->fd,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.lid = lt->cfg.write ? WRITE_LOG_ID : READ_LOG_ID,
.len = sizeof(lt->stats),
.nsid = NVME_NSID_ALL,
.csi = NVME_CSI_NVM,
.lsi = NVME_LOG_LSI_NONE,
.lsp = lt->cfg.type,
.uuidx = NVME_UUID_NONE,
.rae = false,
.ot = false,
};
err = nvme_get_log(&args);
if (err)
return err;
if (lt->print_flags & BINARY)
d_raw((unsigned char *)&lt->stats,
sizeof(lt->stats));
else {
latency_tracker_parse(lt);
}
return err;
}
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.";
__u32 enabled;
int err;
struct latency_tracker lt = {
.cfg = {
.output_format = "normal",
},
.base_range_bits = BASE_RANGE_BITS_4_1,
.bucket_list_size = BUCKET_LIST_SIZE_4_1,
.has_average_latency_field = false,
};
OPT_ARGS(opts) = {
OPT_FLAG("enable", 'e', &lt.cfg.enable, "Enable Latency Tracking"),
OPT_FLAG("disable", 'd', &lt.cfg.disable, "Disable Latency Tracking"),
OPT_FLAG("read", 'r', &lt.cfg.read, "Get read statistics"),
OPT_FLAG("write", 'w', &lt.cfg.write, "Get write statistics"),
OPT_BYTE("type", 't', &lt.cfg.type, "Log type to get"),
OPT_FMT("output-format", 'o', &lt.cfg.output_format, output_format),
OPT_END()
};
lt.fd = parse_and_open(argc, argv, desc, opts);
if (lt.fd < 0)
return lt.fd;
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);
return EINVAL;
}
if (lt.cfg.type > 0xf) {
fprintf(stderr, "Invalid Log type value '%d'\n", lt.cfg.type);
close(lt.fd);
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);
return EINVAL;
}
err = latency_tracking_enable(&lt);
if (err){
close(lt.fd);
return err;
}
err = latency_tracker_get_log(&lt);
if (err){
close(lt.fd);
return err;
}
if ((lt.cfg.read || lt.cfg.write || lt.cfg.enable || lt.cfg.disable)) {
close(lt.fd);
return 0;
}
err = latency_tracking_is_enable(&lt, &enabled);
if (!err) {
if (lt.print_flags == JSON) {
struct json_object *root = json_create_object();
json_object_add_value_int(root,"enabled", enabled);
json_print_object(root, NULL);
json_free_object(root);
printf("\n");
} else if (lt.print_flags == BINARY) {
putchar(enabled);
} else {
printf(
"Latency Statistics Tracking (FID 0x%X) is currently (%i).\n",
LATENCY_TRACKING_FID, enabled);
}
} else {
fprintf(stderr, "Could not read feature id 0xE2.\n");
}
close(lt.fd);
return err;
}

View file

@ -0,0 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022 Solidigm.
*
* Author: leonardo.da.cunha@solidigm.com
*/
int solidigm_get_latency_tracking_log(int argc, char **argv, struct command *cmd,
struct plugin *plugin);

View file

@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022 Solidigm.
*
* Author: leonardo.da.cunha@solidigm.com
*/
#include "nvme.h"
#define CREATE_CMD
#include "solidigm-nvme.h"
#include "solidigm-smart.h"
#include "solidigm-garbage-collection.h"
#include "solidigm-latency-tracking.h"
static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
return solidigm_get_additional_smart_log(argc, argv, cmd, plugin);
}
static int get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
return solidigm_get_garbage_collection_log(argc, argv, cmd, plugin);
}
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);
}

View file

@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2022 Solidigm.
*
* Author: leonardo.da.cunha@solidigm.com
*/
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/solidigm/solidigm-nvme
#if !defined(SOLIDIGM_NVME) || defined(CMD_HEADER_MULTI_READ)
#define SOLIDIGM_NVME
#include "cmd.h"
#define SOLIDIGM_PLUGIN_VERSION "0.4"
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)
)
);
#endif
#include "define_cmd.h"

View file

@ -0,0 +1,250 @@
// 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 <inttypes.h>
#include <endian.h>
#include "common.h"
#include "nvme.h"
#include "libnvme.h"
#include "plugin.h"
#include "linux/types.h"
#include "nvme-print.h"
#include "solidigm-smart.h"
struct __attribute__((packed)) nvme_additional_smart_log_item {
__u8 id;
__u8 _kp[2];
__u8 normalized;
__u8 _np;
union __attribute__((packed)) {
__u8 raw[6];
struct __attribute__((packed)) wear_level {
__le16 min;
__le16 max;
__le16 avg;
} wear_level;
struct __attribute__((packed)) thermal_throttle {
__u8 pct;
__u32 count;
} thermal_throttle;
} ;
__u8 _rp;
} ;
typedef struct nvme_additional_smart_log_item smart_log_item_t;
#define VU_SMART_PAGE_SIZE 512
#define VU_SMART_MAX_ITEMS VU_SMART_PAGE_SIZE / sizeof(smart_log_item_t)
typedef struct vu_smart_log {
smart_log_item_t item[VU_SMART_MAX_ITEMS];
} vu_smart_log_t;
static char *id_to_name(__u8 id)
{
switch (id) {
case 0x0D:
return "soft_ecc_error_rate";
case 0x05:
return "relocatable_sector_count";
case 0xAB:
return "program_fail_count";
case 0xAC:
return "erase_fail_count";
case 0xAD:
return "wear_leveling_count";
case 0xAE:
return "unexpected_power_loss";
case 0xB8:
return "e2e_error_detect_count";
case 0xC7:
return "crc_error_count";
case 0xE2:
return "media_wear_percentage";
case 0xE3:
return "host_reads";
case 0xE4:
return "timed_work_load";
case 0xE5:
return "read_commands_in_flight_counter";
case 0xE6:
return "write_commands_in_flight_counter";
case 0xEA:
return "thermal_throttle_status";
case 0xF0:
return "retry_buffer_overflow_counter";
case 0xF3:
return "pll_lock_loss_counter";
case 0xF4:
return "nand_bytes_written";
case 0xF5:
return "host_bytes_written";
case 0xF6:
return "host_context_wear_used";
case 0xF7:
return "performance_status_indicator";
case 0xF8:
return "media_bytes_read";
case 0xF9:
return "available_fw_downgrades";
case 0xFA:
return "host_read_collision_count";
case 0xFB:
return "host_write_collision_count";
case 0xFC:
return "xor_pass_count";
case 0xFD:
return "xor_fail_count";
case 0xFE:
return "xor_invoked_count";
default:
return "unknown";
}
}
static void smart_log_item_print(smart_log_item_t *item)
{
if (!item->id) {
return;
}
printf("%#x %-45s %3d ",
item->id, id_to_name(item->id), item->normalized);
switch (item->id) {
case 0xAD:
printf("min: %u, max: %u, avg: %u\n",
le16_to_cpu(item->wear_level.min),
le16_to_cpu(item->wear_level.max),
le16_to_cpu(item->wear_level.avg));
return;
case 0xEA:
printf("%u%%, cnt: %u\n",
item->thermal_throttle.pct,
le32_to_cpu(item->thermal_throttle.count));
return;
default:
printf("%"PRIu64"\n", int48_to_long(item->raw));
}
}
static void smart_log_item_add_json(smart_log_item_t *item, struct json_object *dev_stats)
{
struct json_object *entry_stats = json_create_object();
if (!item->id) {
return;
}
json_object_add_value_int(entry_stats, "normalized", item->normalized);
switch (item->id) {
case 0xAD:
json_object_add_value_int(entry_stats, "min", le16_to_cpu(item->wear_level.min));
json_object_add_value_int(entry_stats, "max", le16_to_cpu(item->wear_level.max));
json_object_add_value_int(entry_stats, "avg", le16_to_cpu(item->wear_level.avg));
break;
case 0xEA:
json_object_add_value_int(entry_stats, "percentage", item->thermal_throttle.pct);
json_object_add_value_int(entry_stats, "count", le32_to_cpu(item->thermal_throttle.count));
break;
default:
json_object_add_value_int(entry_stats, "raw", int48_to_long(item->raw));
}
json_object_add_value_object(dev_stats, id_to_name(item->id), entry_stats);
}
static void vu_smart_log_show_json(vu_smart_log_t *payload, unsigned int nsid, const char *devname)
{
struct json_object *dev_stats = json_create_object();
smart_log_item_t *item = payload->item;
struct json_object *root;
for (int i = 0; i < VU_SMART_MAX_ITEMS; i++) {
smart_log_item_add_json(&item[i], dev_stats);
}
root = json_create_object();
json_object_add_value_string(root, "Solidigm SMART log", devname);
json_object_add_value_object(root, "Device stats", dev_stats);
json_print_object(root, NULL);
json_free_object(root);
}
static void vu_smart_log_show(vu_smart_log_t *payload, unsigned int nsid, const char *devname)
{
smart_log_item_t *item = payload->item;
printf("Additional Smart Log for NVME device:%s namespace-id:%x\n",
devname, nsid);
printf("ID KEY Normalized Raw\n");
for (int i = 0; i < VU_SMART_MAX_ITEMS; i++) {
smart_log_item_print(&item[i]);
}
}
int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Get Solidigm vendor specific smart log (optionally, "\
"for the specified namespace), and show it.";
const int solidigm_vu_smart_log_id = 0xCA;
vu_smart_log_t smart_log_payload;
enum nvme_print_flags flags;
int fd, err;
struct config {
__u32 namespace_id;
char *output_format;
};
struct config cfg = {
.namespace_id = NVME_NSID_ALL,
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, "(optional) desired namespace"),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {
return fd;
}
flags = validate_output_format(cfg.output_format);
if (flags == -EINVAL) {
fprintf(stderr, "Invalid output format '%s'\n", cfg.output_format);
close(fd);
return fd;
}
err = nvme_get_log_simple(fd, 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);
} 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);
}
} else if (err > 0) {
nvme_show_status(err);
}
close(fd);
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_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin);

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -148,6 +149,7 @@ static int nvme_sct_command_transfer_log(int fd, bool current)
memcpy(data + 2, &function_code, sizeof(function_code));
err = nvme_sct_op(fd, OP_SCT_COMMAND_TRANSFER, DW10_SCT_COMMAND_TRANSFER, DW11_SCT_COMMAND_TRANSFER, data, data_len);
free(data);
return err;
}
@ -474,6 +476,7 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin
end:
if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -517,6 +520,7 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi
if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}
@ -569,5 +573,6 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd,
end:
if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/toshiba/toshiba-nvme

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -49,7 +50,7 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu
}
}
close(fd);
return result;
}
@ -83,6 +84,6 @@ static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin
int badblock = data[0];
printf("Transcend NVME badblock count: %d\n",badblock);
}
close(fd);
return result;
}

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/transcend/transcend-nvme

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -132,7 +133,7 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l
setlocale(LC_ALL, "C");
long long int lba = 1 << smart->raw_ns.lbaf[lba_index].ds;
unsigned long long int lba = 1ULL << smart->raw_ns.lbaf[lba_index].ds;
capacity = le64_to_cpu(smart->raw_ns.nsze) * lba;
snprintf(tempbuff, sizeof(tempbuff), "log;%s;%lu;%s;%s;%-.*s;", smart->raw_ctrl.sn, smart->time_stamp, smart->path,
@ -270,16 +271,16 @@ static void vt_process_string(char *str, const size_t size)
static int vt_add_entry_to_log(const int fd, const char *path, const struct vtview_save_log_settings *cfg)
{
struct vtview_smart_log_entry smart;
char filename[256] = "";
const char *filename;
int ret = 0;
unsigned nsid = 0;
memset(smart.path, 0, sizeof(smart.path));
strcpy(smart.path, path);
strncpy(smart.path, path, sizeof(smart.path) - 1);
if(NULL == cfg->output_file)
strcpy(filename, vt_default_log_file_name);
filename = vt_default_log_file_name;
else
strcpy(filename, cfg->output_file);
filename = cfg->output_file;
smart.time_stamp = time(NULL);
ret = nvme_get_nsid(fd, &nsid);
@ -317,21 +318,32 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
static int vt_update_vtview_log_header(const int fd, const char *path, const struct vtview_save_log_settings *cfg)
{
struct vtview_log_header header;
char filename[256] = "";
const char *filename;
int ret = 0;
vt_initialize_header_buffer(&header);
if (strlen(path) > sizeof(header.path)) {
printf("filename too long\n");
errno = EINVAL;
return -1;
}
strcpy(header.path, path);
if (NULL == cfg->test_name)
strcpy(header.test_name, DEFAULT_TEST_NAME);
else
else {
if (strlen(cfg->test_name) > sizeof(header.test_name)) {
printf("test name too long\n");
errno = EINVAL;
return -1;
}
strcpy(header.test_name, cfg->test_name);
}
if(NULL == cfg->output_file)
strcpy(filename, vt_default_log_file_name);
filename = vt_default_log_file_name;
else
strcpy(filename, cfg->output_file);
filename = cfg->output_file;
printf("Log file: %s\n", filename);
header.time_stamp = time(NULL);
@ -955,8 +967,13 @@ static int vt_save_smart_to_vtview_log(int argc, char **argv, struct command *cm
vt_generate_vtview_log_file_name(vt_default_log_file_name);
if (argc >= 2)
if (argc >= 2) {
if (strlen(argv[1]) > sizeof(path) - 1) {
printf("Filename too long\n");
return -1;
}
strcpy(path, argv[1]);
}
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) {

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/virtium/virtium-nvme

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/wdc/wdc-nvme
#if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ)
#define WDC_NVME
#define WDC_PLUGIN_VERSION "1.16.4"
#define WDC_PLUGIN_VERSION "2.0.3"
#include "cmd.h"
PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),
@ -40,6 +41,10 @@ PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERS
ENTRY("get-error-recovery-log", "WDC Get Error Recovery Log Page", wdc_get_error_recovery_log)
ENTRY("get-dev-capabilities-log", "WDC Get Device Capabilities Log Page", wdc_get_dev_capabilities_log)
ENTRY("get-unsupported-reqs-log", "WDC Get Unsupported Requirements Log Page", wdc_get_unsupported_reqs_log)
ENTRY("cloud-boot-SSD-version", "WDC Get the Cloud Boot SSD Version", wdc_cloud_boot_SSD_version)
ENTRY("vs-cloud-log", "WDC Get the Cloud Log Page", wdc_vs_cloud_log)
ENTRY("vs-hw-rev-log", "WDC Get the Hardware Revision Log Page", wdc_vs_hw_rev_log)
ENTRY("vs-device-waf", "WDC Calculate Device Write Amplication Factor", wdc_vs_device_waf)
)
);

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2017-2018 Western Digital Corporation or its affiliates.
*

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2017-2018 Western Digital Corporation or its affiliates.
*

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -30,9 +31,21 @@ static int show_ymtc_smart_log(int fd, __u32 nsid, const char *devname,
u8 *nm = malloc(NM_SIZE * sizeof(u8));
u8 *raw = malloc(RAW_SIZE * sizeof(u8));
if (!nm) {
if (raw)
free(raw);
return -1;
}
if (!raw) {
free(nm);
return -1;
}
err = nvme_identify_ctrl(fd, &ctrl);
if (err)
if (err) {
free(nm);
free(raw);
return err;
}
snprintf(fw_ver, sizeof(fw_ver), "%c.%c%c.%c%c%c%c",
ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3],
@ -51,17 +64,17 @@ static int show_ymtc_smart_log(int fd, __u32 nsid, const char *devname,
/* 02 SI_VD_WEARLEVELING_COUNT */
get_ymtc_smart_info(smart, SI_VD_WEARLEVELING_COUNT, nm, raw);
printf("wear_leveling : %3d%% min: %u, max: %u, avg: %u\n", *nm,
*raw, *(raw+2), *(raw+4));
*(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4));
/* 03 SI_VD_E2E_DECTECTION_COUNT */
get_ymtc_smart_info(smart, SI_VD_E2E_DECTECTION_COUNT, nm, raw);
printf("end_to_end_error_detection_count: %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
/* 04 SI_VD_PCIE_CRC_ERR_COUNT */
get_ymtc_smart_info(smart, SI_VD_PCIE_CRC_ERR_COUNT, nm, raw);
printf("crc_error_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
printf("crc_error_count : %3d%% %"PRIu32"\n", *nm, *(uint32_t *)raw);
/* 08 SI_VD_THERMAL_THROTTLE_STATUS */
get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_STATUS, nm, raw);
printf("thermal_throttle_status : %3d%% %"PRIu64"%%, cnt: %"PRIu64"\n", *nm,
int48_to_long(raw), int48_to_long(raw+1));
printf("thermal_throttle_status : %3d%% %d%%, cnt: %"PRIu32"\n", *nm,
*raw, *(uint32_t *)(raw+1));
/* 11 SI_VD_TOTAL_WRITE */
get_ymtc_smart_info(smart, SI_VD_TOTAL_WRITE, nm, raw);
printf("nand_bytes_written : %3d%% sectors: %"PRIu64"\n", *nm, int48_to_long(raw));
@ -74,15 +87,15 @@ static int show_ymtc_smart_log(int fd, __u32 nsid, const char *devname,
/* 15 SI_VD_TEMPT_SINCE_BORN */
get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BORN, nm, raw);
printf("tempt_since_born : %3d%% max: %u, min: %u, curr: %u\n", *nm,
*raw, *(raw+2), *(raw+4));
*(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(int16_t *)(raw+4)-273);
/* 16 SI_VD_POWER_CONSUMPTION */
get_ymtc_smart_info(smart, SI_VD_POWER_CONSUMPTION, nm, raw);
printf("power_consumption : %3d%% max: %u, min: %u, curr: %u\n", *nm,
*raw, *(raw+2), *(raw+4));
*(uint16_t *)raw, *(uint16_t *)(raw+2), *(uint16_t *)(raw+4));
/* 17 SI_VD_TEMPT_SINCE_BOOTUP */
get_ymtc_smart_info(smart, SI_VD_TEMPT_SINCE_BOOTUP, nm, raw);
printf("tempt_since_bootup : %3d%% max: %u, min: %u, curr: %u\n", *nm, *raw,
*(raw+2), *(raw+4));
printf("tempt_since_bootup : %3d%% max: %u, min: %u, curr: %u\n", *nm,
*(uint16_t *)raw-273, *(uint16_t *)(raw+2)-273, *(uint16_t *)(raw+4)-273);
/* 18 SI_VD_POWER_LOSS_PROTECTION */
get_ymtc_smart_info(smart, SI_VD_POWER_LOSS_PROTECTION, nm, raw);
printf("power_loss_protection : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
@ -91,7 +104,8 @@ static int show_ymtc_smart_log(int fd, __u32 nsid, const char *devname,
printf("read_fail : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
/* 20 SI_VD_THERMAL_THROTTLE_TIME */
get_ymtc_smart_info(smart, SI_VD_THERMAL_THROTTLE_TIME, nm, raw);
printf("thermal_throttle_time : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
printf("thermal_throttle_time : %3d%% %u, time: %"PRIu32"\n", *nm,
*raw, *(uint32_t *)(raw+1));
/* 21 SI_VD_FLASH_MEDIA_ERROR */
get_ymtc_smart_info(smart, SI_VD_FLASH_MEDIA_ERROR, nm, raw);
printf("flash_error_media_count : %3d%% %"PRIu64"\n", *nm, int48_to_long(raw));
@ -140,5 +154,6 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
if (err > 0)
nvme_show_status(err);
close(fd);
return err;
}

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/ymtc/ymtc-nvme

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef __YMTC_UTILS_H__
#define __YMTC_UTILS_H__

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
@ -102,13 +103,12 @@ static int list(int argc, char **argv, struct command *cmd,
nvme_root = nvme_scan(NULL);
if (nvme_root) {
err = print_zns_list(nvme_root);
nvme_free_tree(nvme_root);
} else {
fprintf(stderr, "Failed to scan nvme subsystems\n");
err = -errno;
}
nvme_free_tree(nvme_root);
return err;
}
@ -1018,9 +1018,9 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
const char *fua = "force unit access";
const char *prinfo = "protection information action and checks field";
const char *piremap = "protection information remap (for type 1 PI)";
const char *ref_tag = "reference tag (for end to end PI)";
const char *lbat = "logical block application tag (for end to end PI)";
const char *lbatm = "logical block application tag mask (for end to end PI)";
const char *ref_tag = "reference tag for end-to-end PI";
const char *lbat = "logical block application tag for end-to-end PI";
const char *lbatm = "logical block application tag mask for end-to-end PI";
const char *metadata_size = "size of metadata in bytes";
const char *data_size = "size of data in bytes";
const char *latency = "output latency statistics";
@ -1044,7 +1044,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
bool limited_retry;
bool fua;
__u32 namespace_id;
__u32 ref_tag;
__u64 ref_tag;
__u16 lbat;
__u16 lbatm;
__u8 prinfo;
@ -1063,7 +1063,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
OPT_FILE("metadata", 'M', &cfg.metadata, metadata),
OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry),
OPT_FLAG("force-unit-access", 'f', &cfg.fua, fua),
OPT_UINT("ref-tag", 'r', &cfg.ref_tag, ref_tag),
OPT_SUFFIX("ref-tag", 'r', &cfg.ref_tag, ref_tag),
OPT_SHRT("app-tag-mask", 'm', &cfg.lbatm, lbatm),
OPT_SHRT("app-tag", 'a', &cfg.lbat, lbat),
OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo),
@ -1184,7 +1184,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
.zslba = cfg.zslba,
.nlb = nblocks,
.control = control,
.ilbrt = cfg.ref_tag,
.ilbrt_u64 = cfg.ref_tag,
.lbat = cfg.lbat,
.lbatm = cfg.lbatm,
.data_len = cfg.data_size,

View file

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/zns/zns