Skip to content

Commit eac5076

Browse files
author
Kenneth Heitke
committed
nvme: add Verify command
Reviewed-by: Edmund Nadolski <[email protected]> Reviewed-by: Revanth Rajashekar <[email protected]> Signed-off-by: Kenneth Heitke <[email protected]>
1 parent a80475c commit eac5076

6 files changed

Lines changed: 116 additions & 3 deletions

File tree

linux/nvme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ enum nvme_opcode {
676676
nvme_cmd_compare = 0x05,
677677
nvme_cmd_write_zeroes = 0x08,
678678
nvme_cmd_dsm = 0x09,
679+
nvme_cmd_verify = 0x0c,
679680
nvme_cmd_resv_register = 0x0d,
680681
nvme_cmd_resv_report = 0x0e,
681682
nvme_cmd_resv_acquire = 0x11,

nvme-builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ COMMAND_LIST(
5454
ENTRY("write", "Submit a write command, return results", write_cmd)
5555
ENTRY("write-zeroes", "Submit a write zeroes command, return results", write_zeroes)
5656
ENTRY("write-uncor", "Submit a write uncorrectable command, return results", write_uncor)
57+
ENTRY("verify", "Submit a verify command, return results", verify_cmd)
5758
ENTRY("sanitize", "Submit a sanitize command", sanitize)
5859
ENTRY("sanitize-log", "Retrieve sanitize log, show it", sanitize_log)
5960
ENTRY("reset", "Resets the controller", reset)

nvme-ioctl.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,22 @@ int nvme_compare(int fd, __u64 slba, __u16 nblocks, __u16 control, __u32 dsmgmt,
178178
reftag, apptag, appmask, data, metadata);
179179
}
180180

181+
int nvme_verify(int fd, __u32 nsid, __u64 slba, __u16 nblocks,
182+
__u16 control, __u32 reftag, __u16 apptag, __u16 appmask)
183+
{
184+
struct nvme_passthru_cmd cmd = {
185+
.opcode = nvme_cmd_verify,
186+
.nsid = nsid,
187+
.cdw10 = slba & 0xffffffff,
188+
.cdw11 = slba >> 32,
189+
.cdw12 = nblocks | (control << 16),
190+
.cdw14 = reftag,
191+
.cdw15 = apptag | (appmask << 16),
192+
};
193+
194+
return nvme_submit_io_passthru(fd, &cmd);
195+
}
196+
181197
int nvme_passthru_io(int fd, __u8 opcode, __u8 flags, __u16 rsvd,
182198
__u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10,
183199
__u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14,

nvme-ioctl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ int nvme_compare(int fd, __u64 slba, __u16 nblocks, __u16 control,
3838
__u32 dsmgmt, __u32 reftag, __u16 apptag,
3939
__u16 appmask, void *data, void *metadata);
4040

41+
int nvme_verify(int fd, __u32 nsid, __u64 slba, __u16 nblocks,
42+
__u16 control, __u32 reftag, __u16 apptag, __u16 appmask);
43+
4144
/* NVME_IO_CMD */
4245
int nvme_passthru_io(int fd, __u8 opcode, __u8 flags, __u16 rsvd,
4346
__u32 nsid, __u32 cdw2, __u32 cdw3,

nvme-print.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,8 @@ static void show_nvme_id_ctrl_cqes(__u8 cqes)
362362
static void show_nvme_id_ctrl_oncs(__le16 ctrl_oncs)
363363
{
364364
__u16 oncs = le16_to_cpu(ctrl_oncs);
365-
__u16 rsvd = (oncs & 0xFF80) >> 7;
365+
__u16 rsvd = (oncs & 0xFF00) >> 8;
366+
__u16 vrfy = (oncs & 0x80) >> 7;
366367
__u16 tmst = (oncs & 0x40) >> 6;
367368
__u16 resv = (oncs & 0x20) >> 5;
368369
__u16 save = (oncs & 0x10) >> 4;
@@ -372,7 +373,9 @@ static void show_nvme_id_ctrl_oncs(__le16 ctrl_oncs)
372373
__u16 cmp = oncs & 0x1;
373374

374375
if (rsvd)
375-
printf(" [15:7] : %#x\tReserved\n", rsvd);
376+
printf(" [15:8] : %#x\tReserved\n", rsvd);
377+
printf(" [7:7] : %#x\tVerify %sSupported\n",
378+
vrfy, vrfy ? "" : "Not ");
376379
printf(" [6:6] : %#x\tTimestamp %sSupported\n",
377380
tmst, tmst ? "" : "Not ");
378381
printf(" [5:5] : %#x\tReservations %sSupported\n",

nvme.c

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static int open_dev(char *dev)
108108
return -ENODEV;
109109
}
110110
return fd;
111-
perror:
111+
perror:
112112
perror(dev);
113113
return err;
114114
}
@@ -4656,6 +4656,95 @@ static int write_cmd(int argc, char **argv, struct command *cmd, struct plugin *
46564656
return submit_io(nvme_cmd_write, "write", desc, argc, argv);
46574657
}
46584658

4659+
static int verify_cmd(int argc, char **argv, struct command *cmd, struct plugin *plugin)
4660+
{
4661+
int err, fd;
4662+
__u16 control = 0;
4663+
const char *desc = "Verify specified logical blocks on the given device.";
4664+
const char *namespace_id = "desired namespace";
4665+
const char *start_block = "64-bit LBA of first block to access";
4666+
const char *block_count = "number of blocks (zeroes based) on device to access";
4667+
const char *limited_retry = "limit media access attempts";
4668+
const char *force = "force device to commit cached data before performing the verify operation";
4669+
const char *prinfo = "PI and check field";
4670+
const char *ref_tag = "reference tag (for end to end PI)";
4671+
const char *app_tag_mask = "app tag mask (for end to end PI)";
4672+
const char *app_tag = "app tag (for end to end PI)";
4673+
4674+
struct config {
4675+
__u64 start_block;
4676+
__u32 namespace_id;
4677+
__u32 ref_tag;
4678+
__u16 app_tag;
4679+
__u16 app_tag_mask;
4680+
__u16 block_count;
4681+
__u8 prinfo;
4682+
int limited_retry;
4683+
int force_unit_access;
4684+
};
4685+
4686+
struct config cfg = {
4687+
.namespace_id = 0,
4688+
.start_block = 0,
4689+
.block_count = 0,
4690+
.prinfo = 0,
4691+
.ref_tag = 0,
4692+
.app_tag = 0,
4693+
.app_tag_mask = 0,
4694+
.limited_retry = 0,
4695+
.force_unit_access = 0,
4696+
};
4697+
4698+
const struct argconfig_commandline_options command_line_options[] = {
4699+
{"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id},
4700+
{"start-block", 's', "NUM", CFG_LONG_SUFFIX, &cfg.start_block, required_argument, start_block},
4701+
{"block-count", 'c', "NUM", CFG_SHORT, &cfg.block_count, required_argument, block_count},
4702+
{"limited-retry", 'l', "", CFG_NONE, &cfg.limited_retry, no_argument, limited_retry},
4703+
{"force-unit-access", 'f', "", CFG_NONE, &cfg.force_unit_access, no_argument, force},
4704+
{"prinfo", 'p', "NUM", CFG_BYTE, &cfg.prinfo, required_argument, prinfo},
4705+
{"ref-tag", 'r', "NUM", CFG_POSITIVE, &cfg.ref_tag, required_argument, ref_tag},
4706+
{"app-tag", 'a', "NUM", CFG_SHORT, &cfg.app_tag, required_argument, app_tag},
4707+
{"app-tag-mask", 'm', "NUM", CFG_SHORT, &cfg.app_tag_mask, required_argument, app_tag_mask},
4708+
{NULL}
4709+
};
4710+
4711+
fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg));
4712+
if (fd < 0)
4713+
return fd;
4714+
4715+
if (cfg.prinfo > 0xf) {
4716+
err = EINVAL;
4717+
goto close_fd;
4718+
}
4719+
4720+
control |= (cfg.prinfo << 10);
4721+
if (cfg.limited_retry)
4722+
control |= NVME_RW_LR;
4723+
if (cfg.force_unit_access)
4724+
control |= NVME_RW_FUA;
4725+
4726+
if (!cfg.namespace_id) {
4727+
cfg.namespace_id = get_nsid(fd);
4728+
if (cfg.namespace_id == 0) {
4729+
err = EINVAL;
4730+
goto close_fd;
4731+
}
4732+
}
4733+
4734+
err = nvme_verify(fd, cfg.namespace_id, cfg.start_block, cfg.block_count,
4735+
control, cfg.ref_tag, cfg.app_tag, cfg.app_tag_mask);
4736+
if (err < 0)
4737+
perror("verify");
4738+
else if (err != 0)
4739+
show_nvme_status(err);
4740+
else
4741+
printf("NVME Verify Success\n");
4742+
4743+
close_fd:
4744+
close(fd);
4745+
return err;
4746+
}
4747+
46594748
static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *plugin)
46604749
{
46614750
const char *desc = "Obtain results of one or more "\

0 commit comments

Comments
 (0)