ENTRY("write", "Submit a write command, return results", write_cmd)
ENTRY("write-zeroes", "Submit a write zeroes command, return results", write_zeroes)
ENTRY("write-uncor", "Submit a write uncorrectable command, return results", write_uncor)
+ ENTRY("verify", "Submit a verify command, return results", verify_cmd)
ENTRY("sanitize", "Submit a sanitize command", sanitize)
ENTRY("sanitize-log", "Retrieve sanitize log, show it", sanitize_log)
ENTRY("reset", "Resets the controller", reset)
reftag, apptag, appmask, data, metadata);
}
+int nvme_verify(int fd, __u32 nsid, __u64 slba, __u16 nblocks,
+ __u16 control, __u32 reftag, __u16 apptag, __u16 appmask)
+{
+ struct nvme_passthru_cmd cmd = {
+ .opcode = nvme_cmd_verify,
+ .nsid = nsid,
+ .cdw10 = slba & 0xffffffff,
+ .cdw11 = slba >> 32,
+ .cdw12 = nblocks | (control << 16),
+ .cdw14 = reftag,
+ .cdw15 = apptag | (appmask << 16),
+ };
+
+ return nvme_submit_io_passthru(fd, &cmd);
+}
+
int nvme_passthru_io(int fd, __u8 opcode, __u8 flags, __u16 rsvd,
__u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10,
__u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14,
static void show_nvme_id_ctrl_oncs(__le16 ctrl_oncs)
{
__u16 oncs = le16_to_cpu(ctrl_oncs);
- __u16 rsvd = (oncs & 0xFF80) >> 7;
+ __u16 rsvd = (oncs & 0xFF00) >> 8;
+ __u16 vrfy = (oncs & 0x80) >> 7;
__u16 tmst = (oncs & 0x40) >> 6;
__u16 resv = (oncs & 0x20) >> 5;
__u16 save = (oncs & 0x10) >> 4;
__u16 cmp = oncs & 0x1;
if (rsvd)
- printf(" [15:7] : %#x\tReserved\n", rsvd);
+ printf(" [15:8] : %#x\tReserved\n", rsvd);
+ printf(" [7:7] : %#x\tVerify %sSupported\n",
+ vrfy, vrfy ? "" : "Not ");
printf(" [6:6] : %#x\tTimestamp %sSupported\n",
tmst, tmst ? "" : "Not ");
printf(" [5:5] : %#x\tReservations %sSupported\n",
return -ENODEV;
}
return fd;
- perror:
+perror:
perror(dev);
return err;
}
return submit_io(nvme_cmd_write, "write", desc, argc, argv);
}
+static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ int err, fd;
+ __u16 control = 0;
+ 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";
+ const char *block_count = "number of blocks (zeroes based) on device to access";
+ const char *limited_retry = "limit media access attempts";
+ const char *force = "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)";
+
+ struct config {
+ __u64 start_block;
+ __u32 namespace_id;
+ __u32 ref_tag;
+ __u16 app_tag;
+ __u16 app_tag_mask;
+ __u16 block_count;
+ __u8 prinfo;
+ int limited_retry;
+ int force_unit_access;
+ };
+
+ struct config cfg = {
+ .namespace_id = 0,
+ .start_block = 0,
+ .block_count = 0,
+ .prinfo = 0,
+ .ref_tag = 0,
+ .app_tag = 0,
+ .app_tag_mask = 0,
+ .limited_retry = 0,
+ .force_unit_access = 0,
+ };
+
+ const struct argconfig_commandline_options command_line_options[] = {
+ {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id},
+ {"start-block", 's', "NUM", CFG_LONG_SUFFIX, &cfg.start_block, required_argument, start_block},
+ {"block-count", 'c', "NUM", CFG_SHORT, &cfg.block_count, required_argument, block_count},
+ {"limited-retry", 'l', "", CFG_NONE, &cfg.limited_retry, no_argument, limited_retry},
+ {"force-unit-access", 'f', "", CFG_NONE, &cfg.force_unit_access, no_argument, force},
+ {"prinfo", 'p', "NUM", CFG_BYTE, &cfg.prinfo, required_argument, prinfo},
+ {"ref-tag", 'r', "NUM", CFG_POSITIVE, &cfg.ref_tag, required_argument, ref_tag},
+ {"app-tag", 'a', "NUM", CFG_SHORT, &cfg.app_tag, required_argument, app_tag},
+ {"app-tag-mask", 'm', "NUM", CFG_SHORT, &cfg.app_tag_mask, required_argument, app_tag_mask},
+ {NULL}
+ };
+
+ fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg));
+ if (fd < 0)
+ return fd;
+
+ if (cfg.prinfo > 0xf) {
+ err = EINVAL;
+ goto close_fd;
+ }
+
+ control |= (cfg.prinfo << 10);
+ if (cfg.limited_retry)
+ control |= NVME_RW_LR;
+ if (cfg.force_unit_access)
+ control |= NVME_RW_FUA;
+
+ if (!cfg.namespace_id) {
+ cfg.namespace_id = get_nsid(fd);
+ if (cfg.namespace_id == 0) {
+ err = EINVAL;
+ goto close_fd;
+ }
+ }
+
+ err = nvme_verify(fd, cfg.namespace_id, cfg.start_block, cfg.block_count,
+ control, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask);
+ if (err < 0)
+ perror("verify");
+ else if (err != 0)
+ show_nvme_status(err);
+ else
+ printf("NVME Verify Success\n");
+
+close_fd:
+ close(fd);
+ return err;
+}
+
static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin)
{
const char *desc = "Obtain results of one or more "\