1
0
Fork 0

Merging upstream version 2.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-16 12:15:45 +01:00
parent 888be815c6
commit e4376063b0
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
521 changed files with 21541 additions and 21644 deletions

View file

@ -5,17 +5,11 @@
#include <unistd.h>
#include <inttypes.h>
#include "linux/nvme_ioctl.h"
#include "common.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#define CREATE_CMD
#include "amzn-nvme.h"

View file

@ -10,12 +10,10 @@
#include <sys/time.h>
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#include "linux/types.h"
#include "nvme-print.h"
#define CREATE_CMD
#include "dera-nvme.h"
@ -108,7 +106,7 @@ static int nvme_dera_get_device_status(int fd, enum dera_device_status *result)
.cdw12 = 0x104,
};
err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &cmd);
err = nvme_submit_admin_passthru(fd, &cmd, NULL);
if (!err && result) {
*result = cmd.result;
}
@ -131,8 +129,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin
if (fd < 0)
return fd;
err = nvme_get_log(fd, 0xffffffff, 0xc0, false, NVME_NO_LOG_LSP,
sizeof(log), &log);
err = nvme_get_log_simple(fd, 0xc0, sizeof(log), &log);
if (err) {
goto exit;
}
@ -189,7 +186,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 >= 0 && 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{
@ -205,7 +202,7 @@ static int get_status(int argc, char **argv, struct command *cmd, struct plugin
exit:
if (err > 0)
fprintf(stderr, "\nNVMe status:%s(0x%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}

View file

@ -26,16 +26,12 @@
#include <sys/stat.h>
#include "linux/nvme_ioctl.h"
#include "common.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#include <sys/ioctl.h>
#include "util/suffix.h"
#define CREATE_CMD
#include "huawei-nvme.h"
@ -50,7 +46,7 @@
struct huawei_list_item {
char node[1024];
struct nvme_id_ctrl ctrl;
int nsid;
unsigned nsid;
struct nvme_id_ns ns;
unsigned block;
char ns_name[NS_NAME_LEN];
@ -87,8 +83,8 @@ static int huawei_get_nvme_info(int fd, struct huawei_list_item *item, const cha
}
item->huawei_device = true;
item->nsid = nvme_get_nsid(fd);
err = nvme_identify_ns(fd, item->nsid, 0, &item->ns);
err = nvme_get_nsid(fd, &item->nsid);
err = nvme_identify_ns(fd, item->nsid, &item->ns);
if (err)
return err;
@ -211,7 +207,9 @@ static void huawei_print_list_head(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)
{
long long int lba = 1 << list_item.ns.lbaf[(list_item.ns.flbas & 0x0f)].ds;
__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;
@ -320,7 +318,7 @@ static int huawei_list(int argc, char **argv, struct command *command,
if (fmt != JSON && fmt != NORMAL)
return -EINVAL;
n = scandir("/dev", &devices, scan_namespace_filter, alphasort);
n = scandir("/dev", &devices, nvme_namespace_filter, alphasort);
if (n <= 0)
return n;

View file

@ -5,16 +5,12 @@
#include <unistd.h>
#include <inttypes.h>
#include "linux/nvme_ioctl.h"
#include "common.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#include "linux/types.h"
#include "nvme-print.h"
#define CREATE_CMD
#include "intel-nvme.h"
@ -351,8 +347,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
struct config {
__u32 namespace_id;
int raw_binary;
int json;
bool raw_binary;
bool json;
};
struct config cfg = {
@ -370,8 +366,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
if (fd < 0)
return fd;
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
err = nvme_get_log_simple(fd, 0xca, sizeof(smart_log), &smart_log);
if (!err) {
if (cfg.json)
show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, devicename);
@ -381,8 +376,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -395,7 +389,7 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu
int err, fd;
struct config {
int raw_binary;
bool raw_binary;
};
struct config cfg = {
@ -410,16 +404,14 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu
if (fd < 0)
return fd;
err = nvme_get_log(fd, NVME_NSID_ALL, 0xdd, false,
NVME_NO_LOG_LSP, sizeof(log), log);
err = nvme_get_log_simple(fd, 0xdd, sizeof(log), log);
if (!err) {
if (!cfg.raw_binary)
printf("Intel Marketing Name Log:\n%s\n", log);
else
d_raw((unsigned char *)&log, sizeof(log));
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -457,7 +449,7 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct
const char *desc = "Get Temperature Statistics log and show it.";
const char *raw = "dump output in binary format";
struct config {
int raw_binary;
bool raw_binary;
};
struct config cfg = {
@ -472,16 +464,14 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct
if (fd < 0)
return fd;
err = nvme_get_log(fd, NVME_NSID_ALL, 0xc5, false,
NVME_NO_LOG_LSP, sizeof(stats), &stats);
err = nvme_get_log_simple(fd, 0xc5, sizeof(stats), &stats);
if (!err) {
if (!cfg.raw_binary)
show_temp_stats(&stats);
else
d_raw((unsigned char *)&stats, sizeof(stats));
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -497,10 +487,13 @@ struct __attribute__((__packed__)) optane_lat_stats {
__u64 data[9];
};
#define MEDIA_MAJOR_IDX 0
#define MEDIA_MINOR_IDX 1
#define MEDIA_MAX_LEN 2
#define OPTANE_V1000_BUCKET_LEN 8
#define MEDIA_MAJOR_IDX 0
#define MEDIA_MINOR_IDX 1
#define MEDIA_MAX_LEN 2
#define OPTANE_V1000_BUCKET_LEN 8
#define OPTANE_V1000_BUCKET_LEN 8
#define NAND_LAT_STATS_LEN 4868
static struct intel_lat_stats stats;
static struct optane_lat_stats v1000_stats;
@ -529,7 +522,7 @@ enum FormatUnit {
#define US_IN_S 1000000
#define US_IN_MS 1000
static const enum FormatUnit get_seconds_magnitude(__u32 microseconds)
static enum FormatUnit get_seconds_magnitude(__u32 microseconds)
{
if (microseconds > US_IN_S)
return S;
@ -539,7 +532,7 @@ static const enum FormatUnit get_seconds_magnitude(__u32 microseconds)
return US;
}
static const float convert_seconds(__u32 microseconds)
static float convert_seconds(__u32 microseconds)
{
float divisor = 1.0;
@ -567,13 +560,15 @@ enum inf_bound_type {
* either of "-INF" or "+INF", respectively.
*/
static void set_unit_string(char *buffer, __u32 microseconds,
enum FormatUnit unit, enum inf_bound_type bound_type)
enum FormatUnit unit,
enum inf_bound_type bound_type)
{
char *string;
if (bound_type != NOINF) {
snprintf(buffer, 5, "%s", bound_type ? "+INF" : "-INF");
snprintf(buffer, BUFSIZE, "%s", bound_type ? "+INF" : "-INF");
return;
}
char *string;
switch (unit) {
case US:
@ -589,8 +584,9 @@ static void set_unit_string(char *buffer, __u32 microseconds,
string = "_s";
break;
}
snprintf(buffer, 11, "%4.2f%s",
convert_seconds(microseconds), string);
snprintf(buffer, BUFSIZE, "%4.2f%s", convert_seconds(microseconds),
string);
}
static void init_buffer(char *buffer, size_t size)
@ -660,12 +656,11 @@ static void show_lat_stats_linear(struct intel_lat_stats *stats,
/*
* For 4.0-4.5 revision.
*/
#define LATENCY_STATS_V4_BASE_BITS 6
#define LATENCY_STATS_V4_BASE_VAL (1 << LATENCY_STATS_V4_BASE_BITS)
static int lat_stats_log_scale(int i)
{
static const int LATENCY_STATS_V4_BASE_BITS = 6;
static const int LATENCY_STATS_V4_BASE_VAL = (
1 << LATENCY_STATS_V4_BASE_BITS);
// if (i < 128)
if (i < (LATENCY_STATS_V4_BASE_VAL << 1))
return i;
@ -715,8 +710,7 @@ static void json_add_bucket(struct intel_lat_stats *stats,
init_buffer(buffer, BUFSIZE);
json_object_add_value_object(bucket_list,
"bucket", bucket);
json_object_array_add(bucket_list, bucket);
json_object_add_value_int(bucket, "id", id);
set_unit_string(buffer, lower_us,
@ -739,8 +733,7 @@ static void json_add_bucket_optane(struct json_object *bucket_list, __u32 id,
init_buffer(buffer, BUFSIZE);
json_object_add_value_object(bucket_list,
"bucket", bucket);
json_object_array_add(bucket_list, bucket);
json_object_add_value_int(bucket, "id", id);
set_unit_string(buffer, lower_us,
@ -775,7 +768,7 @@ static void json_lat_stats_3_0(struct intel_lat_stats *stats,
int write)
{
struct json_object *root = json_create_object();
struct json_object *bucket_list = json_create_object();
struct json_object *bucket_list = json_object_new_array();
lat_stats_make_json_root(root, bucket_list, write);
@ -794,7 +787,7 @@ static void json_lat_stats_4_0(struct intel_lat_stats *stats,
int write)
{
struct json_object *root = json_create_object();
struct json_object *bucket_list = json_create_object();
struct json_object *bucket_list = json_object_new_array();
lat_stats_make_json_root(root, bucket_list, write);
@ -847,11 +840,11 @@ static void show_lat_stats_4_0(struct intel_lat_stats *stats)
}
}
static void jason_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
static void json_lat_stats_v1000_0(struct optane_lat_stats *stats, int write)
{
int i;
struct json_object *root = json_create_object();
struct json_object *bucket_list = json_create_object();
struct json_object *bucket_list = json_object_new_array();
lat_stats_make_json_root(root, bucket_list, write);
@ -951,7 +944,7 @@ static void json_lat_stats(int write)
case 1000:
switch (media_version[MEDIA_MINOR_IDX]) {
case 0:
jason_lat_stats_v1000_0(&v1000_stats, write);
json_lat_stats_v1000_0(&v1000_stats, write);
break;
default:
printf("Unsupported minor revision (%u.%u)\n",
@ -998,6 +991,7 @@ static void show_lat_stats(int write)
case 3:
case 4:
case 5:
case 6:
show_lat_stats_4_0(&stats);
break;
default:
@ -1028,6 +1022,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
{
int err, fd;
__u8 data[NAND_LAT_STATS_LEN];
const char *desc = "Get Intel Latency Statistics log and show it.";
const char *raw = "Dump output in binary format";
@ -1035,9 +1030,9 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
const char *write = "Get write statistics (read default)";
struct config {
int raw_binary;
int json;
int write;
bool raw_binary;
bool json;
bool write;
};
struct config cfg = {
@ -1054,10 +1049,15 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
if (fd < 0)
return fd;
/* Query maj and minor version first */
err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1,
false, NVME_NO_LOG_LSP, sizeof(media_version),
media_version);
/* For optate, latency stats are deleted every time their LID is pulled.
* Therefore, we query the longest lat_stats log page first.
*/
err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1,
sizeof(data), &data);
media_version[0] = (data[1] << 8) | data[0];
media_version[1] = (data[3] << 8) | data[2];
if (err)
goto close_fd;
@ -1065,11 +1065,23 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
__u32 thresholds[OPTANE_V1000_BUCKET_LEN] = {0};
__u32 result;
err = nvme_get_feature(fd, 0, 0xf7, 0, cfg.write ? 0x1 : 0x0, 0,
sizeof(thresholds), thresholds, &result);
struct nvme_get_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = 0xf7,
.nsid = 0,
.sel = 0,
.cdw11 = cfg.write ? 0x1 : 0x0,
.uuidx = 0,
.data_len = sizeof(thresholds),
.data = thresholds,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_get_features(&args);
if (err) {
fprintf(stderr, "Quering thresholds failed. NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
fprintf(stderr, "Quering thresholds failed. ");
nvme_show_status(err);
goto close_fd;
}
@ -1083,13 +1095,14 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
}
err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1,
false, NVME_NO_LOG_LSP, sizeof(v1000_stats),
&v1000_stats);
/* Move counter values to optate stats struct which has a
* smaller size
*/
memcpy(&v1000_stats, (struct optane_lat_stats *)data,
sizeof(struct optane_lat_stats));
} else {
err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1,
false, NVME_NO_LOG_LSP, sizeof(stats),
&stats);
memcpy(&stats, (struct intel_lat_stats *)data,
sizeof(struct intel_lat_stats));
}
if (!err) {
@ -1097,11 +1110,16 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
json_lat_stats(cfg.write);
else if (!cfg.raw_binary)
show_lat_stats(cfg.write);
else
d_raw((unsigned char *)&stats, sizeof(stats));
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)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
close_fd:
close(fd);
return err;
@ -1213,7 +1231,7 @@ static int read_entire_cmd(struct nvme_passthru_cmd *cmd, int total_size,
dword_tfer = min(max_tfer, total_size);
while (total_size > 0) {
err = nvme_submit_admin_passthru(ioctl_fd, cmd);
err = nvme_submit_admin_passthru(ioctl_fd, cmd, NULL);
if (err) {
fprintf(stderr,
"failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n",
@ -1478,8 +1496,7 @@ static int get_internal_log(int argc, char **argv, struct command *command,
err = 0;
out:
if (err > 0) {
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
} else if (err < 0) {
perror("intel log");
err = EIO;
@ -1518,8 +1535,8 @@ static int enable_lat_stats_tracking(int argc, char **argv,
};
const struct argconfig_commandline_options command_line_options[] = {
{"enable", 'e', "", CFG_NONE, &cfg.enable, no_argument, enable_desc},
{"disable", 'd', "", CFG_NONE, &cfg.disable, no_argument, disable_desc},
{"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc},
{"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc},
{NULL}
};
@ -1540,10 +1557,40 @@ static int enable_lat_stats_tracking(int argc, char **argv,
if (fd < 0)
return fd;
struct nvme_get_features_args args_get = {
.args_size = sizeof(args_get),
.fd = fd,
.fid = fid,
.nsid = nsid,
.sel = sel,
.cdw11 = cdw11,
.uuidx = 0,
.data_len = data_len,
.data = buf,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
struct nvme_set_features_args args_set = {
.args_size = sizeof(args_set),
.fd = fd,
.fid = fid,
.nsid = nsid,
.cdw11 = option,
.cdw12 = cdw12,
.save = save,
.uuidx = 0,
.cdw15 = 0,
.data_len = data_len,
.data = buf,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
switch (option) {
case None:
err = nvme_get_feature(fd, nsid, fid, sel, cdw11, 0, data_len, buf,
&result);
err = nvme_get_features(&args_get);
if (!err) {
printf(
"Latency Statistics Tracking (FID 0x%X) is currently (%i).\n",
@ -1555,11 +1602,9 @@ static int enable_lat_stats_tracking(int argc, char **argv,
break;
case True:
case False:
err = nvme_set_feature(fd, nsid, fid, option, cdw12, save, 0,
data_len, buf, &result);
err = nvme_set_features(&args_set);
if (err > 0) {
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
} else if (err < 0) {
perror("Enable latency tracking");
fprintf(stderr, "Command failed while parsing.\n");
@ -1590,12 +1635,12 @@ static int set_lat_stats_thresholds(int argc, char **argv,
__u32 result;
struct config {
int write;
bool write;
char *bucket_thresholds;
};
struct config cfg = {
.write = 0,
.write = false,
.bucket_thresholds = "",
};
@ -1615,12 +1660,11 @@ static int set_lat_stats_thresholds(int argc, char **argv,
* valid buckets a user is allowed to modify. Read or write doesn't
* matter
*/
err = nvme_get_log(fd, NVME_NSID_ALL, 0xc2,
false, NVME_NO_LOG_LSP, sizeof(media_version),
media_version);
err = nvme_get_log_simple(fd, 0xc2,
sizeof(media_version), media_version);
if (err) {
fprintf(stderr, "Querying media version failed. NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
fprintf(stderr, "Querying media version failed. ");
nvme_show_status(err);
goto close_fd;
}
@ -1635,13 +1679,25 @@ static int set_lat_stats_thresholds(int argc, char **argv,
}
err = nvme_set_feature(fd, nsid, fid, cfg.write ? 0x1 : 0x0,
cdw12, save, 0, OPTANE_V1000_BUCKET_LEN,
thresholds, &result);
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = fid,
.nsid = nsid,
.cdw11 = cfg.write ? 0x1 : 0x0,
.cdw12 = cdw12,
.save = save,
.uuidx = 0,
.cdw15 = 0,
.data_len = sizeof(thresholds),
.data = thresholds,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_set_features(&args);
if (err > 0) {
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
} else if (err < 0) {
perror("Enable latency tracking");
fprintf(stderr, "Command failed while parsing.\n");

View file

@ -1,436 +0,0 @@
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "plugin.h"
#include "nvme-lightnvm.h"
#include "argconfig.h"
#include "suffix.h"
#define CREATE_CMD
#include "lnvm-nvme.h"
static int lnvm_init(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Initialize LightNVM device. A LightNVM/Open-Channel SSD"\
" must have a media manager associated before it can"\
" be exposed to the user. The default is to initialize"
" the general media manager on top of the device.\n\n"
"Example:"
" lnvm-init -d nvme0n1";
const char *devname = "identifier of desired device. e.g. nvme0n1.";
const char *mmtype = "media manager to initialize on top of device. Default: gennvm.";
int ret;
struct config {
char *devname;
char *mmtype;
};
struct config cfg = {
.devname = "",
.mmtype = "gennvm",
};
OPT_ARGS(opts) = {
OPT_STRING("device-name", 'd', "DEVICE", &cfg.devname, devname),
OPT_STRING("mediamgr-name", 'm', "MM", &cfg.mmtype, mmtype),
OPT_END()
};
ret = argconfig_parse(argc, argv, desc, opts);
if (ret < 0)
return ret;
if (!strlen(cfg.devname)) {
fprintf(stderr, "device name missing\n");
return -EINVAL;
}
return lnvm_do_init(cfg.devname, cfg.mmtype);
}
static int lnvm_list(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "List all devices registered with LightNVM.";
int ret;
OPT_ARGS(opts) = {
OPT_END()
};
ret = argconfig_parse(argc, argv, desc, opts);
if (ret < 0)
return ret;
return lnvm_do_list_devices();
}
static int lnvm_info(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Show general information and registered target types with LightNVM";
int ret;
OPT_ARGS(opts) = {
OPT_END()
};
ret = argconfig_parse(argc, argv, desc, opts);
if (ret < 0)
return ret;
return lnvm_do_info();
}
static int lnvm_id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Send an Identify Geometry command to the "\
"given LightNVM device, returns properties of the specified "\
"namespace in either human-readable or binary format.";
const char *raw_binary = "show infos in binary format";
const char *human_readable = "show infos in readable format";
const char *namespace_id = "identifier of desired namespace. default: 1";
unsigned int flags = 0;
int fd;
struct config {
__u32 namespace_id;
int raw_binary;
int human_readable;
};
struct config cfg = {
.namespace_id = 1,
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_binary),
OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
if (cfg.human_readable)
flags |= VERBOSE;
else if (cfg.raw_binary)
flags |= BINARY;
return lnvm_do_id_ns(fd, cfg.namespace_id, flags);
}
static int lnvm_chunk_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Retrieve the chunk information log for the "\
"specified given LightNVM device, returns in either "\
"human-readable or binary format.\n"\
"This will request Geometry first to get the "\
"num_grp,num_pu,num_chk first to figure out the total size "\
"of the log pages."\
;
const char *output_format = "Output format: normal|binary";
const char *human_readable = "Print normal in readable format";
int err, fmt, fd;
struct nvme_nvm_id20 geo;
struct nvme_nvm_chunk_desc *chunk_log;
__u32 nsid;
__u32 data_len;
unsigned int flags = 0;
struct config {
char *output_format;
int human_readable;
};
struct config cfg = {
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_FLAG("human-readable",'H', &cfg.human_readable, human_readable),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
fmt = validate_output_format(cfg.output_format);
if (fmt < 0) {
err = fmt;
goto close;
}
if (fmt == BINARY)
flags |= BINARY;
else if (cfg.human_readable)
flags |= VERBOSE;
nsid = nvme_get_nsid(fd);
/*
* It needs to figure out how many bytes will be requested by this
* subcommand by the (num_grp * num_pu * num_chk) from the Geometry.
*/
err = lnvm_get_identity(fd, nsid, (struct nvme_nvm_id *) &geo);
if (err)
goto close;
data_len = (geo.num_grp * geo.num_pu * geo.num_chk) *
sizeof(struct nvme_nvm_chunk_desc);
chunk_log = malloc(data_len);
if (!chunk_log) {
fprintf(stderr, "cound not alloc for chunk log %dbytes\n",
data_len);
err = -ENOMEM;
goto close;
}
err = lnvm_do_chunk_log(fd, nsid, data_len, chunk_log, flags);
if (err)
fprintf(stderr, "get log page for chunk information failed\n");
free(chunk_log);
close:
close(fd);
return err;
}
static int lnvm_create_tgt(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Instantiate a target on top of a LightNVM enabled device.";
const char *devname = "identifier of desired device. e.g. nvme0n1.";
const char *tgtname = "target name of the device to initialize. e.g. target0.";
const char *tgttype = "identifier of target type. e.g. pblk.";
const char *lun_begin = "Define begin of luns to use for target.";
const char *lun_end = "Define set of luns to use for target.";
const char *over_prov = "Define over-provision percentage for target.";
const char *flag_factory = "Create target in factory mode";
int flags;
int ret;
struct config {
char *devname;
char *tgtname;
char *tgttype;
__u32 lun_begin;
__u32 lun_end;
__u32 over_prov;
/* flags */
__u32 factory;
};
struct config cfg = {
.devname = "",
.tgtname = "",
.tgttype = "",
.lun_begin = -1,
.lun_end = -1,
.over_prov = -1,
.factory = 0,
};
OPT_ARGS(opts) = {
OPT_STRING("device-name", 'd', "DEVICE", &cfg.devname, devname),
OPT_STRING("target-name", 'n', "TARGET", &cfg.tgtname, tgtname),
OPT_STRING("target-type", 't', "TARGETTYPE", &cfg.tgttype, tgttype),
OPT_UINT("lun-begin", 'b', &cfg.lun_begin, lun_begin),
OPT_UINT("lun-end", 'e', &cfg.lun_end, lun_end),
OPT_UINT("over-prov", 'o', &cfg.over_prov, over_prov),
OPT_FLAG("factory", 'f', &cfg.factory, flag_factory),
OPT_END()
};
ret = argconfig_parse(argc, argv, desc, opts);
if (ret < 0)
return ret;
if (!strlen(cfg.devname)) {
fprintf(stderr, "device name missing\n");
return -EINVAL;
}
if (!strlen(cfg.tgtname)) {
fprintf(stderr, "target name missing\n");
return -EINVAL;
}
if (!strlen(cfg.tgttype)) {
fprintf(stderr, "target type missing\n");
return -EINVAL;
}
flags = 0;
if (cfg.factory)
flags |= NVM_TARGET_FACTORY;
return lnvm_do_create_tgt(cfg.devname, cfg.tgtname, cfg.tgttype, cfg.lun_begin, cfg.lun_end, cfg.over_prov, flags);
}
static int lnvm_remove_tgt(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Remove an initialized LightNVM target.";
const char *tgtname = "target name of the device to remove. e.g. target0.";
int ret;
struct config {
char *tgtname;
};
struct config cfg = {
.tgtname = "",
};
OPT_ARGS(opts) = {
OPT_STRING("target-name", 'n', "TARGET", &cfg.tgtname, tgtname),
OPT_END()
};
ret = argconfig_parse(argc, argv, desc, opts);
if (ret < 0)
return ret;
if (!strlen(cfg.tgtname)) {
fprintf(stderr, "target name missing\n");
return -EINVAL;
}
return lnvm_do_remove_tgt(cfg.tgtname);
}
static int lnvm_factory_init(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Factory initialize a LightNVM enabled device.";
const char *devname = "identifier of desired device. e.g. nvme0n1.";
const char *erase_only_marked = "only erase marked blocks. default: all blocks.";
const char *host_marks = "remove host side blocks list. default: keep.";
const char *bb_marks = "remove grown bad blocks list. default: keep";
int ret;
struct config {
char *devname;
int erase_only_marked;
int clear_host_marks;
int clear_bb_marks;
};
struct config cfg = {
.devname = "",
};
OPT_ARGS(opts) = {
OPT_STRING("device-name", 'd', "DEVICE", &cfg.devname, devname),
OPT_FLAG("erase-only-marked", 'e', &cfg.erase_only_marked, erase_only_marked),
OPT_FLAG("clear-host-side-blks", 's', &cfg.clear_host_marks, host_marks),
OPT_FLAG("clear-bb-blks", 'b', &cfg.clear_bb_marks, bb_marks),
OPT_END()
};
ret = argconfig_parse(argc, argv, desc, opts);
if (ret < 0)
return ret;
if (!strlen(cfg.devname)) {
fprintf(stderr, "device name missing\n");
return -EINVAL;
}
return lnvm_do_factory_init(cfg.devname, cfg.erase_only_marked,
cfg.clear_host_marks, cfg.clear_bb_marks);
}
static int lnvm_get_bbtbl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Receive bad block table from a LightNVM compatible"\
" device.";
const char *namespace = "(optional) desired namespace";
const char *ch = "channel identifier";
const char *lun = "lun identifier (within a channel)";
const char *raw_binary = "show infos in binary format";
unsigned int fd, flags = 0;
struct config {
__u32 namespace_id;
__u16 lunid;
__u16 chid;
int raw_binary;
};
struct config cfg = {
.namespace_id = 1,
.lunid = 0,
.chid = 0,
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
OPT_SHRT("channel-id", 'c', &cfg.chid, ch),
OPT_SHRT("lun-id", 'l', &cfg.lunid, lun),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_binary),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (cfg.raw_binary)
flags |= BINARY;
return lnvm_do_get_bbtbl(fd, cfg.namespace_id, cfg.lunid, cfg.chid, flags);
}
static int lnvm_set_bbtbl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Update bad block table on a LightNVM compatible"\
" device.";
const char *namespace = "(optional) desired namespace";
const char *ch = "channel identifier";
const char *lun = "lun identifier (within a channel)";
const char *pln = "plane identifier (within a lun)";
const char *blk = "block identifier (within a plane)";
const char *value = "value to update the specific block to.";
int fd;
struct config {
__u32 namespace_id;
__u16 lunid;
__u16 chid;
__u16 plnid;
__u16 blkid;
__u16 value;
};
struct config cfg = {
.namespace_id = 1,
.lunid = 0,
.chid = 0,
.plnid = 0,
.blkid = 0,
.value = 0,
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace),
OPT_SHRT("channel-id", 'c', &cfg.chid, ch),
OPT_SHRT("lun-id", 'l', &cfg.lunid, lun),
OPT_SHRT("plane-id", 'p', &cfg.plnid, pln),
OPT_SHRT("block-id", 'b', &cfg.blkid, blk),
OPT_SHRT("value", 'v', &cfg.value, value),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
printf("Updating: Ch.: %u LUN: %u Plane: %u Block: %u -> %u\n",
cfg.chid, cfg.lunid, cfg.plnid, cfg.blkid, cfg.value);
return lnvm_do_set_bbtbl(fd, cfg.namespace_id, cfg.chid, cfg.lunid,
cfg.plnid, cfg.blkid, cfg.value);
}

View file

@ -1,27 +0,0 @@
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/lnvm/lnvm-nvme
#if !defined(LNVM_NVME) || defined(CMD_HEADER_MULTI_READ)
#define LNVM_NVME
#include "cmd.h"
PLUGIN(NAME("lnvm", "LightNVM specific extensions", NVME_VERSION),
COMMAND_LIST(
ENTRY("list", "List available LightNVM devices", lnvm_list)
ENTRY("info", "List general information and available target engines", lnvm_info)
ENTRY("id-ns", "List geometry for LightNVM device", lnvm_id_ns, "geometry")
ENTRY("chunk-log", "Chunk Information Log Page", lnvm_chunk_log)
ENTRY("init", "Initialize media manager on LightNVM device", lnvm_init)
ENTRY("create", "Create target on top of a LightNVM device", lnvm_create_tgt)
ENTRY("remove", "Remove target from device", lnvm_remove_tgt)
ENTRY("factory", "Reset device to factory state", lnvm_factory_init)
ENTRY("diag-bbtbl", "Diagnose bad block table", lnvm_get_bbtbl)
ENTRY("diag-set-bbtbl", "Update bad block table", lnvm_set_bbtbl)
)
);
#endif
#include "define_cmd.h"

View file

@ -5,15 +5,11 @@
#include <unistd.h>
#include <time.h>
#include "linux/nvme_ioctl.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#include "linux/types.h"
#include "nvme-print.h"
#define CREATE_CMD
#include "memblaze-nvme.h"
@ -79,22 +75,19 @@ static int compare_fw_version(const char *fw1, const char *fw2)
#define STR_VER_SIZE (5)
int getlogpage_format_type(char *fw_ver)
int getlogpage_format_type(char *model_name)
{
char fw_ver_local[STR_VER_SIZE];
strncpy(fw_ver_local, fw_ver, STR_VER_SIZE);
*(fw_ver_local + STR_VER_SIZE - 1) = '\0';
if ( IS_RAISIN(fw_ver_local)
|| IS_KUMQUAT(fw_ver_local)
|| IS_LOQUAT(fw_ver_local)
)
int logpage_format_type = INTEL_FORMAT;
const char *boundary_model_name1 = "P"; // MEMBLAZE P7936DT0640M00
const char *boundary_model_name2 = "P5920"; // Use INTEL_FORMAT from Raisin P5920.
if (0 == strncmp(model_name, boundary_model_name1, strlen(boundary_model_name1)))
{
return INTEL_FORMAT;
}
else
{
return MEMBLAZE_FORMAT;
if (strncmp(model_name, boundary_model_name2, strlen(boundary_model_name2)) < 0)
{
logpage_format_type = MEMBLAZE_FORMAT;
}
}
return logpage_format_type;
}
static __u32 item_id_2_u32(struct nvme_memblaze_smart_log_item *item)
@ -232,8 +225,6 @@ static void show_memblaze_smart_log_new(struct nvme_memblaze_smart_log *s,
printf("%-32s: %3d%% %s%u%s%u%s%u\n", STR17_01, *nm, STR17_03, *raw,
STR17_04, *(raw+2), STR17_05, *(raw+4));
/* 18 RAISIN_SI_VD_POWER_LOSS_PROTECTION */
get_memblaze_new_smart_info(smart, RAISIN_SI_VD_POWER_LOSS_PROTECTION, nm, raw);
printf("%-32s: %3d%% %"PRIu64"\n", STR18_01, *nm, int48_to_long(raw));
/* 19 RAISIN_SI_VD_READ_FAIL */
get_memblaze_new_smart_info(smart, RAISIN_SI_VD_READ_FAIL, nm, raw);
printf("%-32s: %3d%% %"PRIu64"\n", STR19_01, *nm, int48_to_long(raw));
@ -392,7 +383,7 @@ static int show_memblaze_smart_log(int fd, __u32 nsid, const char *devname,
ctrl.fr[0], ctrl.fr[1], ctrl.fr[2], ctrl.fr[3],
ctrl.fr[4], ctrl.fr[5], ctrl.fr[6]);
if (getlogpage_format_type(fw_ver)) // Intel Format & new format
if (getlogpage_format_type(ctrl.mn)) // Intel Format & new format
{
show_memblaze_smart_log_new(smart, nsid, devname);
}
@ -419,7 +410,7 @@ int parse_params(char *str, int number, ...)
exit(EINVAL);
}
if (isalnum(*c) == 0) {
if (isalnum((int)*c) == 0) {
printf("%s is not a valid number\n", c);
return 1;
}
@ -448,7 +439,7 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm
const char *raw = "dump output in binary format";
struct config {
__u32 namespace_id;
int raw_binary;
bool raw_binary;
};
struct config cfg = {
@ -465,8 +456,8 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm
if (fd < 0)
return fd;
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
sizeof(smart_log), &smart_log);
if (!err) {
if (!cfg.raw_binary)
err = show_memblaze_smart_log(fd, cfg.namespace_id, devicename, &smart_log);
@ -474,7 +465,7 @@ static int mb_get_additional_smart_log(int argc, char **argv, struct command *cm
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -503,7 +494,20 @@ static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
err = nvme_get_feature(fd, 0, feature_id, 0, 0, 0, 0, NULL, &result);
struct nvme_get_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = feature_id,
.nsid = 0,
.sel = 0,
.cdw11 = 0,
.uuidx = 0,
.data_len = 0,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_get_features(&args);
if (err < 0) {
perror("get-feature");
}
@ -512,7 +516,7 @@ static int mb_get_powermanager_status(int argc, char **argv, struct command *cmd
mb_feature_to_string(feature_id),
nvme_select_to_string(0), result);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -527,7 +531,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd
struct config {
__u32 feature_id;
__u32 value;
int save;
bool save;
};
struct config cfg = {
@ -545,7 +549,22 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, 0, NULL, &result);
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = cfg.feature_id,
.nsid = 0,
.cdw11 = cfg.value,
.cdw12 = 0,
.save = cfg.save,
.uuidx = 0,
.cdw15 = 0,
.data_len = 0,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_set_features(&args);
if (err < 0) {
perror("set-feature");
}
@ -553,7 +572,7 @@ static int mb_set_powermanager_status(int argc, char **argv, struct command *cmd
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
mb_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -602,7 +621,22 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s
}
cfg.value = (param1 << MB_FEAT_HIGH_LATENCY_VALUE_SHIFT) | param2;
err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, 0, 0, 0, NULL, &result);
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = cfg.feature_id,
.nsid = 0,
.cdw11 = cfg.value,
.cdw12 = 0,
.save = false,
.uuidx = 0,
.cdw15 = 0,
.data_len = 0,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_set_features(&args);
if (err < 0) {
perror("set-feature");
}
@ -610,7 +644,7 @@ static int mb_set_high_latency_log(int argc, char **argv, struct command *cmd, s
printf("set-feature:0x%02X (%s), value:%#08x\n", cfg.feature_id,
mb_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -721,13 +755,13 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd,
if (fd < 0) return fd;
glp_high_latency_show_bar(fdi, DO_PRINT_FLAG);
err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf);
err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf);
while ( 1) {
while (1) {
if (!glp_high_latency(fdi, buf, LOG_PAGE_SIZE, DO_PRINT_FLAG)) break;
err = nvme_get_log(fd, NVME_NSID_ALL, GLP_ID_VU_GET_HIGH_LATENCY_LOG, 0, NVME_NO_LOG_LSP, sizeof(buf), &buf);
err = nvme_get_log_simple(fd, GLP_ID_VU_GET_HIGH_LATENCY_LOG, sizeof(buf), &buf);
if ( err) {
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
break;
}
}
@ -739,13 +773,13 @@ static int mb_high_latency_log_print(int argc, char **argv, struct command *cmd,
static int memblaze_fw_commit(int fd, int select)
{
struct nvme_admin_cmd cmd = {
.opcode = nvme_admin_activate_fw,
struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_fw_commit,
.cdw10 = 8,
.cdw12 = select,
};
return nvme_submit_admin_passthru(fd, &cmd);
return nvme_submit_admin_passthru(fd, &cmd, NULL);
}
static int mb_selective_download(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@ -839,13 +873,21 @@ static int mb_selective_download(int argc, char **argv, struct command *cmd, str
while (fw_size > 0) {
xfer = min(xfer, fw_size);
err = nvme_fw_download(fd, offset, xfer, fw_buf);
struct nvme_fw_download_args args = {
.args_size = sizeof(args),
.fd = fd,
.offset = offset,
.data_len = xfer,
.data = fw_buf,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = NULL,
};
err = nvme_fw_download(&args);
if (err < 0) {
perror("fw-download");
goto out;
} else if (err != 0) {
fprintf(stderr, "NVME Admin command error:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
goto out;
}
fw_buf += xfer;
@ -980,7 +1022,7 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st
const char *write = "Get write statistics (read default)";
struct config {
int write;
bool write;
};
struct config cfg = {
.write = 0,
@ -994,12 +1036,12 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0) return fd;
err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, false, NVME_NO_LOG_LSP, sizeof(stats), &stats);
err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, sizeof(stats), &stats);
if (!err)
io_latency_histogram(cfg.write ? f2 : f1, stats, DO_PRINT_FLAG,
cfg.write ? GLP_ID_VU_GET_WRITE_LATENCY_HISTOGRAM : GLP_ID_VU_GET_READ_LATENCY_HISTOGRAM);
else
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
close(fd);
return err;
@ -1009,8 +1051,8 @@ static int mb_lat_stats_log_print(int argc, char **argv, struct command *cmd, st
#define FID 0x68
static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
int err, fd;
char *desc = "Clear Memblaze devices error log.";
int err, fd;
char *desc = "Clear Memblaze devices error log.";
//const char *value = "new value of feature (required)";
//const char *save = "specifies that the controller shall save the attribute";
@ -1028,24 +1070,38 @@ static int memblaze_clear_error_log(int argc, char **argv, struct command *cmd,
.save = 0,
};
OPT_ARGS(opts) = {
OPT_END()
};
OPT_ARGS(opts) = {
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
err = nvme_set_feature(fd, 0, cfg.feature_id, cfg.value, 0, cfg.save, 0, 0, NULL, &result);
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = cfg.feature_id,
.nsid = 0,
.cdw11 = cfg.value,
.cdw12 = 0,
.save = cfg.save,
.uuidx = 0,
.cdw15 = 0,
.data_len = 0,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_set_features(&args);
if (err < 0) {
perror("set-feature");
}
if (!err) {
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id, mb_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
/*
struct nvme_admin_cmd admin_cmd = {
.opcode = OP,
@ -1060,7 +1116,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);
};
*/
return err;
return err;
}
static int mb_set_lat_stats(int argc, char **argv,
@ -1092,8 +1148,8 @@ static int mb_set_lat_stats(int argc, char **argv,
};
const struct argconfig_commandline_options command_line_options[] = {
{"enable", 'e', "", CFG_NONE, &cfg.enable, no_argument, enable_desc},
{"disable", 'd', "", CFG_NONE, &cfg.disable, no_argument, disable_desc},
{"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc},
{"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc},
{NULL}
};
@ -1111,12 +1167,41 @@ static int mb_set_lat_stats(int argc, char **argv,
else if (cfg.enable || cfg.disable)
option = cfg.enable;
struct nvme_get_features_args args_get = {
.args_size = sizeof(args_get),
.fd = fd,
.fid = fid,
.nsid = nsid,
.sel = sel,
.cdw11 = cdw11,
.uuidx = 0,
.data_len = data_len,
.data = buf,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
struct nvme_set_features_args args_set = {
.args_size = sizeof(args_set),
.fd = fd,
.fid = fid,
.nsid = nsid,
.cdw11 = option,
.cdw12 = cdw12,
.save = save,
.uuidx = 0,
.cdw15 = 0,
.data_len = data_len,
.data = buf,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
if (fd < 0)
return fd;
switch (option) {
case None:
err = nvme_get_feature(fd, nsid, fid, sel, cdw11, 0, data_len, buf,
&result);
err = nvme_get_features(&args_get);
if (!err) {
printf(
"Latency Statistics Tracking (FID 0x%X) is currently (%i).\n",
@ -1128,17 +1213,15 @@ static int mb_set_lat_stats(int argc, char **argv,
break;
case True:
case False:
err = nvme_set_feature(fd, nsid, fid, option, cdw12, save, 0,
data_len, buf, &result);
err = nvme_set_features(&args_set);
if (err > 0) {
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
} else if (err < 0) {
perror("Enable latency tracking");
fprintf(stderr, "Command failed while parsing.\n");
} else {
printf("Successfully set enable bit for FID (0x%X) to %i.\n",
fid, option);
0xe2, option);
}
break;
default:

21
plugins/meson.build Normal file
View file

@ -0,0 +1,21 @@
sources += [
'plugins/amzn/amzn-nvme.c',
'plugins/dera/dera-nvme.c',
'plugins/huawei/huawei-nvme.c',
'plugins/intel/intel-nvme.c',
'plugins/memblaze/memblaze-nvme.c',
'plugins/micron/micron-nvme.c',
'plugins/netapp/netapp-nvme.c',
'plugins/nvidia/nvidia-nvme.c',
'plugins/scaleflux/sfx-nvme.c',
'plugins/seagate/seagate-nvme.c',
'plugins/shannon/shannon-nvme.c',
'plugins/toshiba/toshiba-nvme.c',
'plugins/transcend/transcend-nvme.c',
'plugins/virtium/virtium-nvme.c',
'plugins/wdc/wdc-utils.c',
'plugins/wdc/wdc-nvme.c',
'plugins/ymtc/ymtc-nvme.c',
'plugins/zns/zns.c',
'plugins/ocp/ocp-nvme.c',
]

File diff suppressed because it is too large Load diff

View file

@ -13,14 +13,17 @@ PLUGIN(NAME("micron", "Micron vendor specific extensions", NVME_VERSION),
ENTRY("vs-pcie-stats", "Retrieve Micron PCIe error stats", micron_pcie_stats)
ENTRY("clear-pcie-correctable-errors", "Clear correctable PCIe errors", micron_clear_pcie_correctable_errors)
ENTRY("vs-internal-log", "Retrieve Micron logs", micron_internal_logs)
ENTRY("vs-telemetry-controller-option", "Enable/Disable controller telemetry log generation", micron_telemetry_cntrl_option)
ENTRY("vs-telemetry-controller-option", "Enable/Disable controller telemetry log generation", micron_telemetry_cntrl_option)
ENTRY("vs-nand-stats", "Retrieve NAND Stats", micron_nand_stats)
ENTRY("vs-smart-ext-log", "Retrieve extended SMART logs", micron_smart_ext_log)
ENTRY("vs-drive-info", "Retrieve Drive information", micron_drive_info)
ENTRY("plugin-version", "Display plugin version info", micron_plugin_version)
ENTRY("cloud-SSD-plugin-version", "Display plugin version info", micron_cloud_ssd_plugin_version)
ENTRY("log-page-directory", "Retrieve log page directory", micron_logpage_dir)
ENTRY("vs-fw-activate-history", "Display FW activation history", micron_fw_activation_history)
ENTRY("vs-error-reason-identifier", "Retrieve Error reason", micron_error_reason)
ENTRY("latency-tracking", "Latency monitoring feature control", micron_latency_stats_track)
ENTRY("latency-stats", "Latency information for tracked commands", micron_latency_stats_info)
ENTRY("latency-logs", "Latency log details tracked by drive", micron_latency_stats_logs)
ENTRY("vs-smart-add-log", "Retrieve extended SMART data", micron_ocp_smart_health_logs)
ENTRY("clear-fw-activate-history", "Clear FW activation history", micron_clr_fw_activation_history)
ENTRY("vs-smbus-option", "Enable/Disable SMBUS on the drive", micron_smbus_option)

View file

@ -21,12 +21,13 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <uuid/uuid.h>
#include "common.h"
#include "nvme.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "suffix.h"
#include "util/suffix.h"
#define CREATE_CMD
#include "netapp-nvme.h"
@ -56,17 +57,17 @@ enum {
static const char *dev_path = "/dev/";
struct smdevice_info {
int nsid;
unsigned nsid;
struct nvme_id_ctrl ctrl;
struct nvme_id_ns ns;
char dev[265];
};
struct ontapdevice_info {
int nsid;
unsigned nsid;
struct nvme_id_ctrl ctrl;
struct nvme_id_ns ns;
char nsdesc[4096];
uuid_t uuid;
unsigned char log_data[ONTAP_C2_LOG_SIZE];
char dev[265];
};
@ -105,24 +106,15 @@ static void netapp_nguid_to_str(char *str, __u8 *nguid)
static void netapp_get_ns_size(char *size, long long *lba,
struct nvme_id_ns *ns)
{
*lba = 1 << ns->lbaf[(ns->flbas & 0x0F)].ds;
__u8 lba_index;
nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index);
*lba = 1 << ns->lbaf[lba_index].ds;
double nsze = le64_to_cpu(ns->nsze) * (*lba);
const char *s_suffix = suffix_si_get(&nsze);
sprintf(size, "%.2f%sB", nsze, s_suffix);
}
static void netapp_uuid_to_str(char *str, void *data)
{
#ifdef LIBUUID
uuid_t uuid;
struct nvme_ns_id_desc *desc = data;
memcpy(uuid, data + sizeof(*desc), 16);
uuid_unparse_lower(uuid, str);
#endif
}
static void ontap_labels_to_str(char *dst, char *src, int count)
{
int i;
@ -249,6 +241,7 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
"Volume ID %s, Controller %c, Access State %s, %s\n";
char columnstr[] = "%-16s %-30s %-30s %4d %32s %c %-12s %9s\n";
char *formatstr = basestr; /* default to "normal" output format */
__u8 lba_index;
if (format == NCOLUMN) {
/* for column output, change output string and print column headers */
@ -265,11 +258,12 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
else if (format == NJSON) {
/* prepare for json output */
root = json_create_object();
json_devices = json_create_object();
json_devices = json_create_array();
}
for (i = 0; i < count; i++) {
long long int lba = 1 << devices[i].ns.lbaf[(devices[i].ns.flbas & 0x0F)].ds;
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;
double nsze = le64_to_cpu(devices[i].ns.nsze) * lba;
const char *s_suffix = suffix_si_get(&nsze);
char size[128];
@ -296,6 +290,8 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int
/* complete the json output */
json_object_add_value_array(root, "SMdevices", json_devices);
json_print_object(root, NULL);
printf("\n");
json_free_object(root);
}
}
@ -331,13 +327,13 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices,
} else if (format == NJSON) {
/* prepare for json output */
root = json_create_object();
json_devices = json_create_object();
json_devices = json_create_array();
}
for (i = 0; i < count; i++) {
netapp_get_ns_size(size, &lba, &devices[i].ns);
netapp_uuid_to_str(uuid_str, devices[i].nsdesc);
uuid_unparse_lower(devices[i].uuid, uuid_str);
netapp_get_ontap_labels(vsname, nspath, devices[i].log_data);
if (format == NJSON) {
@ -354,16 +350,18 @@ static void netapp_ontapdevices_print(struct ontapdevice_info *devices,
/* complete the json output */
json_object_add_value_array(root, "ONTAPdevices", json_devices);
json_print_object(root, NULL);
printf("\n");
json_free_object(root);
}
}
static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen)
{
struct nvme_admin_cmd get_log;
struct nvme_passthru_cmd get_log;
int err;
memset(buf, 0, buflen);
memset(&get_log, 0, sizeof(struct nvme_admin_cmd));
memset(&get_log, 0, sizeof(struct nvme_passthru_cmd));
get_log.opcode = nvme_admin_get_log_page;
get_log.nsid = nsid;
@ -378,7 +376,7 @@ static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen)
get_log.cdw10 |= ONTAP_C2_LOG_NSINFO_LSP << 8;
get_log.cdw11 = numdu;
err = nvme_submit_admin_passthru(fd, &get_log);
err = nvme_submit_admin_passthru(fd, &get_log, NULL);
if (err) {
fprintf(stderr, "ioctl error %0x\n", err);
return 1;
@ -402,8 +400,8 @@ static int netapp_smdevices_get_info(int fd, struct smdevice_info *item,
if (strncmp("NetApp E-Series", item->ctrl.mn, 15) != 0)
return 0; /* not the right model of controller */
item->nsid = nvme_get_nsid(fd);
err = nvme_identify_ns(fd, item->nsid, 0, &item->ns);
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));
@ -418,6 +416,7 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
const char *dev)
{
int err;
void *nsdescs;
err = nvme_identify_ctrl(fd, &item->ctrl);
if (err) {
@ -430,22 +429,30 @@ static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item,
/* not the right controller model */
return 0;
item->nsid = nvme_get_nsid(fd);
err = nvme_get_nsid(fd, &item->nsid);
err = nvme_identify_ns(fd, item->nsid, 0, &item->ns);
err = nvme_identify_ns(fd, item->nsid, &item->ns);
if (err) {
fprintf(stderr, "Unable to identify namespace for %s (%s)\n",
dev, strerror(err));
return 0;
}
err = nvme_identify_ns_descs(fd, item->nsid, item->nsdesc);
if (posix_memalign(&nsdescs, getpagesize(), 0x1000)) {
fprintf(stderr, "Cannot allocate controller list payload\n");
return 0;
}
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));
return 0;
}
memcpy(item->uuid, nsdescs + sizeof(struct nvme_ns_id_desc), sizeof(item->uuid));
free(nsdescs);
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",

View file

@ -5,17 +5,11 @@
#include <unistd.h>
#include <inttypes.h>
#include "linux/nvme_ioctl.h"
#include "common.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#define CREATE_CMD
#include "nvidia-nvme.h"

788
plugins/ocp/ocp-nvme.c Normal file
View file

@ -0,0 +1,788 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2022 Meta Platforms, Inc.
*
* Authors: Arthur Shau <arthurshau@fb.com>,
* Wei Zhang <wzhang@fb.com>,
* Venkat Ramesh <venkatraghavan@fb.com>
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include "common.h"
#include "nvme.h"
#include "libnvme.h"
#include "plugin.h"
#include "linux/types.h"
#include "nvme-print.h"
#define CREATE_CMD
#include "ocp-nvme.h"
/* C0 SCAO Log Page */
#define C0_SMART_CLOUD_ATTR_LEN 0x200
#define C0_SMART_CLOUD_ATTR_OPCODE 0xC0
#define C0_GUID_LENGTH 16
#define C0_ACTIVE_BUCKET_TIMER_INCREMENT 5
#define C0_ACTIVE_THRESHOLD_INCREMENT 5
#define C0_MINIMUM_WINDOW_INCREMENT 100
static __u8 scao_guid[C0_GUID_LENGTH] = { 0xC5, 0xAF, 0x10, 0x28, 0xEA, 0xBF,
0xF2, 0xA4, 0x9C, 0x4F, 0x6F, 0x7C, 0xC9, 0x14, 0xD5, 0xAF };
/* C3 Latency Monitor Log Page */
#define C3_LATENCY_MON_LOG_BUF_LEN 0x200
#define C3_LATENCY_MON_OPCODE 0xC3
#define C3_LATENCY_MON_VERSION 0x0001
#define C3_GUID_LENGTH 16
static __u8 lat_mon_guid[C3_GUID_LENGTH] = { 0x92, 0x7a, 0xc0, 0x8c, 0xd0, 0x84,
0x6c, 0x9c, 0x70, 0x43, 0xe6, 0xd4, 0x58, 0x5e, 0xd4, 0x85 };
#define READ 0
#define WRITE 1
#define TRIM 2
#define RESERVED 3
typedef enum {
SCAO_PMUW = 0, /* Physical media units written */
SCAO_PMUR = 16, /* Physical media units read */
SCAO_BUNBR = 32, /* Bad user nand blocks raw */
SCAO_BUNBN = 38, /* Bad user nand blocks normalized */
SCAO_BSNBR = 40, /* Bad system nand blocks raw */
SCAO_BSNBN = 46, /* Bad system nand blocks normalized */
SCAO_XRC = 48, /* XOR recovery count */
SCAO_UREC = 56, /* Uncorrectable read error count */
SCAO_SEEC = 64, /* Soft ecc error count */
SCAO_EECE = 72, /* End to end corrected errors */
SCAO_EEDC = 76, /* End to end detected errors */
SCAO_SDPU = 80, /* System data percent used */
SCAO_RFSC = 81, /* Refresh counts */
SCAO_MXUDEC = 88, /* Max User data erase counts */
SCAO_MNUDEC = 92, /* Min User data erase counts */
SCAO_NTTE = 96, /* Number of Thermal throttling events */
SCAO_CTS = 97, /* Current throttling status */
SCAO_EVF = 98, /* Errata Version Field */
SCAO_PVF = 99, /* Point Version Field */
SCAO_MIVF = 101, /* Minor Version Field */
SCAO_MAVF = 103, /* Major Version Field */
SCAO_PCEC = 104, /* PCIe correctable error count */
SCAO_ICS = 112, /* Incomplete shutdowns */
SCAO_PFB = 120, /* Percent free blocks */
SCAO_CPH = 128, /* Capacitor health */
SCAO_NEV = 130, /* NVMe Errata Version */
SCAO_UIO = 136, /* Unaligned I/O */
SCAO_SVN = 144, /* Security Version Number */
SCAO_NUSE = 152, /* NUSE - Namespace utilization */
SCAO_PSC = 160, /* PLP start count */
SCAO_EEST = 176, /* Endurance estimate */
SCAO_PLRC = 192, /* PCIe Link Retraining Count */
SCAO_LPV = 494, /* Log page version */
SCAO_LPG = 496, /* Log page GUID */
} SMART_CLOUD_ATTRIBUTE_OFFSETS;
struct __attribute__((__packed__)) ssd_latency_monitor_log {
__u8 feature_status; /* 0x00 */
__u8 rsvd1; /* 0x01 */
__le16 active_bucket_timer; /* 0x02 */
__le16 active_bucket_timer_threshold; /* 0x04 */
__u8 active_threshold_a; /* 0x06 */
__u8 active_threshold_b; /* 0x07 */
__u8 active_threshold_c; /* 0x08 */
__u8 active_threshold_d; /* 0x09 */
__le16 active_latency_config; /* 0x0A */
__u8 active_latency_min_window; /* 0x0C */
__u8 rsvd2[0x13]; /* 0x0D */
__le32 active_bucket_counter[4][4] ; /* 0x20 - 0x5F */
__le64 active_latency_timestamp[4][3]; /* 0x60 - 0xBF */
__le16 active_measured_latency[4][3]; /* 0xC0 - 0xD7 */
__le16 active_latency_stamp_units; /* 0xD8 */
__u8 rsvd3[0x16]; /* 0xDA */
__le32 static_bucket_counter[4][4] ; /* 0xF0 - 0x12F */
__le64 static_latency_timestamp[4][3]; /* 0x130 - 0x18F */
__le16 static_measured_latency[4][3]; /* 0x190 - 0x1A7 */
__le16 static_latency_stamp_units; /* 0x1A8 */
__u8 rsvd4[0x16]; /* 0x1AA */
__le16 debug_log_trigger_enable; /* 0x1C0 */
__le16 debug_log_measured_latency; /* 0x1C2 */
__le64 debug_log_latency_stamp; /* 0x1C4 */
__le16 debug_log_ptr; /* 0x1CC */
__le16 debug_log_counter_trigger; /* 0x1CE */
__u8 debug_log_stamp_units; /* 0x1D0 */
__u8 rsvd5[0x1D]; /* 0x1D1 */
__le16 log_page_version; /* 0x1EE */
__u8 log_page_guid[0x10]; /* 0x1F0 */
};
static long double int128_to_double(__u8 *data)
{
int i;
long double result = 0;
for (i = 0; i < 16; i++) {
result *= 256;
result += data[15 - i];
}
return result;
}
static int convert_ts(time_t time, char *ts_buf)
{
struct tm gmTimeInfo;
time_t time_Human, time_ms;
char buf[80];
time_Human = time/1000;
time_ms = time % 1000;
gmtime_r((const time_t *)&time_Human, &gmTimeInfo);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &gmTimeInfo);
sprintf(ts_buf, "%s.%03ld GMT", buf, time_ms);
return 0;
}
static void ocp_print_C0_log_normal(void *data)
{
__u8 *log_data = (__u8*)data;
uint16_t smart_log_ver = 0;
printf("SMART Cloud Attributes :- \n");
printf(" Physical media units written - %"PRIu64" %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF),
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
printf(" Physical media units read - %"PRIu64" %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF),
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
printf(" Bad user nand blocks - Raw %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
printf(" Bad user nand blocks - Normalized %d\n",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
printf(" Bad system nand blocks - Raw %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
printf(" Bad system nand blocks - Normalized %d\n",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
printf(" XOR recovery count %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
printf(" Uncorrectable read error count %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
printf(" Soft ecc error count %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
printf(" End to end corrected errors %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
printf(" End to end detected errors %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
printf(" System data percent used %d\n",
(__u8)log_data[SCAO_SDPU]);
printf(" Refresh counts %"PRIu64"\n",
(uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF));
printf(" Max User data erase counts %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
printf(" Min User data erase counts %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
printf(" Number of Thermal throttling events %d\n",
(__u8)log_data[SCAO_NTTE]);
printf(" Current throttling status 0x%x\n",
(__u8)log_data[SCAO_CTS]);
printf(" PCIe correctable error count %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
printf(" Incomplete shutdowns %"PRIu32"\n",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
printf(" Percent free blocks %d\n",
(__u8)log_data[SCAO_PFB]);
printf(" Capacitor health %"PRIu16"\n",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
printf(" Unaligned I/O %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
printf(" Security Version Number %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
printf(" NUSE - Namespace utilization %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
printf(" PLP start count %.0Lf\n",
int128_to_double(&log_data[SCAO_PSC]));
printf(" Endurance estimate %.0Lf\n",
int128_to_double(&log_data[SCAO_EEST]));
smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
printf(" Log page version %"PRIu16"\n",smart_log_ver);
printf(" Log page GUID 0x");
printf("%"PRIx64"%"PRIx64"\n",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
if(smart_log_ver > 2) {
printf(" Errata Version Field %d\n",
(__u8)log_data[SCAO_EVF]);
printf(" Point Version Field %"PRIu16"\n",
(uint16_t)log_data[SCAO_PVF]);
printf(" Minor Version Field %"PRIu16"\n",
(uint16_t)log_data[SCAO_MIVF]);
printf(" Major Version Field %d\n",
(__u8)log_data[SCAO_MAVF]);
printf(" NVMe Errata Version %d\n",
(__u8)log_data[SCAO_NEV]);
printf(" PCIe Link Retraining Count %"PRIu64"\n",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
}
printf("\n");
}
static void ocp_print_C0_log_json(void *data)
{
__u8 *log_data = (__u8*)data;
struct json_object *root;
struct json_object *pmuw;
struct json_object *pmur;
uint16_t smart_log_ver = 0;
root = json_create_object();
pmuw = json_create_object();
pmur = json_create_object();
json_object_add_value_uint64(pmuw, "hi",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW+8] & 0xFFFFFFFFFFFFFFFF));
json_object_add_value_uint64(pmuw, "lo",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
json_object_add_value_object(root, "Physical media units written", pmuw);
json_object_add_value_uint64(pmur, "hi",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR+8] & 0xFFFFFFFFFFFFFFFF));
json_object_add_value_uint64(pmur, "lo",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
json_object_add_value_object(root, "Physical media units read", pmur);
json_object_add_value_uint64(root, "Bad user nand blocks - Raw",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BUNBR] & 0x0000FFFFFFFFFFFF));
json_object_add_value_uint(root, "Bad user nand blocks - Normalized",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BUNBN]));
json_object_add_value_uint64(root, "Bad system nand blocks - Raw",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_BSNBR] & 0x0000FFFFFFFFFFFF));
json_object_add_value_uint(root, "Bad system nand blocks - Normalized",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_BSNBN]));
json_object_add_value_uint64(root, "XOR recovery count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_XRC]));
json_object_add_value_uint64(root, "Uncorrectable read error count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UREC]));
json_object_add_value_uint64(root, "Soft ecc error count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SEEC]));
json_object_add_value_uint(root, "End to end corrected errors",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EECE]));
json_object_add_value_uint(root, "End to end detected errors",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_EEDC]));
json_object_add_value_uint(root, "System data percent used",
(__u8)log_data[SCAO_SDPU]);
json_object_add_value_uint64(root, "Refresh counts",
(uint64_t)(le64_to_cpu(*(uint64_t *)&log_data[SCAO_RFSC])& 0x00FFFFFFFFFFFFFF));
json_object_add_value_uint(root, "Max User data erase counts",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MXUDEC]));
json_object_add_value_uint(root, "Min User data erase counts",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
json_object_add_value_uint(root, "Number of Thermal throttling events",
(__u8)log_data[SCAO_NTTE]);
json_object_add_value_uint(root, "Current throttling status",
(__u8)log_data[SCAO_CTS]);
json_object_add_value_uint64(root, "PCIe correctable error count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
json_object_add_value_uint(root, "Incomplete shutdowns",
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_ICS]));
json_object_add_value_uint(root, "Percent free blocks",
(__u8)log_data[SCAO_PFB]);
json_object_add_value_uint(root, "Capacitor health",
(uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_CPH]));
json_object_add_value_uint64(root, "Unaligned I/O",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_UIO]));
json_object_add_value_uint64(root, "Security Version Number",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_SVN]));
json_object_add_value_uint64(root, "NUSE - Namespace utilization",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_NUSE]));
json_object_add_value_uint(root, "PLP start count",
int128_to_double(&log_data[SCAO_PSC]));
json_object_add_value_uint64(root, "Endurance estimate",
int128_to_double(&log_data[SCAO_EEST]));
smart_log_ver = (uint16_t)le16_to_cpu(*(uint16_t *)&log_data[SCAO_LPV]);
json_object_add_value_uint(root, "Log page version", smart_log_ver);
char guid[40];
memset((void*)guid, 0, 40);
sprintf((char*)guid, "0x%"PRIx64"%"PRIx64"",(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG + 8]),
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_LPG]));
json_object_add_value_string(root, "Log page GUID", guid);
if(smart_log_ver > 2){
json_object_add_value_uint(root, "Errata Version Field",
(__u8)log_data[SCAO_EVF]);
json_object_add_value_uint(root, "Point Version Field",
(uint16_t)log_data[SCAO_PVF]);
json_object_add_value_uint(root, "Minor Version Field",
(uint16_t)log_data[SCAO_MIVF]);
json_object_add_value_uint(root, "Major Version Field",
(__u8)log_data[SCAO_MAVF]);
json_object_add_value_uint(root, "NVMe Errata Version",
(__u8)log_data[SCAO_NEV]);
json_object_add_value_uint(root, "PCIe Link Retraining Count",
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PLRC]));
}
json_print_object(root, NULL);
printf("\n");
json_free_object(root);
}
static int get_c0_log_page(int fd, char *format)
{
int ret = 0;
int fmt = -1;
__u8 *data;
int i;
fmt = validate_output_format(format);
if (fmt < 0) {
fprintf(stderr, "ERROR : OCP : invalid output format\n");
return fmt;
}
if ((data = (__u8 *) malloc(sizeof(__u8) * C0_SMART_CLOUD_ATTR_LEN)) == NULL) {
fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno));
return -1;
}
memset(data, 0, sizeof (__u8) * C0_SMART_CLOUD_ATTR_LEN);
ret = nvme_get_log_simple(fd, C0_SMART_CLOUD_ATTR_OPCODE,
C0_SMART_CLOUD_ATTR_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(ret, false), ret);
if (ret == 0) {
/* check log page guid */
/* Verify GUID matches */
for (i=0; i<16; i++) {
if (scao_guid[i] != data[SCAO_LPG + i]) {
fprintf(stderr, "ERROR : OCP : Unknown GUID in C0 Log Page data\n");
int j;
fprintf(stderr, "ERROR : OCP : Expected GUID: 0x");
for (j = 0; j<16; j++) {
fprintf(stderr, "%x", scao_guid[j]);
}
fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x");
for (j = 0; j<16; j++) {
fprintf(stderr, "%x", data[SCAO_LPG + j]);
}
fprintf(stderr, "\n");
ret = -1;
goto out;
}
}
/* 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);
break;
case JSON:
ocp_print_C0_log_json(data);
break;
}
} else {
fprintf(stderr, "ERROR : OCP : Unable to read C0 data from buffer\n");
}
out:
free(data);
return ret;
}
static int ocp_smart_add_log(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
const char *desc = "Retrieve latency monitor log data.";
int fd;
int ret = 0;
struct config {
char *output_format;
};
struct config cfg = {
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_FMT("output-format", 'o', &cfg.output_format, "output Format: normal|json"),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
ret = get_c0_log_page(fd, cfg.output_format);
if (ret)
fprintf(stderr, "ERROR : OCP : Failure reading the C0 Log Page, ret = %d\n",
ret);
return ret;
}
static int ocp_print_C3_log_normal(int fd, struct ssd_latency_monitor_log *log_data)
{
printf("-Latency Monitor/C3 Log Page Data- \n");
printf(" Controller : %s\n", devicename);
int i, j;
int pos = 0;
char ts_buf[128];
printf(" Feature Status 0x%x \n",
log_data->feature_status);
printf(" Active Bucket Timer %d min \n",
C0_ACTIVE_BUCKET_TIMER_INCREMENT *
le16_to_cpu(log_data->active_bucket_timer));
printf(" Active Bucket Timer Threshold %d min \n",
C0_ACTIVE_BUCKET_TIMER_INCREMENT *
le16_to_cpu(log_data->active_bucket_timer_threshold));
printf(" Active Threshold A %d ms \n",
C0_ACTIVE_THRESHOLD_INCREMENT *
le16_to_cpu(log_data->active_threshold_a+1));
printf(" Active Threshold B %d ms \n",
C0_ACTIVE_THRESHOLD_INCREMENT *
le16_to_cpu(log_data->active_threshold_b+1));
printf(" Active Threshold C %d ms \n",
C0_ACTIVE_THRESHOLD_INCREMENT *
le16_to_cpu(log_data->active_threshold_c+1));
printf(" Active Threshold D %d ms \n",
C0_ACTIVE_THRESHOLD_INCREMENT *
le16_to_cpu(log_data->active_threshold_d+1));
printf(" Active Latency Minimum Window %d ms \n",
C0_MINIMUM_WINDOW_INCREMENT *
le16_to_cpu(log_data->active_latency_min_window));
printf(" Active Latency Stamp Units %d \n",
le16_to_cpu(log_data->active_latency_stamp_units));
printf(" Static Latency Stamp Units %d \n",
le16_to_cpu(log_data->static_latency_stamp_units));
printf(" Debug Log Trigger Enable %d \n",
le16_to_cpu(log_data->debug_log_trigger_enable));
printf(" Read Write Deallocate/Trim \n");
for (i = 0; i <= 3; i++) {
printf(" Active Latency Mode: Bucket %d %27d %27d %27d \n",
i,
log_data->active_latency_config & (1 << pos),
log_data->active_latency_config & (1 << pos),
log_data->active_latency_config & (1 << pos));
}
printf("\n");
for (i = 0; i <= 3; i++) {
printf(" Active Bucket Counter: Bucket %d %27d %27d %27d \n",
i,
le32_to_cpu(log_data->active_bucket_counter[i][READ]),
le32_to_cpu(log_data->active_bucket_counter[i][WRITE]),
le32_to_cpu(log_data->active_bucket_counter[i][TRIM]));
}
for (i = 0; i <= 3; i++) {
printf(" Active Measured Latency: Bucket %d %27d ms %27d ms %27d ms \n",
i,
le16_to_cpu(log_data->active_measured_latency[i][READ]),
le16_to_cpu(log_data->active_measured_latency[i][WRITE]),
le16_to_cpu(log_data->active_measured_latency[i][TRIM]));
}
for (i = 0; i <= 3; i++) {
printf(" Active Latency Time Stamp: Bucket %d ", i);
for (j = 0; j <= 2; j++) {
if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1)
printf(" N/A ");
else {
convert_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf);
printf("%s ", ts_buf);
}
}
printf("\n");
}
for (i = 0; i <= 3; i++) {
printf(" Static Bucket Counter: Bucket %d %27d %27d %27d \n",
i,
le32_to_cpu(log_data->static_bucket_counter[i][READ]),
le32_to_cpu(log_data->static_bucket_counter[i][WRITE]),
le32_to_cpu(log_data->static_bucket_counter[i][TRIM]));
}
for (i = 0; i <= 3; i++) {
printf(" Static Measured Latency: Bucket %d %27d ms %27d ms %27d ms \n",
i,
le16_to_cpu(log_data->static_measured_latency[i][READ]),
le16_to_cpu(log_data->static_measured_latency[i][WRITE]),
le16_to_cpu(log_data->static_measured_latency[i][TRIM]));
}
for (i = 0; i <= 3; i++) {
printf(" Static Latency Time Stamp: Bucket %d ", i);
for (j = 0; j <= 2; j++) {
if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1)
printf(" N/A ");
else {
convert_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf);
printf("%s ", ts_buf);
}
}
printf("\n");
}
return 0;
}
static void ocp_print_C3_log_json(struct ssd_latency_monitor_log *log_data)
{
int i, j;
int pos = 0;
char buf[128];
char ts_buf[128];
char *operation[3] = {"Read", "Write", "Trim"};
struct json_object *root;
root = json_create_object();
json_object_add_value_uint(root, "Feature Status",
log_data->feature_status);
json_object_add_value_uint(root, "Active Bucket Timer",
C0_ACTIVE_BUCKET_TIMER_INCREMENT *
le16_to_cpu(log_data->active_bucket_timer));
json_object_add_value_uint(root, "Active Bucket Timer Threshold",
C0_ACTIVE_BUCKET_TIMER_INCREMENT *
le16_to_cpu(log_data->active_bucket_timer_threshold));
json_object_add_value_uint(root, "Active Threshold A",
C0_ACTIVE_THRESHOLD_INCREMENT *
le16_to_cpu(log_data->active_threshold_a+1));
json_object_add_value_uint(root, "Active Threshold B",
C0_ACTIVE_THRESHOLD_INCREMENT *
le16_to_cpu(log_data->active_threshold_b+1));
json_object_add_value_uint(root, "Active Threshold C",
C0_ACTIVE_THRESHOLD_INCREMENT *
le16_to_cpu(log_data->active_threshold_c+1));
json_object_add_value_uint(root, "Active Threshold D",
C0_ACTIVE_THRESHOLD_INCREMENT *
le16_to_cpu(log_data->active_threshold_d+1));
json_object_add_value_uint(root, "Active Lantency Minimum Window",
C0_MINIMUM_WINDOW_INCREMENT *
le16_to_cpu(log_data->active_latency_min_window));
json_object_add_value_uint(root, "Active Latency Stamp Units",
le16_to_cpu(log_data->active_latency_stamp_units));
json_object_add_value_uint(root, "Static Latency Stamp Units",
le16_to_cpu(log_data->static_latency_stamp_units));
json_object_add_value_uint(root, "Debug Log Trigger Enable",
le16_to_cpu(log_data->debug_log_trigger_enable));
for (i = 0; i <= 3; i++) {
struct json_object *bucket;
bucket = json_create_object();
sprintf(buf, "Active Latency Mode: Bucket %d", i);
for (j = 0; j <= 2; j++) {
json_object_add_value_uint(bucket, operation[j],
log_data->active_latency_config & (1 << pos));
}
json_object_add_value_object(root, buf, bucket);
}
for (i = 0; i <= 3; i++) {
struct json_object *bucket;
bucket = json_create_object();
sprintf(buf, "Active Bucket Counter: Bucket %d", i);
for (j = 0; j <= 2; j++) {
json_object_add_value_uint(bucket, operation[j],
le32_to_cpu(log_data->active_bucket_counter[i][j]));
}
json_object_add_value_object(root, buf, bucket);
}
for (i = 0; i <= 3; i++) {
struct json_object *bucket;
bucket = json_create_object();
sprintf(buf, "Active Measured Latency: Bucket %d", i);
for (j = 0; j <= 2; j++) {
json_object_add_value_uint(bucket, operation[j],
le16_to_cpu(log_data->active_measured_latency[i][j]));
}
json_object_add_value_object(root, buf, bucket);
}
for (i = 0; i <= 3; i++) {
struct json_object *bucket;
bucket = json_create_object();
sprintf(buf, "Active Latency Time Stamp: Bucket %d", i);
for (j = 0; j <= 2; j++) {
if (le64_to_cpu(log_data->active_latency_timestamp[i][j]) == -1)
json_object_add_value_string(bucket, operation[j], "NA");
else {
convert_ts(le64_to_cpu(log_data->active_latency_timestamp[i][j]), ts_buf);
json_object_add_value_string(bucket, operation[j], ts_buf);
}
}
json_object_add_value_object(root, buf, bucket);
}
for (i = 0; i <= 3; i++) {
struct json_object *bucket;
bucket = json_create_object();
sprintf(buf, "Static Bucket Counter: Bucket %d", i);
for (j = 0; j <= 2; j++) {
json_object_add_value_uint(bucket, operation[j],
le32_to_cpu(log_data->static_bucket_counter[i][j]));
}
json_object_add_value_object(root, buf, bucket);
}
for (i = 0; i <= 3; i++) {
struct json_object *bucket;
bucket = json_create_object();
sprintf(buf, "Static Measured Latency: Bucket %d", i);
for (j = 0; j <= 2; j++) {
json_object_add_value_uint(bucket, operation[j],
le16_to_cpu(log_data->static_measured_latency[i][j]));
}
json_object_add_value_object(root, buf, bucket);
}
for (i = 0; i <= 3; i++) {
struct json_object *bucket;
bucket = json_create_object();
sprintf(buf, "Static Latency Time Stamp: Bucket %d", i);
for (j = 0; j <= 2; j++) {
if (le64_to_cpu(log_data->static_latency_timestamp[i][j]) == -1)
json_object_add_value_string(bucket, operation[j], "NA");
else {
convert_ts(le64_to_cpu(log_data->static_latency_timestamp[i][j]), ts_buf);
json_object_add_value_string(bucket, operation[j], ts_buf);
}
}
json_object_add_value_object(root, buf, bucket);
}
json_print_object(root, NULL);
printf("\n");
json_free_object(root);
}
static int get_c3_log_page(int fd, char *format)
{
int ret = 0;
int fmt = -1;
__u8 *data;
int i;
struct ssd_latency_monitor_log *log_data;
fmt = validate_output_format(format);
if (fmt < 0) {
fprintf(stderr, "ERROR : OCP : invalid output format\n");
return fmt;
}
if ((data = (__u8 *) malloc(sizeof(__u8) * C3_LATENCY_MON_LOG_BUF_LEN)) == NULL) {
fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno));
return -1;
}
memset(data, 0, sizeof (__u8) * C3_LATENCY_MON_LOG_BUF_LEN);
ret = nvme_get_log_simple(fd, C3_LATENCY_MON_OPCODE,
C3_LATENCY_MON_LOG_BUF_LEN, data);
if (strcmp(format, "json"))
fprintf(stderr,
"NVMe Status:%s(%x)\n",
nvme_status_to_string(ret, false),
ret);
if (ret == 0) {
log_data = (struct ssd_latency_monitor_log*)data;
/* check log page version */
if (log_data->log_page_version != C3_LATENCY_MON_VERSION) {
fprintf(stderr,
"ERROR : OCP : invalid latency monitor version\n");
ret = -1;
goto out;
}
/* check log page guid */
/* Verify GUID matches */
for (i=0; i<16; i++) {
if (lat_mon_guid[i] != log_data->log_page_guid[i]) {
fprintf(stderr,"ERROR : OCP : Unknown GUID in C3 Log Page data\n");
int j;
fprintf(stderr, "ERROR : OCP : Expected GUID: 0x");
for (j = 0; j<16; j++) {
fprintf(stderr, "%x", lat_mon_guid[j]);
}
fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x");
for (j = 0; j<16; j++) {
fprintf(stderr, "%x", log_data->log_page_guid[j]);
}
fprintf(stderr, "\n");
ret = -1;
goto out;
}
}
/* 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);
break;
case JSON:
ocp_print_C3_log_json(log_data);
break;
}
} else {
fprintf(stderr,
"ERROR : OCP : Unable to read C3 data from buffer\n");
}
out:
free(data);
return ret;
}
static int ocp_latency_monitor_log(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
const char *desc = "Retrieve latency monitor log data.";
int fd;
int ret = 0;
struct config {
char *output_format;
};
struct config cfg = {
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_FMT("output-format", 'o', &cfg.output_format,
"output Format: normal|json"),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return fd;
ret = get_c3_log_page(fd, cfg.output_format);
if (ret)
fprintf(stderr,
"ERROR : OCP : Failure reading the C3 Log Page, ret = %d\n",
ret);
return ret;
}

25
plugins/ocp/ocp-nvme.h Normal file
View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2022 Meta Platforms, Inc.
*
* Authors: Arthur Shau <arthurshau@fb.com>,
* Wei Zhang <wzhang@fb.com>,
* Venkat Ramesh <venkatraghavan@fb.com>
*/
#undef CMD_INC_FILE
#define CMD_INC_FILE plugins/ocp/ocp-nvme
#if !defined(OCP_NVME) || defined(CMD_HEADER_MULTI_READ)
#define OCP_NVME
#include "cmd.h"
PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION),
COMMAND_LIST(
ENTRY("smart-add-log", "Retrieve extended SMART Information", ocp_smart_add_log)
ENTRY("latency-monitor-log", "Get Latency Monitor Log Page", ocp_latency_monitor_log)
)
);
#endif
#include "define_cmd.h"

View file

@ -6,21 +6,16 @@
#include <linux/fs.h>
#include <inttypes.h>
#include <asm/byteorder.h>
#include <sys/ioctl.h>
#include <sys/sysinfo.h>
#include <sys/stat.h>
#include <unistd.h>
#include "linux/nvme_ioctl.h"
#include "common.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "nvme-status.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#include "linux/types.h"
#include "nvme-print.h"
#define CREATE_CMD
#include "sfx-nvme.h"
@ -114,38 +109,38 @@ struct nvme_additional_smart_log {
int nvme_change_cap(int fd, __u32 nsid, __u64 capacity)
{
struct nvme_admin_cmd cmd = {
struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_change_cap,
.nsid = nsid,
.cdw10 = (capacity & 0xffffffff),
.cdw11 = (capacity >> 32),
};
return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd);
return nvme_submit_admin_passthru(fd, &cmd, NULL);
}
int nvme_sfx_set_features(int fd, __u32 nsid, __u32 fid, __u32 value)
{
struct nvme_admin_cmd cmd = {
struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_sfx_set_features,
.nsid = nsid,
.cdw10 = fid,
.cdw11 = value,
};
return nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd);
return nvme_submit_admin_passthru(fd, &cmd, NULL);
}
int nvme_sfx_get_features(int fd, __u32 nsid, __u32 fid, __u32 *result)
{
int err = 0;
struct nvme_admin_cmd cmd = {
struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_sfx_get_features,
.nsid = nsid,
.cdw10 = fid,
};
err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD,&cmd);
err = nvme_submit_admin_passthru(fd, &cmd, NULL);
if (!err && result) {
*result = cmd.result;
}
@ -343,8 +338,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
const char *json= "Dump output in json format";
struct config {
__u32 namespace_id;
int raw_binary;
int json;
bool raw_binary;
bool json;
};
struct config cfg = {
@ -361,7 +356,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
fd = parse_and_open(argc, argv, desc, opts);
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, NVME_NO_LOG_LSP,
err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
sizeof(smart_log), (void *)&smart_log);
if (!err) {
if (cfg.json)
@ -372,8 +367,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -428,8 +422,8 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
const char *raw = "dump output in binary format";
const char *write = "Get write statistics (read default)";
struct config {
int raw_binary;
int write;
bool raw_binary;
bool write;
};
struct config cfg = {
@ -443,22 +437,20 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct
fd = parse_and_open(argc, argv, desc, opts);
err = nvme_get_log(fd, 0xffffffff, cfg.write ? 0xc3 : 0xc1, false, NVME_NO_LOG_LSP,
sizeof(stats), (void *)&stats);
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));
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data)
{
struct nvme_admin_cmd cmd = {
struct nvme_passthru_cmd cmd = {
.opcode = nvme_admin_get_log_page,
.nsid = nsid,
.addr = (__u64)(uintptr_t) data,
@ -470,7 +462,7 @@ int sfx_nvme_get_log(int fd, __u32 nsid, __u8 log_id, __u32 data_len, void *data
cmd.cdw10 = log_id | (numdl << 16);
cmd.cdw11 = numdu;
return nvme_submit_admin_passthru(fd, &cmd);
return nvme_submit_admin_passthru(fd, &cmd, NULL);
}
/**
@ -583,8 +575,7 @@ static int sfx_get_bad_block(int argc, char **argv, struct command *cmd, struct
if (err < 0) {
perror("get-bad-block");
} else if (err != 0) {
fprintf(stderr, "NVMe IO command error:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
} else {
bd_table_show(data_buf, buf_size);
printf("ScaleFlux get bad block table: success\n");
@ -616,8 +607,8 @@ static int query_cap_info(int argc, char **argv, struct command *cmd, struct plu
const char *raw = "dump output in binary format";
const char *json= "Dump output in json format";
struct config {
int raw_binary;
int json;
bool raw_binary;
bool json;
};
struct config cfg;
@ -745,9 +736,9 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
struct config {
__u64 cap_in_byte;
__u32 capacity_in_gb;
int raw_binary;
int json;
int force;
bool raw_binary;
bool json;
bool force;
};
struct config cfg = {
@ -790,8 +781,7 @@ static int change_cap(int argc, char **argv, struct command *cmd, struct plugin
if (err < 0)
perror("sfx-change-cap");
else if (err != 0)
fprintf(stderr, "NVMe IO command error:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
else {
printf("ScaleFlux change-capacity: success\n");
ioctl(fd, BLKRRPART);
@ -863,7 +853,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
__u32 namespace_id;
__u32 feature_id;
__u32 value;
__u32 force;
bool force;
};
struct config cfg = {
.namespace_id = 1,
@ -902,14 +892,12 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
if (cfg.feature_id == SFX_FEAT_ATOMIC && cfg.value != 0) {
if (cfg.namespace_id != 0xffffffff) {
err = nvme_identify_ns(fd, cfg.namespace_id, 0, &ns);
err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
if (err) {
if (err < 0)
perror("identify-namespace");
else
fprintf(stderr,
"NVMe Admin command error:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
/*
@ -941,8 +929,7 @@ static int sfx_set_feature(int argc, char **argv, struct command *cmd, struct pl
printf("ScaleFlux set-feature:%#02x (%s), value:%d\n", cfg.feature_id,
sfx_feature_to_string(cfg.feature_id), cfg.value);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -990,8 +977,7 @@ static int sfx_get_feature(int argc, char **argv, struct command *cmd, struct pl
printf("ScaleFlux get-feature:%02x (%s), value:%d\n", cfg.feature_id,
sfx_feature_to_string(cfg.feature_id), result);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;

View file

@ -26,16 +26,14 @@
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <ctype.h>
#include "linux/nvme_ioctl.h"
#include "common.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#include "linux/types.h"
#include "nvme-print.h"
#define CREATE_CMD
@ -176,8 +174,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd,
};
fd = parse_and_open(argc, argv, desc, opts);
err = nvme_get_log(fd, 1, 0xc5, false, NVME_NO_LOG_LSP,
sizeof(logPageMap), &logPageMap);
err = nvme_get_log_simple(fd, 0xc5, sizeof(logPageMap), &logPageMap);
if (!err) {
if (strcmp(cfg.output_format,"json")) {
printf ("Seagate Supported Log-pages count :%d\n",
@ -201,8 +198,7 @@ static int log_pages_supp(int argc, char **argv, struct command *cmd,
}
if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -739,8 +735,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
if (strcmp(cfg.output_format,"json"))
printf("Seagate Extended SMART Information :\n");
err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP,
sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
if (!err) {
if (strcmp(cfg.output_format,"json")) {
printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value");
@ -762,8 +757,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
* Next get Log Page 0xCF
*/
err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP,
sizeof(logPageCF), &logPageCF);
err = nvme_get_log_simple(fd, 0xCF, sizeof(logPageCF), &logPageCF);
if (!err) {
if(strcmp(cfg.output_format,"json")) {
/*printf("Seagate DRAM Supercap SMART Attributes :\n");*/
@ -778,8 +772,7 @@ static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugi
} else if (!strcmp(cfg.output_format, "json"))
json_print_object(root, NULL);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -844,7 +837,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin
if(strcmp(cfg.output_format,"json"))
printf("Seagate Temperature Stats Information :\n");
/*STEP-1 : Get Current Temperature from SMART */
err = nvme_smart_log(fd, 0xffffffff, &smart_log);
err = nvme_get_log_smart(fd, 0xffffffff, true, &smart_log);
if (!err) {
temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]);
temperature = temperature ? temperature - 273 : 0;
@ -860,8 +853,7 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin
}
/* STEP-2 : Get Max temperature form Ext SMART-id 194 */
err = nvme_get_log(fd, 1, 0xC4, false, NVME_NO_LOG_LSP,
sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
err = nvme_get_log_simple(fd, 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
if (!err) {
for(index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) {
if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_LIFE_TEMPERATURE) {
@ -880,11 +872,9 @@ static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin
}
}
else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
cf_err = nvme_get_log(fd, 1, 0xCF, false, NVME_NO_LOG_LSP,
sizeof(ExtdSMARTInfo), &logPageCF);
cf_err = nvme_get_log_simple(fd, 0xCF, sizeof(ExtdSMARTInfo), &logPageCF);
if(!cf_err) {
scCurrentTemp = logPageCF.AttrCF.SuperCapCurrentTemperature;
@ -1013,8 +1003,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct
if(strcmp(cfg.output_format,"json"))
printf("Seagate PCIe error counters Information :\n");
err = nvme_get_log(fd, 1, 0xCB, false, NVME_NO_LOG_LSP,
sizeof(pcieErrorLog), &pcieErrorLog);
err = nvme_get_log_simple(fd, 0xCB, sizeof(pcieErrorLog), &pcieErrorLog);
if (!err) {
if(strcmp(cfg.output_format,"json")) {
print_vs_pcie_error_log(pcieErrorLog);
@ -1022,7 +1011,7 @@ static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct
json_vs_pcie_error_log(pcieErrorLog);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -1034,10 +1023,9 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c
const char *save = "specifies that the controller shall save the attribute";
int err, fd;
__u32 result;
void *buf = NULL;
struct config {
int save;
bool save;
};
struct config cfg = {
@ -1051,7 +1039,7 @@ static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *c
fd = parse_and_open(argc, argv, desc, opts);
err = nvme_set_feature(fd, 0, 0xE1, 0xCB, 0, cfg.save, 0, 0, buf, &result);
err = nvme_set_features_simple(fd, 0xE1, 0, 0xCB, cfg.save, &result);
if (err < 0) {
perror("set-feature");
@ -1080,7 +1068,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
struct config {
__u32 namespace_id;
__u32 log_id;
int raw_binary;
bool raw_binary;
};
struct config cfg = {
@ -1101,8 +1089,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
dump_fd = STDOUT_FILENO;
cfg.log_id = (cfg.log_id << 8) | 0x07;
err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id,
NVME_NO_LOG_LSP, offset, 0, false,
err = nvme_get_nsid_log(fd, false, cfg.log_id, cfg.namespace_id,
sizeof(tele_log), (void *)(&tele_log));
if (!err) {
maxBlk = tele_log.tele_data_area3;
@ -1119,8 +1106,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
} else
seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
else
perror("log page");
@ -1141,9 +1127,24 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
memset(log, 0, blksToGet * 512);
err = nvme_get_log13(fd, cfg.namespace_id, cfg.log_id,
NVME_NO_LOG_LSP, offset, 0, false,
blksToGet * 512, (void *)log);
struct nvme_get_log_args args = {
.args_size = sizeof(args),
.fd = fd,
.lid = cfg.log_id,
.nsid = cfg.namespace_id,
.lpo = offset,
.lsp = 0,
.lsi = 0,
.rae = true,
.uuidx = 0,
.csi = NVME_CSI_NVM,
.ot = false,
.len = blksToGet * 512,
.log = (void *)log,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = NULL,
};
err = nvme_get_log(&args);
if (!err) {
offset += blksToGet * 512;
@ -1154,8 +1155,7 @@ static int get_host_tele(int argc, char **argv, struct command *cmd, struct plug
} else
seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
else
perror("log page");
@ -1182,7 +1182,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
struct config {
__u32 namespace_id;
int raw_binary;
bool raw_binary;
};
struct config cfg = {
@ -1202,8 +1202,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
dump_fd = STDOUT_FILENO;
log_id = 0x08;
err = nvme_get_log13(fd, cfg.namespace_id, log_id,
NVME_NO_LOG_LSP, offset, 0, false,
err = nvme_get_nsid_log(fd, false, log_id, cfg.namespace_id,
sizeof(tele_log), (void *)(&tele_log));
if (!err) {
maxBlk = tele_log.tele_data_area3;
@ -1219,8 +1218,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
} else
seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
else
perror("log page");
@ -1241,9 +1239,24 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
memset(log, 0, blksToGet * 512);
err = nvme_get_log13(fd, cfg.namespace_id, log_id,
NVME_NO_LOG_LSP, offset, 0, false,
blksToGet * 512, (void *)log);
struct nvme_get_log_args args = {
.args_size = sizeof(args),
.fd = fd,
.lid = log_id,
.nsid = cfg.namespace_id,
.lpo = offset,
.lsp = 0,
.lsi = 0,
.rae = true,
.uuidx = 0,
.csi = NVME_CSI_NVM,
.ot = false,
.len = blksToGet * 512,
.log = (void *)log,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = NULL,
};
err = nvme_get_log(&args);
if (!err) {
offset += blksToGet * 512;
@ -1254,8 +1267,7 @@ static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plug
} else
seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
else
perror("log page");
@ -1327,8 +1339,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
}
log_id = 0x08;
err = nvme_get_log13(fd, cfg.namespace_id, log_id,
NVME_NO_LOG_LSP, offset, 0, false,
err = nvme_get_nsid_log(fd, false, log_id, cfg.namespace_id,
sizeof(tele_log), (void *)(&tele_log));
if (!err) {
maxBlk = tele_log.tele_data_area3;
@ -1340,8 +1351,7 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
*/
seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
else
perror("log page");
@ -1363,17 +1373,31 @@ static int vs_internal_log(int argc, char **argv, struct command *cmd, struct pl
memset(log, 0, blksToGet * 512);
err = nvme_get_log13(fd, cfg.namespace_id, log_id,
NVME_NO_LOG_LSP, offset, 0, false,
blksToGet * 512, (void *)log);
struct nvme_get_log_args args = {
.args_size = sizeof(args),
.fd = fd,
.lid = log_id,
.nsid = cfg.namespace_id,
.lpo = offset,
.lsp = 0,
.lsi = 0,
.rae = true,
.uuidx = 0,
.csi = NVME_CSI_NVM,
.ot = false,
.len = blksToGet * 512,
.log = (void *)log,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = NULL,
};
err = nvme_get_log(&args);
if (!err) {
offset += blksToGet * 512;
seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
else
perror("log page");

View file

@ -5,16 +5,12 @@
#include <unistd.h>
#include <inttypes.h>
#include "linux/nvme_ioctl.h"
#include "common.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#include "linux/types.h"
#include "nvme-print.h"
#define CREATE_CMD
#include "shannon-nvme.h"
@ -127,7 +123,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
const char *raw = "dump output in binary format";
struct config {
__u32 namespace_id;
int raw_binary;
bool raw_binary;
};
struct config cfg = {
@ -141,8 +137,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
};
fd = parse_and_open(argc, argv, desc, opts);
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
sizeof(smart_log), &smart_log);
if (!err) {
if (!cfg.raw_binary)
show_shannon_smart_log(&smart_log, cfg.namespace_id, devicename);
@ -150,8 +146,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -181,17 +176,17 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
struct config {
__u32 namespace_id;
enum nvme_feat feature_id;
enum nvme_features_id feature_id;
__u8 sel;
__u32 cdw11;
__u32 data_len;
int raw_binary;
int human_readable;
bool raw_binary;
bool human_readable;
};
struct config cfg = {
.namespace_id = 1,
.feature_id = NVME_FEAT_NONE,
.feature_id = 0,
.sel = 0,
.cdw11 = 0,
.data_len = 0,
@ -231,9 +226,22 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
memset(buf, 0, cfg.data_len);
}
err = nvme_get_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.sel, cfg.cdw11, 0,
cfg.data_len, buf, &result);
struct nvme_get_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = cfg.feature_id,
.nsid = cfg.namespace_id,
.sel = cfg.sel,
.cdw11 = cfg.cdw11,
.uuidx = 0,
.data_len = cfg.data_len,
.data = buf,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_get_features(&args);
if (!err) {
#if 0
printf("get-feature:0x%02x (%s), %s value: %#08x\n", cfg.feature_id,
nvme_feature_to_string(cfg.feature_id),
nvme_select_to_string(cfg.sel), result);
@ -247,9 +255,9 @@ static int get_additional_feature(int argc, char **argv, struct command *cmd, st
d_raw(buf, cfg.data_len);
}
}
#endif
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
if (buf)
free(buf);
return err;
@ -285,7 +293,7 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st
__u32 feature_id;
__u32 value;
__u32 data_len;
int save;
bool save;
};
struct config cfg = {
@ -343,20 +351,35 @@ static int set_additional_feature(int argc, char **argv, struct command *cmd, st
}
}
err = nvme_set_feature(fd, cfg.namespace_id, cfg.feature_id, cfg.value,
0, cfg.save, 0, cfg.data_len, buf, &result);
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = cfg.feature_id,
.nsid = cfg.namespace_id,
.cdw11 = cfg.value,
.cdw12 = 0,
.save = cfg.save,
.uuidx = 0,
.cdw15 = 0,
.data_len = cfg.data_len,
.data = buf,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_set_features(&args);
if (err < 0) {
perror("set-feature");
goto free;
}
if (!err) {
#if 0
printf("set-feature:%02x (%s), value:%#08x\n", cfg.feature_id,
nvme_feature_to_string(cfg.feature_id), cfg.value);
#endif
if (buf)
d(buf, cfg.data_len, 16, 1);
} else if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n",
nvme_status_to_string(err), err);
nvme_show_status(err);
free:
if (buf)

View file

@ -9,10 +9,10 @@
PLUGIN(NAME("shannon", "Shannon vendor specific extensions", NVME_VERSION),
COMMAND_LIST(
ENTRY("smart-log-add", "Retrieve Shannon SMART Log, show it", get_additional_smart_log)
ENTRY("get-feature-add", "Get Shannon feature and show the resulting value", get_additional_feature)
ENTRY("set-feature-add", "Set a Shannon feature and show the resulting value", set_additional_feature)
ENTRY("id-ctrl", "Shannon NVMe Identify Controller", shannon_id_ctrl)
)
ENTRY("set-additioal-feature", "Set additional Shannon feature", set_additional_feature)
ENTRY("get-additional-feature", "Get additional Shannon feature", get_additional_feature)
ENTRY("id-ctrl", "Retrieve Shannon ctrl id, show it", shannon_id_ctrl)
)
);
#endif

View file

@ -7,13 +7,11 @@
#include <inttypes.h>
#include <stdbool.h>
#include "linux/nvme_ioctl.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#include "linux/types.h"
#include "nvme-print.h"
#define CREATE_CMD
#include "toshiba-nvme.h"
@ -67,7 +65,7 @@ static int nvme_sct_op(int fd, __u32 opcode, __u32 cdw10, __u32 cdw11, void* da
int err = 0;
__u32 result;
err = nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd,
err = nvme_admin_passthru(fd, opcode, flags, rsvd,
namespace_id, cdw2, cdw3, cdw10,
cdw11, cdw12, cdw13, cdw14, cdw15,
data_len, data, metadata_len, metadata,
@ -392,8 +390,7 @@ static int nvme_get_vendor_log(int fd, __u32 namespace_id, int log_page,
if (err) {
goto end;
}
err = nvme_get_log(fd, namespace_id, log_page, false,
NVME_NO_LOG_LSP, log_len, log);
err = nvme_get_nsid_log(fd, false, log_page, namespace_id, log_len, log);
if (err) {
fprintf(stderr, "%s: couldn't get log 0x%x\n", __func__,
log_page);
@ -476,7 +473,7 @@ static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin
fprintf(stderr, "%s: couldn't get vendor log 0x%x\n", __func__, cfg.log);
end:
if (err > 0)
fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -518,8 +515,8 @@ static int internal_log(int argc, char **argv, struct command *cmd, struct plugi
if (err < 0)
fprintf(stderr, "%s: couldn't get fw log \n", __func__);
if (err > 0)
fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__,
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}
@ -550,14 +547,27 @@ static int clear_correctable_errors(int argc, char **argv, struct command *cmd,
if (err)
goto end;
err = nvme_set_feature(fd, namespace_id, feature_id, value, cdw12, save,
0, 0, NULL, &result);
struct nvme_set_features_args args = {
.args_size = sizeof(args),
.fd = fd,
.fid = feature_id,
.nsid = namespace_id,
.cdw11 = value,
.cdw12 = cdw12,
.save = save,
.uuidx = 0,
.cdw15 = 0,
.data_len = 0,
.data = NULL,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
err = nvme_set_features(&args);
if (err)
fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n",
__func__);
end:
if (err > 0)
fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__,
nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}

View file

@ -5,13 +5,9 @@
#include <unistd.h>
#include <inttypes.h>
#include "linux/nvme_ioctl.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#define CREATE_CMD
#include "transcend-nvme.h"
@ -37,7 +33,7 @@ static int getHealthValue(int argc, char **argv, struct command *cmd, struct plu
printf("\nDevice not found \n");;
return -1;
}
result = nvme_smart_log(fd, 0xffffffff, &smart_log);
result = nvme_get_log_smart(fd, 0xffffffff, true, &smart_log);
if (!result) {
printf("Transcend NVME heath value: ");
percent_used =smart_log.percent_used;
@ -82,7 +78,7 @@ static int getBadblock(int argc, char **argv, struct command *cmd, struct plugin
nvmecmd.cdw12=DW12_BAD_BLOCK;
nvmecmd.addr = (__u64)(uintptr_t)data;
nvmecmd.data_len = 0x1;
result = nvme_submit_admin_passthru(fd,&nvmecmd);
result = nvme_submit_admin_passthru(fd, &nvmecmd, NULL);
if(!result) {
int badblock = data[0];
printf("Transcend NVME badblock count: %d\n",badblock);

View file

@ -9,13 +9,10 @@
#include <time.h>
#include <locale.h>
#include "linux/nvme_ioctl.h"
#include "common.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#define CREATE_CMD
#include "virtium-nvme.h"
@ -35,7 +32,7 @@ struct vtview_log_header {
char test_name[256];
long int time_stamp;
struct nvme_id_ctrl raw_ctrl;
struct nvme_firmware_log_page raw_fw;
struct nvme_firmware_slot raw_fw;
};
struct vtview_smart_log_entry {
@ -124,6 +121,8 @@ static void vt_convert_smart_data_to_human_readable_format(struct vtview_smart_l
double capacity;
char *curlocale;
char *templocale;
__u8 lba_index;
nvme_id_ns_flbas_to_lbaf_inuse(smart->raw_ns.flbas, &lba_index);
curlocale = setlocale(LC_ALL, NULL);
templocale = strdup(curlocale);
@ -133,7 +132,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[(smart->raw_ns.flbas & 0x0f)].ds;
long long int lba = 1 << 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,
@ -273,7 +272,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
struct vtview_smart_log_entry smart;
char filename[256] = "";
int ret = 0;
int nsid = 0;
unsigned nsid = 0;
memset(smart.path, 0, sizeof(smart.path));
strcpy(smart.path, path);
@ -283,14 +282,14 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
strcpy(filename, cfg->output_file);
smart.time_stamp = time(NULL);
nsid = nvme_get_nsid(fd);
ret = nvme_get_nsid(fd, &nsid);
if (nsid <= 0) {
if (ret < 0) {
printf("Cannot read namespace-id\n");
return -1;
}
ret = nvme_identify_ns(fd, nsid, 0, &smart.raw_ns);
ret = nvme_identify_ns(fd, nsid, &smart.raw_ns);
if (ret) {
printf("Cannot read namespace identify\n");
return -1;
@ -302,7 +301,7 @@ static int vt_add_entry_to_log(const int fd, const char *path, const struct vtvi
return -1;
}
ret = nvme_smart_log(fd, NVME_NSID_ALL, &smart.raw_smart);
ret = nvme_get_log_smart(fd, NVME_NSID_ALL, true, &smart.raw_smart);
if (ret) {
printf("Cannot read device SMART log\n");
return -1;
@ -343,7 +342,7 @@ static int vt_update_vtview_log_header(const int fd, const char *path, const str
return -1;
}
ret = nvme_fw_log(fd, &header.raw_fw);
ret = nvme_get_log_fw_slot(fd, true, &header.raw_fw);
if (ret) {
printf("Cannot read device firmware log\n");
return -1;
@ -445,7 +444,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl)
vt_convert_data_buffer_to_hex_string(&buf[16], 4, true, s);
printf("%9sh", s);
temp = ctrl->psd[i].idle_scale;
temp = ctrl->psd[i].ips;
snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01));
printf("%3sb", s);
@ -454,7 +453,7 @@ static void vt_build_power_state_descriptor(const struct nvme_id_ctrl *ctrl)
vt_convert_data_buffer_to_hex_string(&buf[20], 4, true, s);
printf("%9sh", s);
temp = ctrl->psd[i].active_work_scale;
temp = ctrl->psd[i].apws;
snprintf(s, sizeof(s), "%u%u", (((unsigned char)temp >> 6) & 0x01), (((unsigned char)temp >> 7) & 0x01));
printf("%3sb", s);
snprintf(s, sizeof(s), "%u%u%u", (((unsigned char)temp) & 0x01), (((unsigned char)temp >> 1) & 0x01), (((unsigned char)temp >> 2) & 0x01));

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
#if !defined(WDC_NVME) || defined(CMD_HEADER_MULTI_READ)
#define WDC_NVME
#define WDC_PLUGIN_VERSION "1.15.4"
#define WDC_PLUGIN_VERSION "1.16.4"
#include "cmd.h"
PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERSION),
@ -37,6 +37,9 @@ PLUGIN(NAME("wdc", "Western Digital vendor specific extensions", WDC_PLUGIN_VERS
ENTRY("cloud-SSD-plugin-version", "WDC Cloud SSD Plugin Version", wdc_cloud_ssd_plugin_version)
ENTRY("vs-pcie-stats", "WDC VS PCIE Statistics", wdc_vs_pcie_stats)
ENTRY("get-latency-monitor-log", "WDC Get Latency Monitor Log Page", wdc_get_latency_monitor_log)
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)
)
);

View file

@ -4,15 +4,11 @@
#include <stdlib.h>
#include <unistd.h>
#include "linux/nvme_ioctl.h"
#include "nvme.h"
#include "nvme-print.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "plugin.h"
#include "argconfig.h"
#include "suffix.h"
#include "linux/types.h"
#include "nvme-print.h"
#define CREATE_CMD
#include "ymtc-nvme.h"
@ -116,7 +112,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
const char *raw = "dump output in binary format";
struct config {
__u32 namespace_id;
int raw_binary;
bool raw_binary;
};
struct config cfg = {
@ -133,8 +129,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
if (fd < 0)
return fd;
err = nvme_get_log(fd, cfg.namespace_id, 0xca, false,
NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log);
err = nvme_get_nsid_log(fd, false, 0xca, cfg.namespace_id,
sizeof(smart_log), &smart_log);
if (!err) {
if (!cfg.raw_binary)
err = show_ymtc_smart_log(fd, cfg.namespace_id, devicename, &smart_log);
@ -142,7 +138,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd,
d_raw((unsigned char *)&smart_log, sizeof(smart_log));
}
if (err > 0)
fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err);
nvme_show_status(err);
return err;
}

View file

@ -7,15 +7,110 @@
#include <linux/fs.h>
#include <sys/stat.h>
#include "common.h"
#include "nvme.h"
#include "nvme-ioctl.h"
#include "libnvme.h"
#include "nvme-print.h"
#include "nvme-status.h"
#define CREATE_CMD
#include "zns.h"
static const char *namespace_id = "Namespace identifier to use";
static const char dash[100] = { [0 ... 99] = '-' };
static int detect_zns(nvme_ns_t ns, int *out_supported)
{
int err = 0;
char *zoned;
*out_supported = 0;
zoned = nvme_get_attr(nvme_ns_get_sysfs_dir(ns), "queue/zoned");
if (!zoned) {
*out_supported = 0;
return err;
}
*out_supported = strcmp("host-managed", zoned) == 0;
free(zoned);
return err;
}
static int print_zns_list_ns(nvme_ns_t ns)
{
int supported;
int err = 0;
err = detect_zns(ns, &supported);
if (err) {
perror("Failed to enumerate namespace");
return err;
}
if (supported) {
nvme_show_list_item(ns);
}
return err;
}
static int print_zns_list(nvme_root_t nvme_root)
{
int err = 0;
nvme_host_t h;
nvme_subsystem_t s;
nvme_ctrl_t c;
nvme_ns_t n;
nvme_for_each_host(nvme_root, h)
{
nvme_for_each_subsystem(h, s)
{
nvme_subsystem_for_each_ns(s, n)
{
err = print_zns_list_ns(n);
if (err)
return err;
}
nvme_subsystem_for_each_ctrl(s, c)
{
nvme_ctrl_for_each_ns(c, n)
{
err = print_zns_list_ns(n);
if (err)
return err;
}
}
}
}
return err;
}
static int list(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
int err = 0;
nvme_root_t nvme_root;
printf("%-21s %-20s %-40s %-9s %-26s %-16s %-8s\n", "Node", "SN",
"Model", "Namespace", "Usage", "Format", "FW Rev");
printf("%-.21s %-.20s %-.40s %-.9s %-.26s %-.16s %-.8s\n", dash, dash,
dash, dash, dash, dash, dash);
nvme_root = nvme_scan(NULL);
if (nvme_root) {
err = print_zns_list(nvme_root);
} else {
fprintf(stderr, "Failed to scan nvme subsystems\n");
err = -errno;
}
nvme_free_tree(nvme_root);
return err;
}
static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
@ -57,7 +152,7 @@ static int id_ctrl(int argc, char **argv, struct command *cmd, struct plugin *pl
perror("zns identify controller");
close_fd:
close(fd);
return nvme_status_to_errno(err, false);
return err;
}
static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@ -76,8 +171,8 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
struct config {
char *output_format;
__u32 namespace_id;
int human_readable;
int vendor_specific;
bool human_readable;
bool vendor_specific;
};
struct config cfg = {
@ -105,14 +200,14 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
flags |= VERBOSE;
if (!cfg.namespace_id) {
err = cfg.namespace_id = nvme_get_nsid(fd);
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
err = nvme_identify_ns(fd, cfg.namespace_id, false, &id_ns);
err = nvme_identify_ns(fd, cfg.namespace_id, &id_ns);
if (err) {
nvme_show_status(err);
goto close_fd;
@ -127,18 +222,6 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
perror("zns identify namespace");
close_fd:
close(fd);
return nvme_status_to_errno(err, false);
}
static int __zns_mgmt_send(int fd, __u32 namespace_id, __u64 zslba,
bool select_all, __u32 timeout, enum nvme_zns_send_action zsa,
__u32 data_len, void *buf)
{
int err;
err = nvme_zns_mgmt_send(fd, namespace_id, zslba, select_all, timeout, zsa,
data_len, buf);
close(fd);
return err;
}
@ -149,8 +232,9 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug
const char *select_all = "send command to all zones";
const char *timeout = "timeout value, in milliseconds";
int err, fd;
int err, fd, zcapc = 0;
char *command;
__u32 result;
struct config {
__u64 zslba;
@ -171,26 +255,42 @@ static int zns_mgmt_send(int argc, char **argv, struct command *cmd, struct plug
err = fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return errno;
goto ret;
err = asprintf(&command, "%s-%s", plugin->name, cmd->name);
if (err < 0)
goto close_fd;
if (!cfg.namespace_id) {
err = cfg.namespace_id = nvme_get_nsid(fd);
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto free;
}
}
err = __zns_mgmt_send(fd, cfg.namespace_id, cfg.zslba,
cfg.select_all, cfg.timeout, zsa, 0, NULL);
if (!err)
printf("%s: Success, action:%d zone:%"PRIx64" all:%d nsid:%d\n",
struct nvme_zns_mgmt_send_args args = {
.args_size = sizeof(args),
.fd = fd,
.nsid = cfg.namespace_id,
.slba = cfg.zslba,
.zsa = zsa,
.select_all = cfg.select_all,
.zsaso = 0,
.data_len = 0,
.data = NULL,
.timeout = cfg.timeout,
.result = &result,
};
err = nvme_zns_mgmt_send(&args);
if (!err) {
if (zsa == NVME_ZNS_ZSA_RESET)
zcapc = result & 0x1;
printf("%s: Success, action:%d zone:%"PRIx64" all:%d zcapc:%u nsid:%d\n",
command, zsa, (uint64_t)cfg.zslba, (int)cfg.select_all,
cfg.namespace_id);
zcapc, cfg.namespace_id);
}
else if (err > 0)
nvme_show_status(err);
else
@ -199,7 +299,8 @@ free:
free(command);
close_fd:
close(fd);
return nvme_status_to_errno(err, false);
ret:
return err;
}
static int get_zdes_bytes(int fd, __u32 nsid)
@ -209,7 +310,7 @@ static int get_zdes_bytes(int fd, __u32 nsid)
__u8 lbaf;
int err;
err = nvme_identify_ns(fd, nsid, false, &id_ns);
err = nvme_identify_ns(fd, nsid, &id_ns);
if (err > 0) {
nvme_show_status(err);
return -1;
@ -227,14 +328,16 @@ static int get_zdes_bytes(int fd, __u32 nsid)
return -1;
}
lbaf = id_ns.flbas & NVME_NS_FLBAS_LBA_MASK;
nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf);
return ns.lbafe[lbaf].zdes << 6;
}
static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Zone Management Send";
const char *zslba = "starting LBA of the zone for this command";
const char *zslba = "starting LBA of the zone for this command"\
"(for flush action, last lba to flush)";
const char *zsaso = "Zone Send Action Specific Option";
const char *select_all = "send command to all zones";
const char *zsa = "zone send action";
const char *data_len = "buffer length if data required";
@ -247,6 +350,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
struct config {
__u64 zslba;
__u32 namespace_id;
bool zsaso;
bool select_all;
__u8 zsa;
int data_len;
@ -259,6 +363,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_SUFFIX("start-lba", 's', &cfg.zslba, zslba),
OPT_FLAG("zsaso", 'o', &cfg.zsaso, zsaso),
OPT_FLAG("select-all", 'a', &cfg.select_all, select_all),
OPT_BYTE("zsa", 'z', &cfg.zsa, zsa),
OPT_UINT("data-len", 'l', &cfg.data_len, data_len),
@ -272,7 +377,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
return errno;
if (!cfg.namespace_id) {
err = cfg.namespace_id = nvme_get_nsid(fd);
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
@ -287,15 +392,17 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
if (cfg.zsa == NVME_ZNS_ZSA_SET_DESC_EXT) {
if(!cfg.data_len) {
cfg.data_len = get_zdes_bytes(fd, cfg.namespace_id);
if (!cfg.data_len || cfg.data_len < 0) {
int data_len = get_zdes_bytes(fd, cfg.namespace_id);
if (data_len == 0) {
fprintf(stderr,
"Zone Descriptor Extensions are not supported\n");
goto close_fd;
} else if (cfg.data_len < 0) {
err = cfg.data_len;
} else if (data_len < 0) {
err = data_len;
goto close_fd;
}
cfg.data_len = data_len;
}
if (posix_memalign(&buf, getpagesize(), cfg.data_len)) {
fprintf(stderr, "can not allocate feature payload\n");
@ -325,8 +432,20 @@ static int zone_mgmt_send(int argc, char **argv, struct command *cmd, struct plu
}
}
err = __zns_mgmt_send(fd, cfg.namespace_id, cfg.zslba, cfg.select_all,
cfg.timeout, cfg.zsa, cfg.data_len, buf);
struct nvme_zns_mgmt_send_args args = {
.args_size = sizeof(args),
.fd = fd,
.nsid = cfg.namespace_id,
.slba = cfg.zslba,
.zsa = cfg.zsa,
.select_all = cfg.select_all,
.zsaso = cfg.zsaso,
.data_len = cfg.data_len,
.data = buf,
.timeout = cfg.timeout,
.result = NULL,
};
err = nvme_zns_mgmt_send(&args);
if (!err)
printf("zone-mgmt-send: Success, action:%d zone:%"PRIx64" "
"all:%d nsid:%d\n",
@ -344,7 +463,7 @@ free:
free(buf);
close_fd:
close(fd);
return nvme_status_to_errno(err, false);
return err;
}
static int close_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@ -364,8 +483,67 @@ static int finish_zone(int argc, char **argv, struct command *cmd, struct plugin
static int open_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Open zones\n";
const char *zslba = "starting LBA of the zone for this command";
const char *zrwaa = "Allocate Zone Random Write Area to zone";
const char *select_all = "send command to all zones";
const char *timeout = "timeout value, in milliseconds";
return zns_mgmt_send(argc, argv, cmd, plugin, desc, NVME_ZNS_ZSA_OPEN);
int err, fd;
struct config {
__u64 zslba;
__u32 namespace_id;
bool zrwaa;
bool select_all;
__u32 timeout;
};
struct config cfg = {
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_SUFFIX("start-lba", 's', &cfg.zslba, zslba),
OPT_FLAG("zrwaa", 'r', &cfg.zrwaa, zrwaa),
OPT_FLAG("select-all", 'a', &cfg.select_all, select_all),
OPT_UINT("timeout", 't', &cfg.timeout, timeout),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return errno;
if (!cfg.namespace_id) {
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
struct nvme_zns_mgmt_send_args args = {
.args_size = sizeof(args),
.fd = fd,
.nsid = cfg.namespace_id,
.slba = cfg.zslba,
.zsa = NVME_ZNS_ZSA_OPEN,
.select_all = cfg.select_all,
.zsaso = cfg.zrwaa,
.data_len = 0,
.data = NULL,
.timeout = cfg.timeout,
.result = NULL,
};
err = nvme_zns_mgmt_send(&args);
if (!err)
printf("zns-open-zone: Success zone slba:%"PRIx64" nsid:%d\n",
(uint64_t)cfg.zslba, cfg.namespace_id);
else
nvme_show_status(err);
close_fd:
close(fd);
return err;
}
static int reset_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@ -386,15 +564,17 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
{
const char *desc = "Set Zone Descriptor Extension\n";
const char *zslba = "starting LBA of the zone for this command";
const char *zrwaa = "Allocate Zone Random Write Area to zone";
const char *data = "optional file for zone extention data (default stdin)";
const char *timeout = "timeout value, in milliseconds";
int fd, ffd = STDIN_FILENO, err;
void *buf = NULL;
__u32 data_len;
int data_len;
struct config {
__u64 zslba;
bool zrwaa;
__u32 namespace_id;
char *file;
__u32 timeout;
@ -405,6 +585,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_SUFFIX("start-lba", 's', &cfg.zslba, zslba),
OPT_FLAG("zrwaa", 'r', &cfg.zrwaa, zrwaa),
OPT_FILE("data", 'd', &cfg.file, data),
OPT_UINT("timeout", 't', &cfg.timeout, timeout),
OPT_END()
@ -415,7 +596,7 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
return errno;
if (!cfg.namespace_id) {
err = cfg.namespace_id = nvme_get_nsid(fd);
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
@ -454,8 +635,20 @@ static int set_zone_desc(int argc, char **argv, struct command *cmd, struct plug
goto close_ffd;
}
err = __zns_mgmt_send(fd, cfg.namespace_id, cfg.zslba, 0, cfg.timeout,
NVME_ZNS_ZSA_SET_DESC_EXT, data_len, buf);
struct nvme_zns_mgmt_send_args args = {
.args_size = sizeof(args),
.fd = fd,
.nsid = cfg.namespace_id,
.slba = cfg.zslba,
.zsa = NVME_ZNS_ZSA_SET_DESC_EXT,
.select_all = 0,
.zsaso = cfg.zrwaa,
.data_len = data_len,
.data = buf,
.timeout = cfg.timeout,
.result = NULL,
};
err = nvme_zns_mgmt_send(&args);
if (!err)
printf("set-zone-desc: Success, zone:%"PRIx64" nsid:%d\n",
(uint64_t)cfg.zslba, cfg.namespace_id);
@ -470,7 +663,67 @@ free:
free(buf);
close_fd:
close(fd);
return nvme_status_to_errno(err, false);
return err;
}
static int zrwa_flush_zone(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Flush Explicit ZRWA Range";
const char *slba = "LBA to flush up to";
const char *timeout = "timeout value, in milliseconds";
int err, fd;
struct config {
__u64 lba;
__u32 namespace_id;
__u32 timeout;
};
struct config cfg = {};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_SUFFIX("lba", 'l', &cfg.lba, slba),
OPT_UINT("timeout", 't', &cfg.timeout, timeout),
OPT_END()
};
fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
return errno;
if (!cfg.namespace_id) {
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
struct nvme_zns_mgmt_send_args args = {
.args_size = sizeof(args),
.fd = fd,
.nsid = cfg.namespace_id,
.slba = cfg.lba,
.zsa = NVME_ZNS_ZSA_ZRWA_FLUSH,
.select_all = 0,
.zsaso = 0,
.data_len = 0,
.data = NULL,
.timeout = cfg.timeout,
.result = NULL,
};
err = nvme_zns_mgmt_send(&args);
if (!err)
printf("zrwa-flush-zone: Success, lba:%"PRIx64" nsid:%d\n",
(uint64_t)cfg.lba, cfg.namespace_id);
else
nvme_show_status(err);
close_fd:
close(fd);
return err;
}
static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@ -520,7 +773,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu
goto close_fd;
if (!cfg.namespace_id) {
err = cfg.namespace_id = nvme_get_nsid(fd);
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
@ -541,8 +794,20 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu
}
}
err = nvme_zns_mgmt_recv(fd, cfg.namespace_id, cfg.zslba, cfg.zra,
cfg.zrasf, cfg.partial, cfg.data_len, data);
struct nvme_zns_mgmt_recv_args args = {
.args_size = sizeof(args),
.fd = fd,
.nsid = cfg.namespace_id,
.slba = cfg.zslba,
.zra = cfg.zra,
.zrasf = cfg.zrasf,
.zras_feat = cfg.partial,
.data_len = cfg.data_len,
.data = data,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = NULL,
};
err = nvme_zns_mgmt_recv(&args);
if (!err)
printf("zone-mgmt-recv: Success, action:%d zone:%"PRIx64" nsid:%d\n",
cfg.zra, (uint64_t)cfg.zslba, cfg.namespace_id);
@ -554,7 +819,7 @@ static int zone_mgmt_recv(int argc, char **argv, struct command *cmd, struct plu
free(data);
close_fd:
close(fd);
return nvme_status_to_errno(err, false);
return err;
}
static int report_zones(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@ -584,6 +849,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
struct nvme_id_ns id_ns;
uint8_t lbaf;
__le64 zsze;
struct json_object *zone_list = 0;
struct config {
char *output_format;
@ -591,7 +857,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
__u32 namespace_id;
int num_descs;
int state;
int verbose;
bool verbose;
bool extended;
bool partial;
};
@ -624,7 +890,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
flags |= VERBOSE;
if (!cfg.namespace_id) {
err = cfg.namespace_id = nvme_get_nsid(fd);
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
@ -639,7 +905,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
}
}
err = nvme_identify_ns(fd, cfg.namespace_id, false, &id_ns);
err = nvme_identify_ns(fd, cfg.namespace_id, &id_ns);
if (err) {
nvme_show_status(err);
goto close_fd;
@ -648,7 +914,7 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
err = nvme_zns_identify_ns(fd, cfg.namespace_id, &id_zns);
if (!err) {
/* get zsze field from zns id ns data - needed for offset calculation */
lbaf = id_ns.flbas & NVME_NS_FLBAS_LBA_MASK;
nvme_id_ns_flbas_to_lbaf_inuse(id_ns.flbas, &lbaf);
zsze = le64_to_cpu(id_zns.lbafe[lbaf].zsze);
}
else {
@ -664,7 +930,9 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
}
err = nvme_zns_report_zones(fd, cfg.namespace_id, 0,
0, cfg.state, 0, log_len, buff);
cfg.state, false, false,
log_len, buff,
NVME_DEFAULT_IOCTL_TIMEOUT, NULL);
if (err > 0) {
nvme_show_status(err);
goto free_buff;
@ -695,7 +963,10 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
}
offset = cfg.zslba;
printf("nr_zones: %"PRIu64"\n", (uint64_t)le64_to_cpu(total_nr_zones));
if (flags & JSON)
zone_list = json_create_array();
else
printf("nr_zones: %"PRIu64"\n", (uint64_t)le64_to_cpu(total_nr_zones));
while (nr_zones_retrieved < nr_zones) {
if (nr_zones_retrieved >= nr_zones)
@ -707,27 +978,32 @@ static int report_zones(int argc, char **argv, struct command *cmd, struct plugi
}
err = nvme_zns_report_zones(fd, cfg.namespace_id, offset,
cfg.extended, cfg.state, cfg.partial, log_len, report);
cfg.state, cfg.extended,
cfg.partial, log_len, report,
NVME_DEFAULT_IOCTL_TIMEOUT, NULL);
if (err > 0) {
nvme_show_status(err);
break;
}
if (!err)
nvme_show_zns_report_zones(report, nr_zones_chunks, zdes,
log_len, flags);
nvme_show_zns_report_zones(report, nr_zones_chunks,
zdes, log_len, flags, zone_list);
nr_zones_retrieved += nr_zones_chunks;
offset = (nr_zones_retrieved * zsze);
}
if (flags & JSON)
json_nvme_finish_zone_list(total_nr_zones, zone_list);
nvme_free(report, huge);
free_buff:
free(buff);
close_fd:
close(fd);
return nvme_status_to_errno(err, false);
return err;
}
static int zone_append(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@ -754,6 +1030,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
void *buf = NULL, *mbuf = NULL;
__u16 nblocks, control = 0;
__u64 result;
__u8 lba_index;
struct timeval start_time, end_time;
struct nvme_id_ns ns;
@ -764,15 +1041,15 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
__u64 zslba;
__u64 data_size;
__u64 metadata_size;
int limited_retry;
int fua;
bool limited_retry;
bool fua;
__u32 namespace_id;
__u32 ref_tag;
__u16 lbat;
__u16 lbatm;
__u8 prinfo;
int piremap;
int latency;
bool piremap;
bool latency;
};
struct config cfg = {};
@ -806,49 +1083,50 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
}
if (!cfg.namespace_id) {
err = cfg.namespace_id = nvme_get_nsid(fd);
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
err = nvme_identify_ns(fd, cfg.namespace_id, false, &ns);
err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
if (err) {
nvme_show_status(err);
goto close_fd;
}
lba_size = 1 << ns.lbaf[(ns.flbas & 0x0f)].ds;
nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index);
lba_size = 1 << ns.lbaf[lba_index].ds;
if (cfg.data_size & (lba_size - 1)) {
fprintf(stderr,
"Data size:%#"PRIx64" not aligned to lba size:%#x\n",
(uint64_t)cfg.data_size, lba_size);
errno = EINVAL;
goto close_ns;
goto close_fd;
}
meta_size = ns.lbaf[(ns.flbas & 0x0f)].ms;
meta_size = ns.lbaf[lba_index].ms;
if (meta_size && !(meta_size == 8 && (cfg.prinfo & 0x8)) &&
(!cfg.metadata_size || cfg.metadata_size % meta_size)) {
fprintf(stderr,
"Metadata size:%#"PRIx64" not aligned to metadata size:%#x\n",
(uint64_t)cfg.metadata_size, meta_size);
errno = EINVAL;
goto close_ns;
goto close_fd;
}
if (cfg.prinfo > 0xf) {
fprintf(stderr, "Invalid value for prinfo:%#x\n", cfg.prinfo);
errno = EINVAL;
goto close_ns;
goto close_fd;
}
if (cfg.data) {
dfd = open(cfg.data, O_RDONLY);
if (dfd < 0) {
perror(cfg.data);
goto close_ns;
goto close_fd;
}
}
@ -870,7 +1148,7 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
if (mfd < 0) {
perror(cfg.metadata);
err = -1;
goto close_dfd;
goto free_data;
}
}
@ -893,17 +1171,32 @@ static int zone_append(int argc, char **argv, struct command *cmd, struct plugin
nblocks = (cfg.data_size / lba_size) - 1;
control |= (cfg.prinfo << 10);
if (cfg.limited_retry)
control |= NVME_RW_LR;
control |= NVME_IO_LR;
if (cfg.fua)
control |= NVME_RW_FUA;
control |= NVME_IO_FUA;
if (cfg.piremap)
control |= NVME_RW_PIREMAP;
control |= NVME_IO_ZNS_APPEND_PIREMAP;
struct nvme_zns_append_args args = {
.args_size = sizeof(args),
.fd = fd,
.nsid = cfg.namespace_id,
.zslba = cfg.zslba,
.nlb = nblocks,
.control = control,
.ilbrt = cfg.ref_tag,
.lbat = cfg.lbat,
.lbatm = cfg.lbatm,
.data_len = cfg.data_size,
.data = buf,
.metadata_len = cfg.metadata_size,
.metadata = mbuf,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.result = &result,
};
gettimeofday(&start_time, NULL);
err = nvme_zns_append(fd, cfg.namespace_id, cfg.zslba, nblocks,
control, cfg.ref_tag, cfg.lbat, cfg.lbatm,
cfg.data_size, buf, cfg.metadata_size, mbuf,
&result);
err = nvme_zns_append(&args);
gettimeofday(&end_time, NULL);
if (cfg.latency)
printf(" latency: zone append: %llu us\n",
@ -926,10 +1219,9 @@ free_data:
close_dfd:
if (cfg.data)
close(dfd);
close_ns:
close_fd:
close(fd);
return nvme_status_to_errno(err, false);
return err;
}
static int changed_zone_list(int argc, char **argv, struct command *cmd, struct plugin *plugin)
@ -967,15 +1259,14 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct
goto close_fd;
if (!cfg.namespace_id) {
err = cfg.namespace_id = nvme_get_nsid(fd);
err = nvme_get_nsid(fd, &cfg.namespace_id);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
err = nvme_get_log(fd, cfg.namespace_id, NVME_LOG_ZONE_CHANGED_LIST,
cfg.rae, NVME_NO_LOG_LSP, sizeof(log), &log);
err = nvme_get_log_zns_changed_zones(fd, cfg.namespace_id, cfg.rae, &log);
if (!err)
nvme_show_zns_changed(&log, flags);
else if (err > 0)
@ -985,5 +1276,5 @@ static int changed_zone_list(int argc, char **argv, struct command *cmd, struct
close_fd:
close(fd);
return nvme_status_to_errno(err, false);
return err;
}

View file

@ -8,23 +8,24 @@
PLUGIN(NAME("zns", "Zoned Namespace Command Set", NVME_VERSION),
COMMAND_LIST(
ENTRY("id-ctrl", "Retrieve ZNS controller identification", id_ctrl)
ENTRY("id-ns", "Retrieve ZNS namespace identification", id_ns)
ENTRY("zone-mgmt-recv", "Sends the zone management receive command", zone_mgmt_recv)
ENTRY("zone-mgmt-send", "Sends the zone management send command", zone_mgmt_send)
ENTRY("report-zones", "Retrieve the Report Zones report", report_zones)
ENTRY("close-zone", "Closes one or more zones", close_zone)
ENTRY("finish-zone", "Finishes one or more zones", finish_zone)
ENTRY("open-zone", "Opens one or more zones", open_zone)
ENTRY("reset-zone", "Resets one or more zones", reset_zone)
ENTRY("offline-zone", "Offlines one or more zones", offline_zone)
ENTRY("set-zone-desc", "Attaches zone descriptor extension data", set_zone_desc)
ENTRY("zone-append", "Writes data and metadata (if applicable), appended to the end of the requested zone", zone_append)
ENTRY("changed-zone-list", "Retrieves the changed zone list log", changed_zone_list)
ENTRY("list", "List all NVMe devices with Zoned Namespace Command Set support", list)
ENTRY("id-ctrl", "Send NVMe Identify Zoned Namespace Controller, display structure", id_ctrl)
ENTRY("id-ns", "Send NVMe Identify Zoned Namespace Namespace, display structure", id_ns)
ENTRY("report-zones", "Report zones associated to a Zoned Namespace", report_zones)
ENTRY("reset-zone", "Reset one or more zones", reset_zone)
ENTRY("close-zone", "Close one or more zones", close_zone)
ENTRY("finish-zone", "Finishe one or more zones", finish_zone)
ENTRY("open-zone", "Open one or more zones", open_zone)
ENTRY("offline-zone", "Offline one or more zones", offline_zone)
ENTRY("set-zone-desc", "Attach zone descriptor extension data to a zone", set_zone_desc)
ENTRY("zrwa-flush-zone", "Flush LBAs associated with a ZRWA to a zone.", zrwa_flush_zone)
ENTRY("changed-zone-list", "Retrieve the changed zone list log", changed_zone_list)
ENTRY("zone-mgmt-recv", "Send the zone management receive command", zone_mgmt_recv)
ENTRY("zone-mgmt-send", "Send the zone management send command", zone_mgmt_send)
ENTRY("zone-append", "Append data and metadata (if applicable) to a zone", zone_append)
)
);
#endif
#include "define_cmd.h"