Merging upstream version 2.1~rc0 (Closes: #1015722).
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
9489161ac8
commit
316e846c86
504 changed files with 6751 additions and 2957 deletions
329
nvme.c
329
nvme.c
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* nvme.c -- NVM-Express command line utility.
|
||||
*
|
||||
|
@ -369,23 +370,26 @@ static int get_ana_log(int argc, char **argv, struct command *cmd,
|
|||
{
|
||||
const char *desc = "Retrieve ANA log for the given device in " \
|
||||
"decoded format (default), json or binary.";
|
||||
const char *groups = "Return ANA groups only.";
|
||||
void *ana_log;
|
||||
int err = -1, fd;
|
||||
int groups = 0; /* Right now get all the per ANA group NSIDS */
|
||||
size_t ana_log_len;
|
||||
struct nvme_id_ctrl ctrl;
|
||||
enum nvme_print_flags flags;
|
||||
enum nvme_log_ana_lsp lsp;
|
||||
|
||||
struct config {
|
||||
bool groups;
|
||||
char *output_format;
|
||||
};
|
||||
|
||||
struct config cfg = {
|
||||
.groups = false,
|
||||
.output_format = "normal",
|
||||
};
|
||||
|
||||
OPT_ARGS(opts) = {
|
||||
OPT_FLAG("groups", 'g', &cfg.groups, groups),
|
||||
OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
|
||||
OPT_END()
|
||||
};
|
||||
|
@ -416,8 +420,8 @@ static int get_ana_log(int argc, char **argv, struct command *cmd,
|
|||
goto close_fd;
|
||||
}
|
||||
|
||||
lsp = groups ? NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY :
|
||||
NVME_LOG_ANA_LSP_RGO_NAMESPACES;
|
||||
lsp = cfg.groups ? NVME_LOG_ANA_LSP_RGO_GROUPS_ONLY :
|
||||
NVME_LOG_ANA_LSP_RGO_NAMESPACES;
|
||||
|
||||
err = nvme_get_log_ana(fd, lsp, true, 0, ana_log_len, ana_log);
|
||||
if (!err) {
|
||||
|
@ -583,18 +587,22 @@ ret:
|
|||
return err;
|
||||
}
|
||||
|
||||
void collect_effects_log(int fd, enum nvme_csi csi, struct list_head *list, int flags)
|
||||
static int collect_effects_log(int fd, enum nvme_csi csi,
|
||||
struct list_head *list, int flags)
|
||||
{
|
||||
nvme_effects_log_node_t *node;
|
||||
int err;
|
||||
nvme_effects_log_node_t *node = malloc(sizeof(nvme_effects_log_node_t));
|
||||
|
||||
node = malloc(sizeof(nvme_effects_log_node_t));
|
||||
if (!node)
|
||||
return;
|
||||
return -ENOMEM;
|
||||
|
||||
node->csi = csi;
|
||||
|
||||
err = nvme_get_log_cmd_effects(fd, csi, &node->effects);
|
||||
if (!err) {
|
||||
list_add(list, &node->node);
|
||||
return;
|
||||
return err;
|
||||
}
|
||||
else if (err > 0)
|
||||
nvme_show_status(err);
|
||||
|
@ -602,6 +610,7 @@ void collect_effects_log(int fd, enum nvme_csi csi, struct list_head *list, int
|
|||
fprintf(stderr, "effects log page: %s\n", nvme_strerror(errno));
|
||||
|
||||
free(node);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int get_effects_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
|
@ -672,29 +681,28 @@ static int get_effects_log(int argc, char **argv, struct command *cmd, struct pl
|
|||
nvme_command_set_supported = NVME_CAP_CSS(cap) & NVME_CAP_CSS_NVM;
|
||||
other_command_sets_supported = NVME_CAP_CSS(cap) & NVME_CAP_CSS_CSI;
|
||||
|
||||
if (nvme_command_set_supported)
|
||||
err = collect_effects_log(fd, NVME_CSI_NVM,
|
||||
&log_pages, flags);
|
||||
|
||||
if (nvme_command_set_supported) {
|
||||
collect_effects_log(fd, NVME_CSI_NVM, &log_pages, flags);
|
||||
}
|
||||
if (!err && other_command_sets_supported)
|
||||
err = collect_effects_log(fd, NVME_CSI_ZNS,
|
||||
&log_pages, flags);
|
||||
|
||||
if (other_command_sets_supported) {
|
||||
collect_effects_log(fd, NVME_CSI_ZNS, &log_pages, flags);
|
||||
}
|
||||
|
||||
nvme_print_effects_log_pages(&log_pages, flags);
|
||||
|
||||
}
|
||||
else {
|
||||
collect_effects_log(fd, cfg.csi, &log_pages, flags);
|
||||
nvme_print_effects_log_pages(&log_pages, flags);
|
||||
} else {
|
||||
err = collect_effects_log(fd, cfg.csi, &log_pages, flags);
|
||||
}
|
||||
|
||||
if (!err)
|
||||
nvme_print_effects_log_pages(&log_pages, flags);
|
||||
else if (err > 0)
|
||||
nvme_show_status(err);
|
||||
else
|
||||
perror("effects log page");
|
||||
|
||||
close_fd:
|
||||
while ((node = list_pop(&log_pages, nvme_effects_log_node_t, node))) {
|
||||
while ((node = list_pop(&log_pages, nvme_effects_log_node_t, node)))
|
||||
free(node);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
ret:
|
||||
return err;
|
||||
|
@ -1154,7 +1162,7 @@ static int get_persistent_event_log(int argc, char **argv,
|
|||
}
|
||||
|
||||
/*
|
||||
* if header aleady read with context establish action 0x1,
|
||||
* if header already read with context establish action 0x1,
|
||||
* action shall not be 0x1 again in the subsequent request,
|
||||
* until the current context is released by issuing action
|
||||
* with 0x2, otherwise throws command sequence error, make
|
||||
|
@ -1184,7 +1192,7 @@ static int get_persistent_event_log(int argc, char **argv,
|
|||
pevent_collected = pevent_log_info;
|
||||
if (pevent_collected->gen_number != pevent->gen_number) {
|
||||
printf("Collected Persistent Event Log may be invalid, "\
|
||||
"Re-read the log is reiquired\n");
|
||||
"Re-read the log is required\n");
|
||||
goto free;
|
||||
}
|
||||
|
||||
|
@ -2434,7 +2442,7 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin *
|
|||
}
|
||||
goto close_fd;
|
||||
}
|
||||
for (i = 0; i < 16; ++i) {
|
||||
for (i = 0; i <= ns.nlbaf; ++i) {
|
||||
if ((1 << ns.lbaf[i].ds) == cfg.bs && ns.lbaf[i].ms == 0) {
|
||||
cfg.flbas = i;
|
||||
break;
|
||||
|
@ -2522,6 +2530,7 @@ static int list_subsys(int argc, char **argv, struct command *cmd,
|
|||
const char *verbose = "Increase output verbosity";
|
||||
nvme_scan_filter_t filter = NULL;
|
||||
int err;
|
||||
int nsid = NVME_NSID_ALL;
|
||||
|
||||
struct config {
|
||||
char *output_format;
|
||||
|
@ -2570,7 +2579,7 @@ static int list_subsys(int argc, char **argv, struct command *cmd,
|
|||
}
|
||||
|
||||
if (devicename) {
|
||||
int subsys_num, nsid;
|
||||
int subsys_num;
|
||||
|
||||
if (sscanf(devicename,"nvme%dn%d",
|
||||
&subsys_num, &nsid) != 2) {
|
||||
|
@ -2588,7 +2597,7 @@ static int list_subsys(int argc, char **argv, struct command *cmd,
|
|||
goto ret;
|
||||
}
|
||||
|
||||
nvme_show_subsystem_list(r, flags);
|
||||
nvme_show_subsystem_list(r, nsid != NVME_NSID_ALL, flags);
|
||||
|
||||
ret:
|
||||
if (r)
|
||||
|
@ -2642,7 +2651,7 @@ static int list(int argc, char **argv, struct command *cmd, struct plugin *plugi
|
|||
}
|
||||
err = nvme_scan_topology(r, NULL, NULL);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Failed to scan topoplogy: %s\n",
|
||||
fprintf(stderr, "Failed to scan topology: %s\n",
|
||||
nvme_strerror(errno));
|
||||
nvme_free_tree(r);
|
||||
return err;
|
||||
|
@ -2983,7 +2992,7 @@ static int id_ns(int argc, char **argv, struct command *cmd, struct plugin *plug
|
|||
"given device, returns properties of the specified namespace "\
|
||||
"in either human-readable or binary format. Can also return "\
|
||||
"binary vendor-specific namespace attributes.";
|
||||
const char *force = "Return this namespace, even if not attaced (1.2 devices only)";
|
||||
const char *force = "Return this namespace, even if not attached (1.2 devices only)";
|
||||
const char *vendor_specific = "dump binary vendor fields";
|
||||
const char *raw = "show identify in binary format";
|
||||
const char *human_readable = "show identify in readable format";
|
||||
|
@ -3173,7 +3182,7 @@ static int id_ns_granularity(int argc, char **argv, struct command *cmd, struct
|
|||
nvme_show_status(err);
|
||||
else
|
||||
fprintf(stderr, "identify namespace granularity: %s\n", nvme_strerror(errno));
|
||||
|
||||
free(granularity_list);
|
||||
close_fd:
|
||||
close(fd);
|
||||
ret:
|
||||
|
@ -3848,7 +3857,7 @@ static int get_feature(int argc, char **argv, struct command *cmd,
|
|||
"specified controller. Operating parameters are grouped "\
|
||||
"and identified by Feature Identifiers; each Feature "\
|
||||
"Identifier contains one or more attributes that may affect "\
|
||||
"behaviour of the feature. Each Feature has three possible "\
|
||||
"behavior of the feature. Each Feature has three possible "\
|
||||
"settings: default, saveable, and current. If a Feature is "\
|
||||
"saveable, it may be modified by set-feature. Default values "\
|
||||
"are vendor-specific and not changeable. Use set-feature to "\
|
||||
|
@ -4536,7 +4545,7 @@ ret:
|
|||
static int set_property(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
const char *desc = "Writes and shows the defined NVMe controller property "\
|
||||
"for NVMe ove Fabric";
|
||||
"for NVMe over Fabric";
|
||||
const char *offset = "the offset of the property";
|
||||
const char *value = "the value of the property to be set";
|
||||
int fd, err;
|
||||
|
@ -4738,7 +4747,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
|
|||
nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &prev_lbaf);
|
||||
|
||||
if (cfg.bs) {
|
||||
for (i = 0; i < 16; ++i) {
|
||||
for (i = 0; i < ns.nlbaf; ++i) {
|
||||
if ((1ULL << ns.lbaf[i].ds) == cfg.bs &&
|
||||
ns.lbaf[i].ms == 0) {
|
||||
cfg.lbaf = i;
|
||||
|
@ -4766,7 +4775,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
|
|||
err = -EINVAL;
|
||||
goto close_fd;
|
||||
}
|
||||
if (cfg.lbaf > 15) {
|
||||
if (cfg.lbaf > 63) {
|
||||
fprintf(stderr, "invalid lbaf:%d\n", cfg.lbaf);
|
||||
err = -EINVAL;
|
||||
goto close_fd;
|
||||
|
@ -4803,7 +4812,8 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
|
|||
.args_size = sizeof(args),
|
||||
.fd = fd,
|
||||
.nsid = cfg.namespace_id,
|
||||
.lbaf = cfg.lbaf,
|
||||
.lbafu = (cfg.lbaf & NVME_NS_FLBAS_HIGHER_MASK) >> 4,
|
||||
.lbaf = cfg.lbaf & NVME_NS_FLBAS_LOWER_MASK,
|
||||
.mset = cfg.ms,
|
||||
.pi = cfg.pi,
|
||||
.pil = cfg.pil,
|
||||
|
@ -5028,7 +5038,8 @@ static int set_feature(int argc, char **argv, struct command *cmd, struct plugin
|
|||
nvme_show_status(err);
|
||||
|
||||
close_ffd:
|
||||
close(ffd);
|
||||
if (ffd != STDIN_FILENO)
|
||||
close(ffd);
|
||||
free:
|
||||
free(buf);
|
||||
close_fd:
|
||||
|
@ -5393,10 +5404,47 @@ ret:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int invalid_tags(__u64 storage_tag, __u64 ref_tag, __u8 sts, __u8 pif)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (sts < 64 && storage_tag >= (1LL << sts)) {
|
||||
fprintf(stderr, "Storage tag larger than storage tag size\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (pif) {
|
||||
case 0:
|
||||
if (ref_tag >= (1LL << (32 - sts)))
|
||||
result = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (sts > 16 && ref_tag >= (1LL << (80 - sts)))
|
||||
result = 1;
|
||||
break;
|
||||
case 2:
|
||||
if (sts > 0 && ref_tag >= (1LL << (64 - sts)))
|
||||
result = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid PIF\n");
|
||||
result = 1;
|
||||
}
|
||||
|
||||
if (result)
|
||||
fprintf(stderr, "Reference tag larger than allowed by PIF\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugin *plugin)
|
||||
{
|
||||
int err, fd;
|
||||
__u16 control = 0;
|
||||
__u8 lba_index, sts = 0, pif = 0;
|
||||
struct nvme_id_ns ns;
|
||||
struct nvme_nvm_id_ns nvm_ns;
|
||||
|
||||
const char *desc = "The Write Zeroes command is used to set a "\
|
||||
"range of logical blocks to zero.";
|
||||
const char *namespace_id = "desired namespace";
|
||||
|
@ -5405,11 +5453,10 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
|
|||
const char *limited_retry = "limit media access attempts";
|
||||
const char *force_unit_access = "force device to commit data before command completes";
|
||||
const char *prinfo = "PI and check field";
|
||||
const char *ref_tag = "reference tag (for end to end PI)";
|
||||
const char *app_tag_mask = "app tag mask (for end to end PI)";
|
||||
const char *app_tag = "app tag (for end to end PI)";
|
||||
const char *storage_tag = "storage tag, CDW2 and CDW3 (00:47) bits "\
|
||||
"(for end to end PI)";
|
||||
const char *ref_tag = "reference tag for end-to-end PI";
|
||||
const char *app_tag_mask = "app tag mask for end-to-end PI";
|
||||
const char *app_tag = "app tag for end-to-end PI";
|
||||
const char *storage_tag = "storage tag for end-to-end PI";
|
||||
const char *deac = "Set DEAC bit, requesting controller to deallocate specified logical blocks";
|
||||
const char *storage_tag_check = "This bit specifies the Storage Tag field shall be checked as "\
|
||||
"part of end-to-end data protection processing";
|
||||
|
@ -5422,7 +5469,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
|
|||
bool limited_retry;
|
||||
bool force_unit_access;
|
||||
__u8 prinfo;
|
||||
__u32 ref_tag;
|
||||
__u64 ref_tag;
|
||||
__u16 app_tag_mask;
|
||||
__u16 app_tag;
|
||||
__u64 storage_tag;
|
||||
|
@ -5452,7 +5499,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
|
|||
OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry),
|
||||
OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access),
|
||||
OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo),
|
||||
OPT_UINT("ref-tag", 'r', &cfg.ref_tag, ref_tag),
|
||||
OPT_SUFFIX("ref-tag", 'r', &cfg.ref_tag, ref_tag),
|
||||
OPT_SHRT("app-tag-mask", 'm', &cfg.app_tag_mask, app_tag_mask),
|
||||
OPT_SHRT("app-tag", 'a', &cfg.app_tag, app_tag),
|
||||
OPT_SUFFIX("storage-tag", 'S', &cfg.storage_tag, storage_tag),
|
||||
|
@ -5477,7 +5524,7 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
|
|||
if (cfg.deac)
|
||||
control |= NVME_IO_DEAC;
|
||||
if (cfg.storage_tag_check)
|
||||
control |= NVME_SC_STORAGE_TAG_CHECK;
|
||||
control |= NVME_IO_STC;
|
||||
if (!cfg.namespace_id) {
|
||||
err = nvme_get_nsid(fd, &cfg.namespace_id);
|
||||
if (err < 0) {
|
||||
|
@ -5486,6 +5533,27 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
|
|||
}
|
||||
}
|
||||
|
||||
err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
|
||||
if (err) {
|
||||
nvme_show_status(err);
|
||||
goto close_fd;
|
||||
} else if (err < 0) {
|
||||
fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno));
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
err = nvme_identify_ns_csi(fd, cfg.namespace_id, 0, NVME_CSI_NVM, &nvm_ns);
|
||||
if (!err) {
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index);
|
||||
sts = nvm_ns.elbaf[lba_index] & NVME_NVM_ELBAF_STS_MASK;
|
||||
pif = (nvm_ns.elbaf[lba_index] & NVME_NVM_ELBAF_PIF_MASK) >> 7;
|
||||
}
|
||||
|
||||
if (invalid_tags(cfg.storage_tag, cfg.ref_tag, sts, pif)) {
|
||||
err = -EINVAL;
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
struct nvme_io_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = fd,
|
||||
|
@ -5493,9 +5561,11 @@ static int write_zeroes(int argc, char **argv, struct command *cmd, struct plugi
|
|||
.slba = cfg.start_block,
|
||||
.nlb = cfg.block_count,
|
||||
.control = control,
|
||||
.reftag = cfg.ref_tag,
|
||||
.reftag_u64 = cfg.ref_tag,
|
||||
.apptag = cfg.app_tag,
|
||||
.appmask = cfg.app_tag_mask,
|
||||
.sts = sts,
|
||||
.pif = pif,
|
||||
.storage_tag = cfg.storage_tag,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.result = NULL,
|
||||
|
@ -5648,10 +5718,19 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi
|
|||
uint16_t nr, nb, ns, nrts, natms, nats;
|
||||
__u16 nlbs[128] = { 0 };
|
||||
unsigned long long slbas[128] = {0,};
|
||||
__u32 eilbrts[128] = { 0 };
|
||||
|
||||
union {
|
||||
__u32 f0[128];
|
||||
__u64 f1[101];
|
||||
} eilbrts;
|
||||
|
||||
__u32 elbatms[128] = { 0 };
|
||||
__u32 elbats[128] = { 0 };
|
||||
struct nvme_copy_range copy[128];
|
||||
|
||||
union {
|
||||
struct nvme_copy_range f0[128];
|
||||
struct nvme_copy_range_f1 f1[101];
|
||||
} copy;
|
||||
|
||||
struct config {
|
||||
__u32 namespace_id;
|
||||
|
@ -5662,12 +5741,12 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi
|
|||
bool fua;
|
||||
__u8 prinfow;
|
||||
__u8 prinfor;
|
||||
__u32 ilbrt;
|
||||
__u64 ilbrt;
|
||||
char *eilbrts;
|
||||
__u16 lbat;
|
||||
char *elbatms;
|
||||
__u16 lbatm;
|
||||
char *elbats;
|
||||
__u16 lbatm;
|
||||
char *elbatms;
|
||||
__u8 dtype;
|
||||
__u16 dspec;
|
||||
__u8 format;
|
||||
|
@ -5702,7 +5781,7 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi
|
|||
OPT_FLAG("force-unit-access", 'f', &cfg.fua, d_fua),
|
||||
OPT_BYTE("prinfow", 'p', &cfg.prinfow, d_prinfow),
|
||||
OPT_BYTE("prinfor", 'P', &cfg.prinfor, d_prinfor),
|
||||
OPT_UINT("ref-tag", 'r', &cfg.ilbrt, d_ilbrt),
|
||||
OPT_SUFFIX("ref-tag", 'r', &cfg.ilbrt, d_ilbrt),
|
||||
OPT_LIST("expected-ref-tags", 'R', &cfg.eilbrts, d_eilbrts),
|
||||
OPT_SHRT("app-tag", 'a', &cfg.lbat, d_lbat),
|
||||
OPT_LIST("expected-app-tags", 'A', &cfg.elbats, d_elbats),
|
||||
|
@ -5722,12 +5801,22 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi
|
|||
|
||||
nb = argconfig_parse_comma_sep_array(cfg.nlbs, (int *)nlbs, ARRAY_SIZE(nlbs));
|
||||
ns = argconfig_parse_comma_sep_array_long(cfg.slbas, slbas, ARRAY_SIZE(slbas));
|
||||
nrts = argconfig_parse_comma_sep_array(cfg.eilbrts, (int *)eilbrts, ARRAY_SIZE(eilbrts));
|
||||
|
||||
if (cfg.format == 0)
|
||||
nrts = argconfig_parse_comma_sep_array(cfg.eilbrts, (int *)eilbrts.f0, ARRAY_SIZE(eilbrts.f0));
|
||||
else if (cfg.format == 1)
|
||||
nrts = argconfig_parse_comma_sep_array_long(cfg.eilbrts, (__u64 *)eilbrts.f1, ARRAY_SIZE(eilbrts.f1));
|
||||
else {
|
||||
fprintf(stderr, "invalid format\n");
|
||||
err = -EINVAL;
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
natms = argconfig_parse_comma_sep_array(cfg.elbatms, (int *)elbatms, ARRAY_SIZE(elbatms));
|
||||
nats = argconfig_parse_comma_sep_array(cfg.elbats, (int *)elbats, ARRAY_SIZE(elbats));
|
||||
|
||||
nr = max(nb, max(ns, max(nrts, max(natms, nats))));
|
||||
if (!nr || nr > 128) {
|
||||
if (!nr || nr > 128 || (cfg.format == 1 && nr > 101)) {
|
||||
fprintf(stderr, "invalid range\n");
|
||||
err = -EINVAL;
|
||||
goto close_fd;
|
||||
|
@ -5741,13 +5830,18 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi
|
|||
}
|
||||
}
|
||||
|
||||
nvme_init_copy_range(copy, nlbs, (__u64 *)slbas, eilbrts, elbatms, elbats, nr);
|
||||
if (cfg.format == 0)
|
||||
nvme_init_copy_range(copy.f0, nlbs, (__u64 *)slbas,
|
||||
eilbrts.f0, elbatms, elbats, nr);
|
||||
else if (cfg.format == 1)
|
||||
nvme_init_copy_range_f1(copy.f1, nlbs, (__u64 *)slbas,
|
||||
eilbrts.f1, elbatms, elbats, nr);
|
||||
|
||||
struct nvme_copy_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = fd,
|
||||
.nsid = cfg.namespace_id,
|
||||
.copy = copy,
|
||||
.copy = copy.f0,
|
||||
.sdlba = cfg.sdlba,
|
||||
.nr = nr,
|
||||
.prinfor = cfg.prinfor,
|
||||
|
@ -5757,7 +5851,8 @@ static int copy(int argc, char **argv, struct command *cmd, struct plugin *plugi
|
|||
.format = cfg.format,
|
||||
.lr = cfg.lr,
|
||||
.fua = cfg.fua,
|
||||
.ilbrt = cfg.ilbrt,
|
||||
.prinfow = cfg.prinfow,
|
||||
.ilbrt_u64 = cfg.ilbrt,
|
||||
.lbatm = cfg.lbatm,
|
||||
.lbat = cfg.lbat,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
|
@ -6202,17 +6297,18 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
__u16 control = 0;
|
||||
__u32 dsmgmt = 0;
|
||||
int logical_block_size = 0;
|
||||
long long buffer_size = 0, mbuffer_size = 0;
|
||||
unsigned long long buffer_size = 0, mbuffer_size = 0;
|
||||
bool huge;
|
||||
struct nvme_id_ns ns;
|
||||
__u8 lba_index, ms = 0;
|
||||
struct nvme_nvm_id_ns nvm_ns;
|
||||
__u8 lba_index, ms = 0, sts = 0, pif = 0;
|
||||
|
||||
const char *namespace_id = "Identifier of desired namespace";
|
||||
const char *start_block = "64-bit addr of first block to access";
|
||||
const char *block_count = "number of blocks (zeroes based) on device to access";
|
||||
const char *data_size = "size of data in bytes";
|
||||
const char *metadata_size = "size of metadata in bytes";
|
||||
const char *ref_tag = "reference tag (for end to end PI)";
|
||||
const char *ref_tag = "reference tag for end-to-end PI";
|
||||
const char *data = "data file";
|
||||
const char *metadata = "metadata file";
|
||||
const char *prinfo = "PI and check field";
|
||||
|
@ -6228,8 +6324,7 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
const char *dsm = "dataset management attributes (lower 8 bits)";
|
||||
const char *storage_tag_check = "This bit specifies the Storage Tag field shall be " \
|
||||
"checked as part of end-to-end data protection processing";
|
||||
const char *storage_tag = "storage tag, CDW2 and CDW3 (00:47) bits "\
|
||||
"(for end to end PI)";
|
||||
const char *storage_tag = "storage tag for end-to-end PI";
|
||||
const char *force = "The \"I know what I'm doing\" flag, do not enforce exclusive access for write";
|
||||
|
||||
struct config {
|
||||
|
@ -6238,7 +6333,7 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
__u16 block_count;
|
||||
__u64 data_size;
|
||||
__u64 metadata_size;
|
||||
__u32 ref_tag;
|
||||
__u64 ref_tag;
|
||||
char *data;
|
||||
char *metadata;
|
||||
__u8 prinfo;
|
||||
|
@ -6288,7 +6383,7 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
OPT_SHRT("block-count", 'c', &cfg.block_count, block_count),
|
||||
OPT_SUFFIX("data-size", 'z', &cfg.data_size, data_size),
|
||||
OPT_SUFFIX("metadata-size", 'y', &cfg.metadata_size, metadata_size),
|
||||
OPT_UINT("ref-tag", 'r', &cfg.ref_tag, ref_tag),
|
||||
OPT_SUFFIX("ref-tag", 'r', &cfg.ref_tag, ref_tag),
|
||||
OPT_FILE("data", 'd', &cfg.data, data),
|
||||
OPT_FILE("metadata", 'M', &cfg.metadata, metadata),
|
||||
OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo),
|
||||
|
@ -6354,7 +6449,7 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
if (cfg.force_unit_access)
|
||||
control |= NVME_IO_FUA;
|
||||
if (cfg.storage_tag_check)
|
||||
control |= NVME_SC_STORAGE_TAG_CHECK;
|
||||
control |= NVME_IO_STC;
|
||||
if (cfg.dtype) {
|
||||
if (cfg.dtype > 0xf) {
|
||||
fprintf(stderr, "Invalid directive type, %x\n",
|
||||
|
@ -6394,7 +6489,7 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
&logical_block_size) < 0)
|
||||
goto close_mfd;
|
||||
|
||||
buffer_size = (cfg.block_count + 1) * logical_block_size;
|
||||
buffer_size = ((long long)cfg.block_count + 1) * logical_block_size;
|
||||
if (cfg.data_size < buffer_size) {
|
||||
fprintf(stderr, "Rounding data size to fit block count (%lld bytes)\n",
|
||||
buffer_size);
|
||||
|
@ -6410,16 +6505,24 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
|
||||
if (cfg.metadata_size) {
|
||||
err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
|
||||
if (err) {
|
||||
if (err > 0) {
|
||||
nvme_show_status(err);
|
||||
goto free_buffer;
|
||||
} else if (err < 0) {
|
||||
fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno));
|
||||
goto free_buffer;
|
||||
}
|
||||
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index);
|
||||
ms = ns.lbaf[lba_index].ms;
|
||||
mbuffer_size = (cfg.block_count + 1) * ms;
|
||||
|
||||
err = nvme_identify_ns_csi(fd, 1, 0, NVME_CSI_NVM, &nvm_ns);
|
||||
if (!err) {
|
||||
sts = nvm_ns.elbaf[lba_index] & NVME_NVM_ELBAF_STS_MASK;
|
||||
pif = (nvm_ns.elbaf[lba_index] & NVME_NVM_ELBAF_PIF_MASK) >> 7;
|
||||
}
|
||||
|
||||
mbuffer_size = ((unsigned long long)cfg.block_count + 1) * ms;
|
||||
if (ms && cfg.metadata_size < mbuffer_size) {
|
||||
fprintf(stderr, "Rounding metadata size to fit block count (%lld bytes)\n",
|
||||
mbuffer_size);
|
||||
|
@ -6434,6 +6537,11 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
memset(mbuffer, 0, mbuffer_size);
|
||||
}
|
||||
|
||||
if (invalid_tags(cfg.storage_tag, cfg.ref_tag, sts, pif)) {
|
||||
err = -EINVAL;
|
||||
goto free_buffer;
|
||||
}
|
||||
|
||||
if ((opcode & 1)) {
|
||||
err = read(dfd, (void *)buffer, cfg.data_size);
|
||||
if (err < 0) {
|
||||
|
@ -6464,11 +6572,13 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
printf("addr : %"PRIx64"\n", (uint64_t)(uintptr_t)buffer);
|
||||
printf("slba : %"PRIx64"\n", (uint64_t)cfg.start_block);
|
||||
printf("dsmgmt : %08x\n", dsmgmt);
|
||||
printf("reftag : %08x\n", cfg.ref_tag);
|
||||
printf("reftag : %"PRIx64"\n", (uint64_t)cfg.ref_tag);
|
||||
printf("apptag : %04x\n", cfg.app_tag);
|
||||
printf("appmask : %04x\n", cfg.app_tag_mask);
|
||||
printf("storagetagcheck : %04x\n", cfg.storage_tag_check);
|
||||
printf("storagetag : %"PRIx64"\n", (uint64_t)cfg.storage_tag);
|
||||
printf("pif : %02x\n", pif);
|
||||
printf("sts : %02x\n", sts);
|
||||
}
|
||||
if (cfg.dry_run)
|
||||
goto free_mbuffer;
|
||||
|
@ -6481,8 +6591,10 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
.nlb = cfg.block_count,
|
||||
.control = control,
|
||||
.dsm = cfg.dsmgmt,
|
||||
.sts = sts,
|
||||
.pif = pif,
|
||||
.dspec = cfg.dspec,
|
||||
.reftag = cfg.ref_tag,
|
||||
.reftag_u64 = cfg.ref_tag,
|
||||
.apptag = cfg.app_tag,
|
||||
.appmask = cfg.app_tag_mask,
|
||||
.storage_tag = cfg.storage_tag,
|
||||
|
@ -6494,10 +6606,7 @@ static int submit_io(int opcode, char *command, const char *desc,
|
|||
.result = NULL,
|
||||
};
|
||||
gettimeofday(&start_time, NULL);
|
||||
if (opcode & 1)
|
||||
err = nvme_write(&args);
|
||||
else
|
||||
err = nvme_read(&args);
|
||||
err = nvme_io(&args, opcode);
|
||||
gettimeofday(&end_time, NULL);
|
||||
if (cfg.latency)
|
||||
printf(" latency: %s: %llu us\n",
|
||||
|
@ -6562,6 +6671,10 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
|
|||
{
|
||||
int err, fd;
|
||||
__u16 control = 0;
|
||||
__u8 lba_index, sts = 0, pif = 0;
|
||||
struct nvme_id_ns ns;
|
||||
struct nvme_nvm_id_ns nvm_ns;
|
||||
|
||||
const char *desc = "Verify specified logical blocks on the given device.";
|
||||
const char *namespace_id = "desired namespace";
|
||||
const char *start_block = "64-bit LBA of first block to access";
|
||||
|
@ -6569,11 +6682,10 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
|
|||
const char *limited_retry = "limit media access attempts";
|
||||
const char *force_unit_access = "force device to commit cached data before performing the verify operation";
|
||||
const char *prinfo = "PI and check field";
|
||||
const char *ref_tag = "reference tag (for end to end PI)";
|
||||
const char *app_tag_mask = "app tag mask (for end to end PI)";
|
||||
const char *app_tag = "app tag (for end to end PI)";
|
||||
const char *storage_tag = "storage tag, CDW2 and CDW3 (00:47) bits "\
|
||||
"(for end to end PI)";
|
||||
const char *ref_tag = "reference tag for end-to-end PI";
|
||||
const char *app_tag_mask = "app tag mask for end-to-end PI";
|
||||
const char *app_tag = "app tag for end-to-end PI";
|
||||
const char *storage_tag = "storage tag for end-to-end PI";
|
||||
const char *storage_tag_check = "This bit specifies the Storage Tag field shall "\
|
||||
"be checked as part of Verify operation";
|
||||
|
||||
|
@ -6612,7 +6724,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
|
|||
OPT_FLAG("limited-retry", 'l', &cfg.limited_retry, limited_retry),
|
||||
OPT_FLAG("force-unit-access", 'f', &cfg.force_unit_access, force_unit_access),
|
||||
OPT_BYTE("prinfo", 'p', &cfg.prinfo, prinfo),
|
||||
OPT_UINT("ref-tag", 'r', &cfg.ref_tag, ref_tag),
|
||||
OPT_SUFFIX("ref-tag", 'r', &cfg.ref_tag, ref_tag),
|
||||
OPT_SHRT("app-tag", 'a', &cfg.app_tag, app_tag),
|
||||
OPT_SHRT("app-tag-mask", 'm', &cfg.app_tag_mask, app_tag_mask),
|
||||
OPT_SUFFIX("storage-tag", 'S', &cfg.storage_tag, storage_tag),
|
||||
|
@ -6635,7 +6747,7 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
|
|||
if (cfg.force_unit_access)
|
||||
control |= NVME_IO_FUA;
|
||||
if (cfg.storage_tag_check)
|
||||
control |= NVME_SC_STORAGE_TAG_CHECK;
|
||||
control |= NVME_IO_STC;
|
||||
|
||||
if (!cfg.namespace_id) {
|
||||
err = nvme_get_nsid(fd, &cfg.namespace_id);
|
||||
|
@ -6645,6 +6757,27 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
|
|||
}
|
||||
}
|
||||
|
||||
err = nvme_identify_ns(fd, cfg.namespace_id, &ns);
|
||||
if (err) {
|
||||
nvme_show_status(err);
|
||||
goto close_fd;
|
||||
} else if (err < 0) {
|
||||
fprintf(stderr, "identify namespace: %s\n", nvme_strerror(errno));
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
err = nvme_identify_ns_csi(fd, cfg.namespace_id, 0, NVME_CSI_NVM, &nvm_ns);
|
||||
if (!err) {
|
||||
nvme_id_ns_flbas_to_lbaf_inuse(ns.flbas, &lba_index);
|
||||
sts = nvm_ns.elbaf[lba_index] & NVME_NVM_ELBAF_STS_MASK;
|
||||
pif = (nvm_ns.elbaf[lba_index] & NVME_NVM_ELBAF_PIF_MASK) >> 7;
|
||||
}
|
||||
|
||||
if (invalid_tags(cfg.storage_tag, cfg.ref_tag, sts, pif)) {
|
||||
err = -EINVAL;
|
||||
goto close_fd;
|
||||
}
|
||||
|
||||
struct nvme_io_args args = {
|
||||
.args_size = sizeof(args),
|
||||
.fd = fd,
|
||||
|
@ -6652,9 +6785,11 @@ static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin
|
|||
.slba = cfg.start_block,
|
||||
.nlb = cfg.block_count,
|
||||
.control = control,
|
||||
.reftag = cfg.ref_tag,
|
||||
.reftag_u64 = cfg.ref_tag,
|
||||
.apptag = cfg.app_tag,
|
||||
.appmask = cfg.app_tag_mask,
|
||||
.sts = sts,
|
||||
.pif = pif,
|
||||
.storage_tag = cfg.storage_tag,
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.result = NULL,
|
||||
|
@ -7143,7 +7278,7 @@ static int lockdown_cmd(int argc, char **argv, struct command *cmd, struct plugi
|
|||
if (fd < 0)
|
||||
goto ret;
|
||||
|
||||
/* check for input arguement limit */
|
||||
/* check for input argument limit */
|
||||
if (cfg.ifc > 3) {
|
||||
fprintf(stderr, "invalid interface settings:%d\n", cfg.ifc);
|
||||
err = -1;
|
||||
|
@ -7313,8 +7448,22 @@ static int passthru(int argc, char **argv, bool admin,
|
|||
if (fd < 0)
|
||||
goto ret;
|
||||
|
||||
flags = cfg.opcode & 1 ? O_RDONLY : O_WRONLY | O_CREAT;
|
||||
dfd = mfd = cfg.opcode & 1 ? STDIN_FILENO : STDOUT_FILENO;
|
||||
if (cfg.opcode & 0x01)
|
||||
cfg.write = true;
|
||||
|
||||
if (cfg.opcode & 0x02)
|
||||
cfg.read = true;
|
||||
|
||||
if (cfg.write) {
|
||||
flags = O_RDONLY;
|
||||
dfd = mfd = STDIN_FILENO;
|
||||
}
|
||||
|
||||
if (cfg.read) {
|
||||
flags = O_WRONLY | O_CREAT;
|
||||
dfd = mfd = STDOUT_FILENO;
|
||||
}
|
||||
|
||||
if (strlen(cfg.input_file)) {
|
||||
dfd = open(cfg.input_file, flags, mode);
|
||||
if (dfd < 0) {
|
||||
|
@ -7357,14 +7506,6 @@ static int passthru(int argc, char **argv, bool admin,
|
|||
goto free_metadata;
|
||||
}
|
||||
|
||||
if (cfg.write && !(cfg.opcode & 0x01)) {
|
||||
fprintf(stderr, "warning: write flag set but write direction bit is not set in the opcode\n");
|
||||
}
|
||||
|
||||
if (cfg.read && !(cfg.opcode & 0x02)) {
|
||||
fprintf(stderr, "warning: read flag set but read direction bit is not set in the opcode\n");
|
||||
}
|
||||
|
||||
memset(data, cfg.prefill, cfg.data_len);
|
||||
if (!cfg.read && !cfg.write) {
|
||||
fprintf(stderr, "data direction not given\n");
|
||||
|
@ -7434,7 +7575,7 @@ static int passthru(int argc, char **argv, bool admin,
|
|||
admin ? "Admin": "IO",
|
||||
strcmp(cmd_name, "Unknown") ? cmd_name: "Vendor Specific",
|
||||
result);
|
||||
if (cfg.read && cfg.input_file) {
|
||||
if (cfg.read && strlen(cfg.input_file)) {
|
||||
if (write(dfd, (void *)data, cfg.data_len) < 0)
|
||||
perror("failed to write data buffer");
|
||||
if (cfg.metadata_len && cfg.metadata)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue