170d20ed3SAlexander Motin /*- 270d20ed3SAlexander Motin * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 370d20ed3SAlexander Motin * 470d20ed3SAlexander Motin * Copyright (C) 2019 Alexander Motin <mav@FreeBSD.org> 570d20ed3SAlexander Motin * 670d20ed3SAlexander Motin * Redistribution and use in source and binary forms, with or without 770d20ed3SAlexander Motin * modification, are permitted provided that the following conditions 870d20ed3SAlexander Motin * are met: 970d20ed3SAlexander Motin * 1. Redistributions of source code must retain the above copyright 1070d20ed3SAlexander Motin * notice, this list of conditions and the following disclaimer, 1170d20ed3SAlexander Motin * without modification, immediately at the beginning of the file. 1270d20ed3SAlexander Motin * 2. Redistributions in binary form must reproduce the above copyright 1370d20ed3SAlexander Motin * notice, this list of conditions and the following disclaimer in the 1470d20ed3SAlexander Motin * documentation and/or other materials provided with the distribution. 1570d20ed3SAlexander Motin * 1670d20ed3SAlexander Motin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1770d20ed3SAlexander Motin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1870d20ed3SAlexander Motin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1970d20ed3SAlexander Motin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2070d20ed3SAlexander Motin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2170d20ed3SAlexander Motin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2270d20ed3SAlexander Motin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2370d20ed3SAlexander Motin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2470d20ed3SAlexander Motin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2570d20ed3SAlexander Motin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2670d20ed3SAlexander Motin */ 2770d20ed3SAlexander Motin 2870d20ed3SAlexander Motin #include <sys/cdefs.h> 2970d20ed3SAlexander Motin __FBSDID("$FreeBSD$"); 3070d20ed3SAlexander Motin 3170d20ed3SAlexander Motin #include <sys/param.h> 3270d20ed3SAlexander Motin #include <sys/ioccom.h> 3370d20ed3SAlexander Motin 3470d20ed3SAlexander Motin #include <err.h> 3570d20ed3SAlexander Motin #include <fcntl.h> 3670d20ed3SAlexander Motin #include <stdbool.h> 3770d20ed3SAlexander Motin #include <stddef.h> 3870d20ed3SAlexander Motin #include <stdio.h> 3970d20ed3SAlexander Motin #include <stdlib.h> 4070d20ed3SAlexander Motin #include <string.h> 4170d20ed3SAlexander Motin #include <unistd.h> 4270d20ed3SAlexander Motin 4370d20ed3SAlexander Motin #include "nvmecontrol.h" 4470d20ed3SAlexander Motin 4570d20ed3SAlexander Motin /* Tables for command line parsing */ 4670d20ed3SAlexander Motin 4770d20ed3SAlexander Motin static cmd_fn_t resv; 4870d20ed3SAlexander Motin static cmd_fn_t resvacquire; 4970d20ed3SAlexander Motin static cmd_fn_t resvregister; 5070d20ed3SAlexander Motin static cmd_fn_t resvrelease; 5170d20ed3SAlexander Motin static cmd_fn_t resvreport; 5270d20ed3SAlexander Motin 5370d20ed3SAlexander Motin #define NONE 0xffffffffu 5470d20ed3SAlexander Motin #define NONE64 0xffffffffffffffffull 5570d20ed3SAlexander Motin #define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc } 5670d20ed3SAlexander Motin #define OPT_END { NULL, 0, arg_none, NULL, NULL } 5770d20ed3SAlexander Motin 5870d20ed3SAlexander Motin static struct cmd resv_cmd = { 5970d20ed3SAlexander Motin .name = "resv", 6070d20ed3SAlexander Motin .fn = resv, 6170d20ed3SAlexander Motin .descr = "Reservation commands", 6270d20ed3SAlexander Motin .ctx_size = 0, 6370d20ed3SAlexander Motin .opts = NULL, 6470d20ed3SAlexander Motin .args = NULL, 6570d20ed3SAlexander Motin }; 6670d20ed3SAlexander Motin 6770d20ed3SAlexander Motin CMD_COMMAND(resv_cmd); 6870d20ed3SAlexander Motin 6970d20ed3SAlexander Motin static struct acquire_options { 7070d20ed3SAlexander Motin uint64_t crkey; 7170d20ed3SAlexander Motin uint64_t prkey; 7270d20ed3SAlexander Motin uint8_t rtype; 7370d20ed3SAlexander Motin uint8_t racqa; 7470d20ed3SAlexander Motin const char *dev; 7570d20ed3SAlexander Motin } acquire_opt = { 7670d20ed3SAlexander Motin .crkey = 0, 7770d20ed3SAlexander Motin .prkey = 0, 7870d20ed3SAlexander Motin .rtype = 0, 7970d20ed3SAlexander Motin .racqa = 0, 8070d20ed3SAlexander Motin .dev = NULL, 8170d20ed3SAlexander Motin }; 8270d20ed3SAlexander Motin 8370d20ed3SAlexander Motin static const struct opts acquire_opts[] = { 8470d20ed3SAlexander Motin OPT("crkey", 'c', arg_uint64, acquire_opt, crkey, 8570d20ed3SAlexander Motin "Current Reservation Key"), 8670d20ed3SAlexander Motin OPT("prkey", 'p', arg_uint64, acquire_opt, prkey, 8770d20ed3SAlexander Motin "Preempt Reservation Key"), 8870d20ed3SAlexander Motin OPT("rtype", 't', arg_uint8, acquire_opt, rtype, 8970d20ed3SAlexander Motin "Reservation Type"), 9070d20ed3SAlexander Motin OPT("racqa", 'a', arg_uint8, acquire_opt, racqa, 9170d20ed3SAlexander Motin "Acquire Action (0=acq, 1=pre, 2=pre+ab)"), 9270d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 9370d20ed3SAlexander Motin }; 9470d20ed3SAlexander Motin 9570d20ed3SAlexander Motin static const struct args acquire_args[] = { 9670d20ed3SAlexander Motin { arg_string, &acquire_opt.dev, "namespace-id" }, 9770d20ed3SAlexander Motin { arg_none, NULL, NULL }, 9870d20ed3SAlexander Motin }; 9970d20ed3SAlexander Motin 10070d20ed3SAlexander Motin static struct cmd acquire_cmd = { 10170d20ed3SAlexander Motin .name = "acquire", 10270d20ed3SAlexander Motin .fn = resvacquire, 10370d20ed3SAlexander Motin .descr = "Acquire/preempt reservation", 10470d20ed3SAlexander Motin .ctx_size = sizeof(acquire_opt), 10570d20ed3SAlexander Motin .opts = acquire_opts, 10670d20ed3SAlexander Motin .args = acquire_args, 10770d20ed3SAlexander Motin }; 10870d20ed3SAlexander Motin 10970d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, acquire_cmd); 11070d20ed3SAlexander Motin 11170d20ed3SAlexander Motin static struct register_options { 11270d20ed3SAlexander Motin uint64_t crkey; 11370d20ed3SAlexander Motin uint64_t nrkey; 11470d20ed3SAlexander Motin uint8_t rrega; 11570d20ed3SAlexander Motin bool iekey; 11670d20ed3SAlexander Motin uint8_t cptpl; 11770d20ed3SAlexander Motin const char *dev; 11870d20ed3SAlexander Motin } register_opt = { 11970d20ed3SAlexander Motin .crkey = 0, 12070d20ed3SAlexander Motin .nrkey = 0, 12170d20ed3SAlexander Motin .rrega = 0, 12270d20ed3SAlexander Motin .iekey = false, 12370d20ed3SAlexander Motin .cptpl = 0, 12470d20ed3SAlexander Motin .dev = NULL, 12570d20ed3SAlexander Motin }; 12670d20ed3SAlexander Motin 12770d20ed3SAlexander Motin static const struct opts register_opts[] = { 12870d20ed3SAlexander Motin OPT("crkey", 'c', arg_uint64, register_opt, crkey, 12970d20ed3SAlexander Motin "Current Reservation Key"), 13070d20ed3SAlexander Motin OPT("nrkey", 'k', arg_uint64, register_opt, nrkey, 13170d20ed3SAlexander Motin "New Reservation Key"), 13270d20ed3SAlexander Motin OPT("rrega", 'r', arg_uint8, register_opt, rrega, 13370d20ed3SAlexander Motin "Register Action (0=reg, 1=unreg, 2=replace)"), 13470d20ed3SAlexander Motin OPT("iekey", 'i', arg_none, register_opt, iekey, 13570d20ed3SAlexander Motin "Ignore Existing Key"), 13670d20ed3SAlexander Motin OPT("cptpl", 'p', arg_uint8, register_opt, cptpl, 13770d20ed3SAlexander Motin "Change Persist Through Power Loss State"), 13870d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 13970d20ed3SAlexander Motin }; 14070d20ed3SAlexander Motin 14170d20ed3SAlexander Motin static const struct args register_args[] = { 14270d20ed3SAlexander Motin { arg_string, ®ister_opt.dev, "namespace-id" }, 14370d20ed3SAlexander Motin { arg_none, NULL, NULL }, 14470d20ed3SAlexander Motin }; 14570d20ed3SAlexander Motin 14670d20ed3SAlexander Motin static struct cmd register_cmd = { 14770d20ed3SAlexander Motin .name = "register", 14870d20ed3SAlexander Motin .fn = resvregister, 14970d20ed3SAlexander Motin .descr = "Register/unregister reservation", 15070d20ed3SAlexander Motin .ctx_size = sizeof(register_opt), 15170d20ed3SAlexander Motin .opts = register_opts, 15270d20ed3SAlexander Motin .args = register_args, 15370d20ed3SAlexander Motin }; 15470d20ed3SAlexander Motin 15570d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, register_cmd); 15670d20ed3SAlexander Motin 15770d20ed3SAlexander Motin static struct release_options { 15870d20ed3SAlexander Motin uint64_t crkey; 15970d20ed3SAlexander Motin uint8_t rtype; 16070d20ed3SAlexander Motin uint8_t rrela; 16170d20ed3SAlexander Motin const char *dev; 16270d20ed3SAlexander Motin } release_opt = { 16370d20ed3SAlexander Motin .crkey = 0, 16470d20ed3SAlexander Motin .rtype = 0, 16570d20ed3SAlexander Motin .rrela = 0, 16670d20ed3SAlexander Motin .dev = NULL, 16770d20ed3SAlexander Motin }; 16870d20ed3SAlexander Motin 16970d20ed3SAlexander Motin static const struct opts release_opts[] = { 17070d20ed3SAlexander Motin OPT("crkey", 'c', arg_uint64, release_opt, crkey, 17170d20ed3SAlexander Motin "Current Reservation Key"), 17270d20ed3SAlexander Motin OPT("rtype", 't', arg_uint8, release_opt, rtype, 17370d20ed3SAlexander Motin "Reservation Type"), 17470d20ed3SAlexander Motin OPT("rrela", 'a', arg_uint8, release_opt, rrela, 17570d20ed3SAlexander Motin "Release Action (0=release, 1=clear)"), 17670d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 17770d20ed3SAlexander Motin }; 17870d20ed3SAlexander Motin 17970d20ed3SAlexander Motin static const struct args release_args[] = { 18070d20ed3SAlexander Motin { arg_string, &release_opt.dev, "namespace-id" }, 18170d20ed3SAlexander Motin { arg_none, NULL, NULL }, 18270d20ed3SAlexander Motin }; 18370d20ed3SAlexander Motin 18470d20ed3SAlexander Motin static struct cmd release_cmd = { 18570d20ed3SAlexander Motin .name = "release", 18670d20ed3SAlexander Motin .fn = resvrelease, 18770d20ed3SAlexander Motin .descr = "Release/clear reservation", 18870d20ed3SAlexander Motin .ctx_size = sizeof(release_opt), 18970d20ed3SAlexander Motin .opts = release_opts, 19070d20ed3SAlexander Motin .args = release_args, 19170d20ed3SAlexander Motin }; 19270d20ed3SAlexander Motin 19370d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, release_cmd); 19470d20ed3SAlexander Motin 19570d20ed3SAlexander Motin static struct report_options { 19670d20ed3SAlexander Motin bool hex; 19770d20ed3SAlexander Motin bool verbose; 19870d20ed3SAlexander Motin bool eds; 19970d20ed3SAlexander Motin const char *dev; 20070d20ed3SAlexander Motin } report_opt = { 20170d20ed3SAlexander Motin .hex = false, 20270d20ed3SAlexander Motin .verbose = false, 20370d20ed3SAlexander Motin .eds = false, 20470d20ed3SAlexander Motin .dev = NULL, 20570d20ed3SAlexander Motin }; 20670d20ed3SAlexander Motin 20770d20ed3SAlexander Motin static const struct opts report_opts[] = { 20870d20ed3SAlexander Motin OPT("hex", 'x', arg_none, report_opt, hex, 20970d20ed3SAlexander Motin "Print reservation status in hex"), 21070d20ed3SAlexander Motin OPT("verbose", 'v', arg_none, report_opt, verbose, 21170d20ed3SAlexander Motin "More verbosity"), 21270d20ed3SAlexander Motin OPT("eds", 'e', arg_none, report_opt, eds, 21370d20ed3SAlexander Motin "Extended Data Structure"), 21470d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 21570d20ed3SAlexander Motin }; 21670d20ed3SAlexander Motin 21770d20ed3SAlexander Motin static const struct args report_args[] = { 21870d20ed3SAlexander Motin { arg_string, &report_opt.dev, "namespace-id" }, 21970d20ed3SAlexander Motin { arg_none, NULL, NULL }, 22070d20ed3SAlexander Motin }; 22170d20ed3SAlexander Motin 22270d20ed3SAlexander Motin static struct cmd report_cmd = { 22370d20ed3SAlexander Motin .name = "report", 22470d20ed3SAlexander Motin .fn = resvreport, 22570d20ed3SAlexander Motin .descr = "Print reservation status", 22670d20ed3SAlexander Motin .ctx_size = sizeof(report_opt), 22770d20ed3SAlexander Motin .opts = report_opts, 22870d20ed3SAlexander Motin .args = report_args, 22970d20ed3SAlexander Motin }; 23070d20ed3SAlexander Motin 23170d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, report_cmd); 23270d20ed3SAlexander Motin 23370d20ed3SAlexander Motin /* handles NVME_OPC_RESERVATION_* NVM commands */ 23470d20ed3SAlexander Motin 23570d20ed3SAlexander Motin static void 23670d20ed3SAlexander Motin resvacquire(const struct cmd *f, int argc, char *argv[]) 23770d20ed3SAlexander Motin { 23870d20ed3SAlexander Motin struct nvme_pt_command pt; 23970d20ed3SAlexander Motin uint64_t data[2]; 24070d20ed3SAlexander Motin int fd; 24170d20ed3SAlexander Motin uint32_t nsid; 24270d20ed3SAlexander Motin 24370d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 24470d20ed3SAlexander Motin return; 245*1f15d49eSAlexander Motin open_dev(acquire_opt.dev, &fd, 0, 1); 24670d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 24770d20ed3SAlexander Motin if (nsid == 0) { 24870d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 24970d20ed3SAlexander Motin arg_help(argc, argv, f); 25070d20ed3SAlexander Motin } 25170d20ed3SAlexander Motin 25270d20ed3SAlexander Motin data[0] = htole64(acquire_opt.crkey); 25370d20ed3SAlexander Motin data[1] = htole64(acquire_opt.prkey); 25470d20ed3SAlexander Motin 25570d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 25670d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_ACQUIRE; 25770d20ed3SAlexander Motin pt.cmd.cdw10 = htole32((acquire_opt.racqa & 7) | 25870d20ed3SAlexander Motin (acquire_opt.rtype << 8)); 25970d20ed3SAlexander Motin pt.buf = &data; 26070d20ed3SAlexander Motin pt.len = sizeof(data); 26170d20ed3SAlexander Motin pt.is_read = 0; 26270d20ed3SAlexander Motin 26370d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 26470d20ed3SAlexander Motin err(1, "acquire request failed"); 26570d20ed3SAlexander Motin 26670d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 26770d20ed3SAlexander Motin errx(1, "acquire request returned error"); 26870d20ed3SAlexander Motin 26970d20ed3SAlexander Motin close(fd); 27070d20ed3SAlexander Motin exit(0); 27170d20ed3SAlexander Motin } 27270d20ed3SAlexander Motin 27370d20ed3SAlexander Motin static void 27470d20ed3SAlexander Motin resvregister(const struct cmd *f, int argc, char *argv[]) 27570d20ed3SAlexander Motin { 27670d20ed3SAlexander Motin struct nvme_pt_command pt; 27770d20ed3SAlexander Motin uint64_t data[2]; 27870d20ed3SAlexander Motin int fd; 27970d20ed3SAlexander Motin uint32_t nsid; 28070d20ed3SAlexander Motin 28170d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 28270d20ed3SAlexander Motin return; 283*1f15d49eSAlexander Motin open_dev(register_opt.dev, &fd, 0, 1); 28470d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 28570d20ed3SAlexander Motin if (nsid == 0) { 28670d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 28770d20ed3SAlexander Motin arg_help(argc, argv, f); 28870d20ed3SAlexander Motin } 28970d20ed3SAlexander Motin 29070d20ed3SAlexander Motin data[0] = htole64(register_opt.crkey); 29170d20ed3SAlexander Motin data[1] = htole64(register_opt.nrkey); 29270d20ed3SAlexander Motin 29370d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 29470d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_REGISTER; 29570d20ed3SAlexander Motin pt.cmd.cdw10 = htole32((register_opt.rrega & 7) | 29670d20ed3SAlexander Motin (register_opt.iekey << 3) | (register_opt.cptpl << 30)); 29770d20ed3SAlexander Motin pt.buf = &data; 29870d20ed3SAlexander Motin pt.len = sizeof(data); 29970d20ed3SAlexander Motin pt.is_read = 0; 30070d20ed3SAlexander Motin 30170d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 30270d20ed3SAlexander Motin err(1, "register request failed"); 30370d20ed3SAlexander Motin 30470d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 30570d20ed3SAlexander Motin errx(1, "register request returned error"); 30670d20ed3SAlexander Motin 30770d20ed3SAlexander Motin close(fd); 30870d20ed3SAlexander Motin exit(0); 30970d20ed3SAlexander Motin } 31070d20ed3SAlexander Motin 31170d20ed3SAlexander Motin static void 31270d20ed3SAlexander Motin resvrelease(const struct cmd *f, int argc, char *argv[]) 31370d20ed3SAlexander Motin { 31470d20ed3SAlexander Motin struct nvme_pt_command pt; 31570d20ed3SAlexander Motin uint64_t data[1]; 31670d20ed3SAlexander Motin int fd; 31770d20ed3SAlexander Motin uint32_t nsid; 31870d20ed3SAlexander Motin 31970d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 32070d20ed3SAlexander Motin return; 321*1f15d49eSAlexander Motin open_dev(release_opt.dev, &fd, 0, 1); 32270d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 32370d20ed3SAlexander Motin if (nsid == 0) { 32470d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 32570d20ed3SAlexander Motin arg_help(argc, argv, f); 32670d20ed3SAlexander Motin } 32770d20ed3SAlexander Motin 32870d20ed3SAlexander Motin data[0] = htole64(release_opt.crkey); 32970d20ed3SAlexander Motin 33070d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 33170d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_RELEASE; 33270d20ed3SAlexander Motin pt.cmd.cdw10 = htole32((release_opt.rrela & 7) | 33370d20ed3SAlexander Motin (release_opt.rtype << 8)); 33470d20ed3SAlexander Motin pt.buf = &data; 33570d20ed3SAlexander Motin pt.len = sizeof(data); 33670d20ed3SAlexander Motin pt.is_read = 0; 33770d20ed3SAlexander Motin 33870d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 33970d20ed3SAlexander Motin err(1, "release request failed"); 34070d20ed3SAlexander Motin 34170d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 34270d20ed3SAlexander Motin errx(1, "release request returned error"); 34370d20ed3SAlexander Motin 34470d20ed3SAlexander Motin close(fd); 34570d20ed3SAlexander Motin exit(0); 34670d20ed3SAlexander Motin } 34770d20ed3SAlexander Motin 34870d20ed3SAlexander Motin static void 34970d20ed3SAlexander Motin resvreport(const struct cmd *f, int argc, char *argv[]) 35070d20ed3SAlexander Motin { 35170d20ed3SAlexander Motin struct nvme_pt_command pt; 35270d20ed3SAlexander Motin struct nvme_resv_status *s; 35370d20ed3SAlexander Motin struct nvme_resv_status_ext *e; 354217c81f3SAlexander Motin uint8_t data[4096] __aligned(4); 35570d20ed3SAlexander Motin int fd; 35670d20ed3SAlexander Motin u_int i, n; 35770d20ed3SAlexander Motin uint32_t nsid; 35870d20ed3SAlexander Motin 35970d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 36070d20ed3SAlexander Motin return; 361*1f15d49eSAlexander Motin open_dev(report_opt.dev, &fd, 0, 1); 36270d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 36370d20ed3SAlexander Motin if (nsid == 0) { 36470d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 36570d20ed3SAlexander Motin arg_help(argc, argv, f); 36670d20ed3SAlexander Motin } 36770d20ed3SAlexander Motin 36870d20ed3SAlexander Motin bzero(data, sizeof(data)); 36970d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 37070d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_REPORT; 37170d20ed3SAlexander Motin pt.cmd.cdw10 = htole32(sizeof(data) / 4 - 1); 37270d20ed3SAlexander Motin pt.cmd.cdw11 = htole32(report_opt.eds); /* EDS */ 37370d20ed3SAlexander Motin pt.buf = &data; 37470d20ed3SAlexander Motin pt.len = sizeof(data); 37570d20ed3SAlexander Motin pt.is_read = 1; 37670d20ed3SAlexander Motin 37770d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 37870d20ed3SAlexander Motin err(1, "report request failed"); 37970d20ed3SAlexander Motin 38070d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 38170d20ed3SAlexander Motin errx(1, "report request returned error"); 38270d20ed3SAlexander Motin 38370d20ed3SAlexander Motin close(fd); 38470d20ed3SAlexander Motin 38570d20ed3SAlexander Motin if (report_opt.eds) 38670d20ed3SAlexander Motin nvme_resv_status_ext_swapbytes((void *)data, sizeof(data)); 38770d20ed3SAlexander Motin else 38870d20ed3SAlexander Motin nvme_resv_status_swapbytes((void *)data, sizeof(data)); 38970d20ed3SAlexander Motin 39070d20ed3SAlexander Motin if (report_opt.hex) { 39170d20ed3SAlexander Motin i = sizeof(data); 39270d20ed3SAlexander Motin if (!report_opt.verbose) { 39370d20ed3SAlexander Motin for (; i > 64; i--) { 39470d20ed3SAlexander Motin if (data[i - 1] != 0) 39570d20ed3SAlexander Motin break; 39670d20ed3SAlexander Motin } 39770d20ed3SAlexander Motin } 39870d20ed3SAlexander Motin print_hex(&data, i); 39970d20ed3SAlexander Motin exit(0); 40070d20ed3SAlexander Motin } 40170d20ed3SAlexander Motin 40270d20ed3SAlexander Motin s = (struct nvme_resv_status *)data; 40370d20ed3SAlexander Motin n = (s->regctl[1] << 8) | s->regctl[0]; 40470d20ed3SAlexander Motin printf("Generation: %u\n", s->gen); 40570d20ed3SAlexander Motin printf("Reservation Type: %u\n", s->rtype); 40670d20ed3SAlexander Motin printf("Number of Registered Controllers: %u\n", n); 40770d20ed3SAlexander Motin printf("Persist Through Power Loss State: %u\n", s->ptpls); 40870d20ed3SAlexander Motin if (report_opt.eds) { 40970d20ed3SAlexander Motin e = (struct nvme_resv_status_ext *)data; 41070d20ed3SAlexander Motin n = MIN(n, (sizeof(data) - sizeof(e)) / sizeof(e->ctrlr[0])); 41170d20ed3SAlexander Motin for (i = 0; i < n; i++) { 41270d20ed3SAlexander Motin printf("Controller ID: 0x%04x\n", 41370d20ed3SAlexander Motin e->ctrlr[i].ctrlr_id); 41470d20ed3SAlexander Motin printf(" Reservation Status: %u\n", 41570d20ed3SAlexander Motin e->ctrlr[i].rcsts); 41670d20ed3SAlexander Motin printf(" Reservation Key: 0x%08jx\n", 41770d20ed3SAlexander Motin e->ctrlr[i].rkey); 41870d20ed3SAlexander Motin printf(" Host Identifier: 0x%08jx%08jx\n", 41970d20ed3SAlexander Motin e->ctrlr[i].hostid[0], e->ctrlr[i].hostid[1]); 42070d20ed3SAlexander Motin } 42170d20ed3SAlexander Motin } else { 42270d20ed3SAlexander Motin n = MIN(n, (sizeof(data) - sizeof(s)) / sizeof(s->ctrlr[0])); 42370d20ed3SAlexander Motin for (i = 0; i < n; i++) { 42470d20ed3SAlexander Motin printf("Controller ID: 0x%04x\n", 42570d20ed3SAlexander Motin s->ctrlr[i].ctrlr_id); 42670d20ed3SAlexander Motin printf(" Reservation Status: %u\n", 42770d20ed3SAlexander Motin s->ctrlr[i].rcsts); 42870d20ed3SAlexander Motin printf(" Host Identifier: 0x%08jx\n", 42970d20ed3SAlexander Motin s->ctrlr[i].hostid); 43070d20ed3SAlexander Motin printf(" Reservation Key: 0x%08jx\n", 43170d20ed3SAlexander Motin s->ctrlr[i].rkey); 43270d20ed3SAlexander Motin } 43370d20ed3SAlexander Motin } 43470d20ed3SAlexander Motin exit(0); 43570d20ed3SAlexander Motin } 43670d20ed3SAlexander Motin 43770d20ed3SAlexander Motin static void 43870d20ed3SAlexander Motin resv(const struct cmd *nf __unused, int argc, char *argv[]) 43970d20ed3SAlexander Motin { 44070d20ed3SAlexander Motin 44170d20ed3SAlexander Motin cmd_dispatch(argc, argv, &resv_cmd); 44270d20ed3SAlexander Motin } 443