Merging upstream version 2.1~rc0 (Closes: #1015722).
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
9489161ac8
commit
316e846c86
504 changed files with 6751 additions and 2957 deletions
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -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
54
plugins/dell/dell-nvme.c
Normal 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
18
plugins/dell/dell-nvme.h
Normal 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"
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/dera/dera-nvme
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/huawei/huawei-nvme
|
||||
|
||||
|
|
402
plugins/innogrit/innogrit-nvme.c
Normal file
402
plugins/innogrit/innogrit-nvme.c
Normal 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;
|
||||
}
|
20
plugins/innogrit/innogrit-nvme.h
Normal file
20
plugins/innogrit/innogrit-nvme.h
Normal 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"
|
72
plugins/innogrit/typedef.h
Normal file
72
plugins/innogrit/typedef.h
Normal 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];
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/intel/intel-nvme
|
||||
|
||||
|
|
|
@ -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, ¶m1, ¶m2)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/memblaze/memblaze-nvme
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/micron/micron-nvme
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/netapp/netapp-nvme
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/nvidia/nvidia-nvme
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/scaleflux/sfx-nvme
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Do NOT modify or remove this copyright and license
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Do NOT modify or remove this copyright and license
|
||||
*
|
||||
|
|
|
@ -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 "\
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/shannon/shannon-nvme
|
||||
|
||||
|
|
5
plugins/solidigm/meson.build
Normal file
5
plugins/solidigm/meson.build
Normal file
|
@ -0,0 +1,5 @@
|
|||
sources += [
|
||||
'plugins/solidigm/solidigm-smart.c',
|
||||
'plugins/solidigm/solidigm-garbage-collection.c',
|
||||
'plugins/solidigm/solidigm-latency-tracking.c',
|
||||
]
|
111
plugins/solidigm/solidigm-garbage-collection.c
Normal file
111
plugins/solidigm/solidigm-garbage-collection.c
Normal 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;
|
||||
}
|
8
plugins/solidigm/solidigm-garbage-collection.h
Normal file
8
plugins/solidigm/solidigm-garbage-collection.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
int solidigm_get_garbage_collection_log(int argc, char **argv, struct command *cmd, struct plugin *plugin);
|
470
plugins/solidigm/solidigm-latency-tracking.c
Normal file
470
plugins/solidigm/solidigm-latency-tracking.c
Normal 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 = <->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 *)<->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', <.cfg.enable, "Enable Latency Tracking"),
|
||||
OPT_FLAG("disable", 'd', <.cfg.disable, "Disable Latency Tracking"),
|
||||
OPT_FLAG("read", 'r', <.cfg.read, "Get read statistics"),
|
||||
OPT_FLAG("write", 'w', <.cfg.write, "Get write statistics"),
|
||||
OPT_BYTE("type", 't', <.cfg.type, "Log type to get"),
|
||||
OPT_FMT("output-format", 'o', <.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(<);
|
||||
if (err){
|
||||
close(lt.fd);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = latency_tracker_get_log(<);
|
||||
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(<, &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;
|
||||
}
|
9
plugins/solidigm/solidigm-latency-tracking.h
Normal file
9
plugins/solidigm/solidigm-latency-tracking.h
Normal 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);
|
30
plugins/solidigm/solidigm-nvme.c
Normal file
30
plugins/solidigm/solidigm-nvme.c
Normal 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);
|
||||
}
|
28
plugins/solidigm/solidigm-nvme.h
Normal file
28
plugins/solidigm/solidigm-nvme.h
Normal 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"
|
250
plugins/solidigm/solidigm-smart.c
Normal file
250
plugins/solidigm/solidigm-smart.c
Normal 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;
|
||||
}
|
||||
|
8
plugins/solidigm/solidigm-smart.h
Normal file
8
plugins/solidigm/solidigm-smart.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Author: leonardo.da.cunha@solidigm.com
|
||||
*/
|
||||
|
||||
int solidigm_get_additional_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin);
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/toshiba/toshiba-nvme
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/transcend/transcend-nvme
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
@ -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)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2017-2018 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2017-2018 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/ymtc/ymtc-nvme
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#ifndef __YMTC_UTILS_H__
|
||||
#define __YMTC_UTILS_H__
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#undef CMD_INC_FILE
|
||||
#define CMD_INC_FILE plugins/zns/zns
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue