Adding upstream version 2.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
50aec1e4c5
commit
1b3a431c1d
521 changed files with 21541 additions and 21644 deletions
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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"
|
|
@ -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
21
plugins/meson.build
Normal 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
|
@ -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)
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
788
plugins/ocp/ocp-nvme.c
Normal 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
25
plugins/ocp/ocp-nvme.h
Normal 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"
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue