1
0
Fork 0

Adding upstream version 1.16.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-16 12:13:36 +01:00
parent 90b6101daf
commit 50aec1e4c5
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
345 changed files with 7594 additions and 7512 deletions

512
nvme.c
View file

@ -365,18 +365,25 @@ ret:
return nvme_status_to_errno(err, false);
}
__u16 get_feat_buf_len(unsigned short feature) {
return nvme_feat_buf_len[feature];
}
static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Retrieve telemetry log and write to binary file";
const char *fname = "File name to save raw binary, includes header";
const char *hgen = "Have the host tell the controller to generate the report";
const char *cgen = "Gather report generated by the controller.";
const char *dgen = "Pick which telemetry data area to report. Default is all. Valid options are 1, 2, 3.";
const char *dgen = "Pick which telemetry data area to report. Default is 3 to fetch areas 1-3. Valid options are 1, 2, 3, 4.";
const size_t bs = 512;
struct nvme_telemetry_log_page_hdr *hdr;
struct nvme_id_ctrl ctrl;
size_t full_size, offset = bs;
int err = -1, fd, output;
void *page_log;
__u32 result;
void *buf = NULL;
struct config {
char *file_name;
@ -454,6 +461,46 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
case 3:
full_size = (le16_to_cpu(hdr->dalb3) * bs) + offset;
break;
case 4:
err = nvme_identify_ctrl(fd, &ctrl);
if (err) {
perror("identify-ctrl");
goto close_output;
}
if (posix_memalign(&buf, getpagesize(), nvme_feat_buf_len[NVME_FEAT_HOST_BEHAVIOR])) {
fprintf(stderr, "can not allocate feature payload\n");
errno = ENOMEM;
err = -1;
goto close_output;
}
memset(buf, 0, nvme_feat_buf_len[NVME_FEAT_HOST_BEHAVIOR]);
err = nvme_get_feature(fd, NVME_NSID_ALL, NVME_FEAT_HOST_BEHAVIOR, 0, 0,
0, nvme_feat_buf_len[NVME_FEAT_HOST_BEHAVIOR], buf, &result);
if (err > 0) {
nvme_show_status(err);
} else if (err < 0) {
perror("get-feature");
} else {
if ((ctrl.lpa & 0x40)) {
if (((unsigned char *)buf)[1] == 1)
full_size = (le32_to_cpu(hdr->dalb4) * bs) + offset;
else {
fprintf(stderr, "Data area 4 unsupported, Host Behavior Support ETDAS not set to 1\n");
errno = EINVAL;
err = -1;
}
} else {
fprintf(stderr, "Data area 4 unsupported, bit 6 of Log Page Attributes not set\n");
errno = EINVAL;
err = -1;
}
}
free(buf);
if (err)
goto close_output;
break;
default:
fprintf(stderr, "Invalid data area requested\n");
errno = EINVAL;
@ -593,6 +640,56 @@ ret:
return nvme_status_to_errno(err, false);
}
static int get_supported_log_pages(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
const char *desc = "Retrieve supported logs and print the table.";
const char *verbose = "Increase output verbosity";
struct nvme_support_log_pages supports;
int err = -1, fd;
enum nvme_print_flags flags;
struct config {
int verbose;
char *output_format;
};
struct config cfg = {
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_FLAG("verbose", 'v', &cfg.verbose, verbose),
OPT_END()
};
err = fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
goto ret;
err = flags = validate_output_format(cfg.output_format);
if (flags < 0)
goto close_fd;
if (cfg.verbose)
flags |= VERBOSE;
err = nvme_supported_log(fd, &supports);
if (!err)
nvme_show_supported_log(&supports, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
perror("supported log pages");
close_fd:
close(fd);
ret:
return nvme_status_to_errno(err, false);
}
static int get_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Retrieve specified number of "\
@ -929,7 +1026,7 @@ static int get_persistent_event_log(int argc, char **argv,
const char *log_len = "number of bytes to retrieve";
const char *raw = "use binary output";
void *pevent_log_info;
struct nvme_persistent_event_log_head *pevent_log_head = NULL;
struct nvme_persistent_event_log_head *pevent_log_head, *collected_head;
enum nvme_print_flags flags;
int err = -1, fd;
bool huge;
@ -985,22 +1082,22 @@ static int get_persistent_event_log(int argc, char **argv,
sizeof(*pevent_log_head), pevent_log_head);
if (err < 0) {
perror("persistent event log");
goto close_fd;
goto free_head;
} else if (err) {
nvme_show_status(err);
goto close_fd;
goto free_head;
}
if (cfg.action == NVME_PEVENT_LOG_RELEASE_CTX) {
printf("Releasing Persistent Event Log Context\n");
goto close_fd;
goto free_head;
}
if (!cfg.log_len && cfg.action != NVME_PEVENT_LOG_EST_CTX_AND_READ) {
cfg.log_len = le64_to_cpu(pevent_log_head->tll);
} else if (!cfg.log_len && cfg.action == NVME_PEVENT_LOG_EST_CTX_AND_READ) {
printf("Establishing Persistent Event Log Context\n");
goto close_fd;
goto free_head;
}
/*
@ -1018,22 +1115,39 @@ static int get_persistent_event_log(int argc, char **argv,
perror("could not alloc buffer for persistent event log page\n");
errno = ENOMEM;
err = -1;
goto close_fd;
goto free_head;
}
err = nvme_persistent_event_log(fd, cfg.action,
cfg.log_len, pevent_log_info);
if (!err)
if (!err) {
err = nvme_persistent_event_log(fd, cfg.action,
sizeof(*pevent_log_head), pevent_log_head);
if (err < 0) {
perror("persistent event log");
goto free;
} else if (err) {
nvme_show_status(err);
goto free;
}
collected_head = pevent_log_info;
if(collected_head->gen_number != pevent_log_head->gen_number) {
printf("Collected Persistent Event Log may be invalid, "\
"Re-read the log is reiquired\n");
goto free;
}
nvme_show_persistent_event_log(pevent_log_info, cfg.action,
cfg.log_len, devicename, flags);
}
else if (err > 0)
nvme_show_status(err);
else
perror("persistent event log");
free:
nvme_free(pevent_log_info, huge);
close_fd:
free_head:
free(pevent_log_head);
close_fd:
close(fd);
ret:
return nvme_status_to_errno(err, false);
@ -1249,6 +1363,113 @@ ret:
}
static int get_boot_part_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Retrieve Boot Partition " \
"log page and prints it, for the given " \
"device in either decoded format(default), " \
"json or binary.";
const char *lsp = "log specific field";
const char *fname = "boot partition data output file name";
struct nvme_boot_part_hdr boot;
__u8 *bp_log;
enum nvme_print_flags flags;
int err = -1, fd = 0, output = 0;
__u32 bpsz = 0;
struct config {
__u8 lsp;
char *output_format;
char *file_name;
};
struct config cfg = {
.lsp = 0,
.file_name = NULL,
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_BYTE("lsp", 's', &cfg.lsp, lsp),
OPT_FILE("output-file", 'f', &cfg.file_name, fname),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_END()
};
err = fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
goto ret;
err = flags = validate_output_format(cfg.output_format);
if (flags < 0)
goto close_fd;
if (!cfg.file_name) {
fprintf(stderr, "Please provide an output file!\n");
errno = EINVAL;
err = -1;
goto close_fd;
}
if (cfg.lsp > 128) {
fprintf(stderr, "invalid lsp param: %u\n", cfg.lsp);
errno = EINVAL;
err = -1;
goto close_fd;
}
output = open(cfg.file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (output < 0) {
fprintf(stderr, "Failed to open output file %s: %s!\n",
cfg.file_name, strerror(errno));
err = output;
goto close_fd;
}
err = nvme_boot_part_log(fd, cfg.lsp, &boot, sizeof(boot));
if (err < 0) {
perror("boot partition log");
goto close_output;
} else if (err) {
nvme_show_status(err);
goto close_output;
}
bpsz = (boot.bpinfo & 0x7fff) * 128 * 1024;
bp_log = calloc(sizeof(boot) + bpsz, 1);
if (!bp_log) {
perror("could not alloc buffer for boot partition log");
errno = ENOMEM;
err = -1;
goto close_output;
}
err = nvme_boot_part_log(fd, cfg.lsp, &bp_log, sizeof(boot) + bpsz);
if (!err)
nvme_show_boot_part_log(&bp_log, devicename, flags, sizeof(boot) + bpsz);
else if (err > 0)
nvme_show_status(err);
else
perror("boot partition log");
err = write(output, (void *) bp_log + sizeof(boot), bpsz);
if (err != bpsz) {
fprintf(stderr, "Failed to flush all data to file!\n");
} else {
printf("Data flushed into file %s\n", cfg.file_name);
}
err = 0;
free(bp_log);
close_output:
close(output);
close_fd:
close(fd);
ret:
return nvme_status_to_errno(err, false);
}
static int get_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Retrieve desired number of bytes "\
@ -1428,6 +1649,53 @@ ret:
return nvme_status_to_errno(err, false);
}
static int get_fid_support_effects_log(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
const char *desc = "Retrieve FID Support and Effects log and show it.";
const char *human_readable = "show log in readable format";
struct nvme_fid_support_effects fid_support_log;
enum nvme_print_flags flags;
int fd, err = -1;
struct config {
int human_readable;
char *output_format;
};
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()
};
err = fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
goto ret;
err = flags = validate_output_format(cfg.output_format);
if (flags < 0)
goto close_fd;
if (cfg.human_readable)
flags |= VERBOSE;
err = nvme_fid_support_effects_log(fd, &fid_support_log);
if (!err)
nvme_show_fid_support_effects_log(&fid_support_log, devicename, flags);
else if (err > 0)
nvme_show_status(err);
else
perror("fid support effects log");
close_fd:
close(fd);
ret:
return nvme_status_to_errno(err, false);
}
static int list_ctrl(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Show controller list information for the subsystem the "\
@ -1554,6 +1822,67 @@ ret:
return nvme_status_to_errno(err, false);
}
static int id_endurance_grp_list(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
{
const char *desc = "Show endurance group list information for the given endurance "\
"group id";
const char *endurance_grp_id = "Endurance Group ID";
int err = -1, fd;
struct nvme_endurance_group_list *endgrp_list;
enum nvme_print_flags flags;
struct config {
__u16 endgrp_id;
char *output_format;
};
struct config cfg = {
.endgrp_id = 0,
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_SHRT("endgrp-id", 'i', &cfg.endgrp_id, endurance_grp_id),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_END()
};
err = fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
goto ret;
err = flags = validate_output_format(cfg.output_format);
if (flags < 0)
goto close_fd;
if (flags != JSON && flags != NORMAL) {
err = -EINVAL;
fprintf(stderr, "invalid output format\n");
goto close_fd;
}
if (posix_memalign((void *)&endgrp_list, getpagesize(), 0x1000)) {
fprintf(stderr, "can not allocate memory for endurance gropu list\n");
errno = ENOMEM;
err = -1;
goto close_fd;
}
err = nvme_identify_endurance_group_list(fd, cfg.endgrp_id, endgrp_list);
if (!err)
nvme_show_endurance_group_list(endgrp_list, flags);
else if (err > 0)
nvme_show_status(err);
else
perror("id endurance group list");
free(endgrp_list);
close_fd:
close(fd);
ret:
return nvme_status_to_errno(err, false);
}
static int delete_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Delete the given namespace by "\
@ -2224,6 +2553,73 @@ ret:
return nvme_status_to_errno(err, false);
}
static int cmd_set_independent_id_ns(int argc, char **argv,
struct command *cmd, struct plugin *plugin)
{
const char *desc = "Send an I/O Command Set Independent Identify "\
"Namespace command to the given device, returns properties of the "\
"specified namespace in human-readable or binary or json format.";
const char *raw = "show identify in binary format";
const char *human_readable = "show identify in readable format";
const char *namespace_id = "identifier of desired namespace";
enum nvme_print_flags flags;
struct nvme_cmd_set_independent_id_ns ns;
int err = -1, fd;
struct config {
__u32 namespace_id;
int raw_binary;
int human_readable;
char *output_format;
};
struct config cfg = {
.namespace_id = 0,
.output_format = "normal",
};
OPT_ARGS(opts) = {
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
OPT_FLAG("human-readable", 'H', &cfg.human_readable, human_readable),
OPT_END()
};
err = fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
goto ret;
err = flags = validate_output_format(cfg.output_format);
if (flags < 0)
goto close_fd;
if (cfg.raw_binary)
flags = BINARY;
if (cfg.human_readable)
flags |= VERBOSE;
if (!cfg.namespace_id) {
err = cfg.namespace_id = nvme_get_nsid(fd);
if (err < 0) {
perror("get-namespace-id");
goto close_fd;
}
}
err = nvme_cmd_set_independent_identify_ns(fd, cfg.namespace_id, &ns);
if (!err)
nvme_show_cmd_set_independent_id_ns(&ns, cfg.namespace_id, flags);
else if (err > 0)
nvme_show_status(err);
else
perror("I/O command set independent identify namespace");
close_fd:
close(fd);
ret:
return nvme_status_to_errno(err, false);
}
static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Send an Identify Namespace Granularity List command to the "\
@ -5244,7 +5640,7 @@ static int submit_io(int opcode, char *command, const char *desc,
gettimeofday(&start_time, NULL);
err = nvme_io(fd, opcode, cfg.namespace_id, cfg.start_block, cfg.block_count,
control, dsmgmt, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask,
cfg.storage_tag, buffer, mbuffer);
cfg.storage_tag, buffer, buffer_size, mbuffer, mbuffer_size);
gettimeofday(&end_time, NULL);
if (cfg.latency)
printf(" latency: %s: %llu us\n",
@ -5788,6 +6184,100 @@ static int rpmb_cmd(int argc, char **argv, struct command *cmd, struct plugin *p
return rpmb_cmd_option(argc, argv, cmd, plugin);
}
static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "The Lockdown command is used to control the "\
"Command and Feature Lockdown capability which configures the "\
"prohibition or allowance of execution of the specified command "\
"or Set Features command targeting a specific Feature Identifier.";
const char *ofi_desc = "Opcode or Feature Identifier(OFI) "\
"specifies the command opcode or Set Features Feature Identifier "\
"identified by the Scope field.";
const char *ifc_desc = "[0-3] Interface (INF) field identifies the "\
"interfaces affected by this command.";
const char *prhbt_desc = "[0-1]Prohibit(PRHBT) bit specifies whether "\
"to prohibit or allow the command opcode or Set Features Feature "\
"Identifier specified by this command.";
const char *scp_desc = "[0-15]Scope(SCP) field specifies the contents "\
"of the Opcode or Feature Identifier field.";
const char *uuid_desc = "UUID Index - If this field is set to a non-zero "\
"value, then the value of this field is the index of a UUID in the UUID "\
"List that is used by the command.If this field is cleared to 0h,"\
"then no UUID index is specified";
int fd, err = -1;
struct config {
__u8 ofi;
__u8 ifc;
__u8 prhbt;
__u8 scp;
__u8 uuid;
};
struct config cfg = {
.ofi = 0,
.ifc = 0,
.prhbt = 0,
.scp = 0,
.uuid = 0,
};
OPT_ARGS(opts) = {
OPT_BYTE("ofi", 'o', &cfg.ofi, ofi_desc),
OPT_BYTE("ifc", 'f', &cfg.ifc, ifc_desc),
OPT_BYTE("prhbt", 'p', &cfg.prhbt, prhbt_desc),
OPT_BYTE("scp", 's', &cfg.scp, scp_desc),
OPT_BYTE("uuid", 'U', &cfg.uuid, uuid_desc),
OPT_END()
};
err = fd = parse_and_open(argc, argv, desc, opts);
if (fd < 0)
goto ret;
/* check for input arguement limit */
if (cfg.ifc > 3) {
fprintf(stderr, "invalid interface settings:%d\n", cfg.ifc);
errno = EINVAL;
err = -1;
goto close_fd;
}
if (cfg.prhbt > 1) {
fprintf(stderr, "invalid prohibit settings:%d\n", cfg.prhbt);
errno = EINVAL;
err = -1;
goto close_fd;
}
if (cfg.scp > 15) {
fprintf(stderr, "invalid scope settings:%d\n", cfg.scp);
errno = EINVAL;
err = -1;
goto close_fd;
}
if (cfg.uuid > 127) {
fprintf(stderr, "invalid UUID index settings:%d\n", cfg.uuid);
errno = EINVAL;
err = -1;
goto close_fd;
}
err = nvme_lockdown(fd, cfg.scp,cfg.prhbt,cfg.ifc,cfg.ofi,
cfg.uuid);
if (err < 0)
perror("lockdown");
else if (err > 0)
nvme_show_status(err);
else
printf("Lockdown Command is Successful\n");
close_fd:
close(fd);
ret:
return nvme_status_to_errno(err, false);
}
static int passthru(int argc, char **argv, int ioctl_cmd, uint8_t cmd_type,
const char *desc, struct command *cmd)
{