From: Keith Busch Date: Sat, 6 Dec 2014 00:16:45 +0000 (-0700) Subject: NVMe: Add compare command support X-Git-Tag: v0.1~84 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=4ec75bbeca786171323a6afd3a709eb04f4692b6;p=users%2Fsagi%2Fnvme-cli.git NVMe: Add compare command support Signed-off-by: Keith Busch --- diff --git a/Documentation/nvme-compare.txt b/Documentation/nvme-compare.txt new file mode 100644 index 00000000..81436d97 --- /dev/null +++ b/Documentation/nvme-compare.txt @@ -0,0 +1,44 @@ +nvme-compare(1) +=============== + +NAME +---- +nvme-compare - Send an NVMe Compare command, provide results + +SYNOPSIS +-------- +[verse] +'nvme-compare' [--start-block= | -s ] + [--block-count= | -c ] + [--data-size= | -z ] + [--ref-tag= | -r ] + [--data= | -d ] + [--prinfo= | -p ] + [--app-tag-mask= | -m ] + [--app-tag= | -a ] + [--limited-retry | -l] + [--force-unit-access | -f] + +DESCRIPTION +----------- +The Compare command reads the logical blocks specified by the command +from the medium and compares the data read to a comparison data buffer +transferred as part of the command. If the data read from the controller +and the comparison data buffer are equivalent with no miscompares, +then the command completes successfully. If there is any miscompare, +the command completes with an error of Compare Failure. If metadata is +provided, then a comparison is also performed for the metadata. + +OPTIONS +------- +--start-block=:: +-s :: + Start block. + +EXAMPLES +-------- +No examples yet. + +NVME +---- +Part of the nvme-user suite diff --git a/nvme.c b/nvme.c index 783d6e36..1c9584b4 100644 --- a/nvme.c +++ b/nvme.c @@ -66,6 +66,7 @@ static const char *devicename; ENTRY(RESV_RELEASE, "resv-release", "Submit a Reservation Release, return results", resv_release) \ ENTRY(RESV_REPORT, "resv-report", "Submit a Reservation Report, return results", resv_report) \ ENTRY(FLUSH, "flush", "Submit a Flush command, return results", flush) \ + ENTRY(COMPARE, "compare", "Submit a Comapre command, return results", compare) \ ENTRY(HELP, "help", "Display this help", help) #define ENTRY(i, n, h, f) \ @@ -1610,6 +1611,82 @@ static int resv_report(int argc, char **argv) return 0; } +static int compare(int argc, char **argv) +{ + struct nvme_user_io io; + void *buffer; + int err, opt, dfd = STDIN_FILENO, long_index = 0; + unsigned int data_size = 0; + __u8 prinfo = 0; + static struct option opts[] = { + {"start-block", required_argument, 0, 's'}, + {"block-count", required_argument, 0, 'c'}, + {"data-size", required_argument, 0, 'z'}, + {"ref-tag", required_argument, 0, 'r'}, + {"data", required_argument, 0, 'd'}, + {"prinfo", required_argument, 0, 'p'}, + {"app-tag-mask", required_argument, 0, 'm'}, + {"app-tag", required_argument, 0, 'a'}, + {"limited-retry", no_argument, 0, 'l'}, + {"force-unit-access", no_argument, 0, 'f'}, + { 0, 0, 0, 0} + }; + + memset(&io, 0, sizeof(io)); + while ((opt = getopt_long(argc, (char **)argv, "p:s:c:z:r:d:m:a:lf", opts, + &long_index)) != -1) { + switch(opt) { + case 's': get_long(optarg, &io.slba); break; + case 'c': get_short(optarg, &io.nblocks); break; + case 'z': get_int(optarg, &data_size); break; + case 'r': get_int(optarg, &io.reftag); break; + case 'm': get_short(optarg, &io.appmask); break; + case 'a': get_short(optarg, &io.apptag); break; + case 'p': + get_byte(optarg, &prinfo); + if (prinfo > 0xf) + return EINVAL; + io.control |= (prinfo << 10); + break; + case 'l': + io.control |= NVME_RW_LR; + break; + case 'f': + io.control | NVME_RW_FUA; + break; + case 'd': + dfd = open(optarg, O_RDONLY); + if (dfd < 0) { + perror(optarg); + return EINVAL; + } + break; + default: + return EINVAL; + } + }; + get_dev(optind, argc, argv); + + if (!data_size) { + fprintf(stderr, "data size not provided\n"); + return EINVAL; + } + buffer = malloc(data_size); + if (read(dfd, (void *)buffer, data_size) < 0) { + fprintf(stderr, "failed to read compare buffer\n"); + return EINVAL; + } + + io.opcode = nvme_cmd_compare; + io.addr = (__u64)buffer; + err = ioctl(fd, NVME_IOCTL_SUBMIT_IO, &io); + if (err < 0) + perror("ioctl"); + else + printf("compare:%s(%04x)\n", nvme_status_to_string(err), err); + return 0; +} + static int sec_recv(int argc, char **argv) { struct nvme_admin_cmd cmd;