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> 415dc463f9SAlexander Motin #include <sysexits.h> 4270d20ed3SAlexander Motin #include <unistd.h> 4370d20ed3SAlexander Motin 4470d20ed3SAlexander Motin #include "nvmecontrol.h" 4570d20ed3SAlexander Motin 4670d20ed3SAlexander Motin /* Tables for command line parsing */ 4770d20ed3SAlexander Motin 4870d20ed3SAlexander Motin static cmd_fn_t resv; 4970d20ed3SAlexander Motin static cmd_fn_t resvacquire; 5070d20ed3SAlexander Motin static cmd_fn_t resvregister; 5170d20ed3SAlexander Motin static cmd_fn_t resvrelease; 5270d20ed3SAlexander Motin static cmd_fn_t resvreport; 5370d20ed3SAlexander Motin 5470d20ed3SAlexander Motin #define NONE 0xffffffffu 5570d20ed3SAlexander Motin #define NONE64 0xffffffffffffffffull 5670d20ed3SAlexander Motin #define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc } 5770d20ed3SAlexander Motin #define OPT_END { NULL, 0, arg_none, NULL, NULL } 5870d20ed3SAlexander Motin 5970d20ed3SAlexander Motin static struct cmd resv_cmd = { 6070d20ed3SAlexander Motin .name = "resv", 6170d20ed3SAlexander Motin .fn = resv, 6270d20ed3SAlexander Motin .descr = "Reservation commands", 6370d20ed3SAlexander Motin .ctx_size = 0, 6470d20ed3SAlexander Motin .opts = NULL, 6570d20ed3SAlexander Motin .args = NULL, 6670d20ed3SAlexander Motin }; 6770d20ed3SAlexander Motin 6870d20ed3SAlexander Motin CMD_COMMAND(resv_cmd); 6970d20ed3SAlexander Motin 7070d20ed3SAlexander Motin static struct acquire_options { 7170d20ed3SAlexander Motin uint64_t crkey; 7270d20ed3SAlexander Motin uint64_t prkey; 7370d20ed3SAlexander Motin uint8_t rtype; 7470d20ed3SAlexander Motin uint8_t racqa; 7570d20ed3SAlexander Motin const char *dev; 7670d20ed3SAlexander Motin } acquire_opt = { 7770d20ed3SAlexander Motin .crkey = 0, 7870d20ed3SAlexander Motin .prkey = 0, 7970d20ed3SAlexander Motin .rtype = 0, 8070d20ed3SAlexander Motin .racqa = 0, 8170d20ed3SAlexander Motin .dev = NULL, 8270d20ed3SAlexander Motin }; 8370d20ed3SAlexander Motin 8470d20ed3SAlexander Motin static const struct opts acquire_opts[] = { 8570d20ed3SAlexander Motin OPT("crkey", 'c', arg_uint64, acquire_opt, crkey, 8670d20ed3SAlexander Motin "Current Reservation Key"), 8770d20ed3SAlexander Motin OPT("prkey", 'p', arg_uint64, acquire_opt, prkey, 8870d20ed3SAlexander Motin "Preempt Reservation Key"), 8970d20ed3SAlexander Motin OPT("rtype", 't', arg_uint8, acquire_opt, rtype, 9070d20ed3SAlexander Motin "Reservation Type"), 9170d20ed3SAlexander Motin OPT("racqa", 'a', arg_uint8, acquire_opt, racqa, 9270d20ed3SAlexander Motin "Acquire Action (0=acq, 1=pre, 2=pre+ab)"), 9370d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 9470d20ed3SAlexander Motin }; 9570d20ed3SAlexander Motin 9670d20ed3SAlexander Motin static const struct args acquire_args[] = { 9770d20ed3SAlexander Motin { arg_string, &acquire_opt.dev, "namespace-id" }, 9870d20ed3SAlexander Motin { arg_none, NULL, NULL }, 9970d20ed3SAlexander Motin }; 10070d20ed3SAlexander Motin 10170d20ed3SAlexander Motin static struct cmd acquire_cmd = { 10270d20ed3SAlexander Motin .name = "acquire", 10370d20ed3SAlexander Motin .fn = resvacquire, 10470d20ed3SAlexander Motin .descr = "Acquire/preempt reservation", 10570d20ed3SAlexander Motin .ctx_size = sizeof(acquire_opt), 10670d20ed3SAlexander Motin .opts = acquire_opts, 10770d20ed3SAlexander Motin .args = acquire_args, 10870d20ed3SAlexander Motin }; 10970d20ed3SAlexander Motin 11070d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, acquire_cmd); 11170d20ed3SAlexander Motin 11270d20ed3SAlexander Motin static struct register_options { 11370d20ed3SAlexander Motin uint64_t crkey; 11470d20ed3SAlexander Motin uint64_t nrkey; 11570d20ed3SAlexander Motin uint8_t rrega; 11670d20ed3SAlexander Motin bool iekey; 11770d20ed3SAlexander Motin uint8_t cptpl; 11870d20ed3SAlexander Motin const char *dev; 11970d20ed3SAlexander Motin } register_opt = { 12070d20ed3SAlexander Motin .crkey = 0, 12170d20ed3SAlexander Motin .nrkey = 0, 12270d20ed3SAlexander Motin .rrega = 0, 12370d20ed3SAlexander Motin .iekey = false, 12470d20ed3SAlexander Motin .cptpl = 0, 12570d20ed3SAlexander Motin .dev = NULL, 12670d20ed3SAlexander Motin }; 12770d20ed3SAlexander Motin 12870d20ed3SAlexander Motin static const struct opts register_opts[] = { 12970d20ed3SAlexander Motin OPT("crkey", 'c', arg_uint64, register_opt, crkey, 13070d20ed3SAlexander Motin "Current Reservation Key"), 13170d20ed3SAlexander Motin OPT("nrkey", 'k', arg_uint64, register_opt, nrkey, 13270d20ed3SAlexander Motin "New Reservation Key"), 13370d20ed3SAlexander Motin OPT("rrega", 'r', arg_uint8, register_opt, rrega, 13470d20ed3SAlexander Motin "Register Action (0=reg, 1=unreg, 2=replace)"), 13570d20ed3SAlexander Motin OPT("iekey", 'i', arg_none, register_opt, iekey, 13670d20ed3SAlexander Motin "Ignore Existing Key"), 13770d20ed3SAlexander Motin OPT("cptpl", 'p', arg_uint8, register_opt, cptpl, 13870d20ed3SAlexander Motin "Change Persist Through Power Loss State"), 13970d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 14070d20ed3SAlexander Motin }; 14170d20ed3SAlexander Motin 14270d20ed3SAlexander Motin static const struct args register_args[] = { 14370d20ed3SAlexander Motin { arg_string, ®ister_opt.dev, "namespace-id" }, 14470d20ed3SAlexander Motin { arg_none, NULL, NULL }, 14570d20ed3SAlexander Motin }; 14670d20ed3SAlexander Motin 14770d20ed3SAlexander Motin static struct cmd register_cmd = { 14870d20ed3SAlexander Motin .name = "register", 14970d20ed3SAlexander Motin .fn = resvregister, 15070d20ed3SAlexander Motin .descr = "Register/unregister reservation", 15170d20ed3SAlexander Motin .ctx_size = sizeof(register_opt), 15270d20ed3SAlexander Motin .opts = register_opts, 15370d20ed3SAlexander Motin .args = register_args, 15470d20ed3SAlexander Motin }; 15570d20ed3SAlexander Motin 15670d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, register_cmd); 15770d20ed3SAlexander Motin 15870d20ed3SAlexander Motin static struct release_options { 15970d20ed3SAlexander Motin uint64_t crkey; 16070d20ed3SAlexander Motin uint8_t rtype; 16170d20ed3SAlexander Motin uint8_t rrela; 16270d20ed3SAlexander Motin const char *dev; 16370d20ed3SAlexander Motin } release_opt = { 16470d20ed3SAlexander Motin .crkey = 0, 16570d20ed3SAlexander Motin .rtype = 0, 16670d20ed3SAlexander Motin .rrela = 0, 16770d20ed3SAlexander Motin .dev = NULL, 16870d20ed3SAlexander Motin }; 16970d20ed3SAlexander Motin 17070d20ed3SAlexander Motin static const struct opts release_opts[] = { 17170d20ed3SAlexander Motin OPT("crkey", 'c', arg_uint64, release_opt, crkey, 17270d20ed3SAlexander Motin "Current Reservation Key"), 17370d20ed3SAlexander Motin OPT("rtype", 't', arg_uint8, release_opt, rtype, 17470d20ed3SAlexander Motin "Reservation Type"), 17570d20ed3SAlexander Motin OPT("rrela", 'a', arg_uint8, release_opt, rrela, 17670d20ed3SAlexander Motin "Release Action (0=release, 1=clear)"), 17770d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 17870d20ed3SAlexander Motin }; 17970d20ed3SAlexander Motin 18070d20ed3SAlexander Motin static const struct args release_args[] = { 18170d20ed3SAlexander Motin { arg_string, &release_opt.dev, "namespace-id" }, 18270d20ed3SAlexander Motin { arg_none, NULL, NULL }, 18370d20ed3SAlexander Motin }; 18470d20ed3SAlexander Motin 18570d20ed3SAlexander Motin static struct cmd release_cmd = { 18670d20ed3SAlexander Motin .name = "release", 18770d20ed3SAlexander Motin .fn = resvrelease, 18870d20ed3SAlexander Motin .descr = "Release/clear reservation", 18970d20ed3SAlexander Motin .ctx_size = sizeof(release_opt), 19070d20ed3SAlexander Motin .opts = release_opts, 19170d20ed3SAlexander Motin .args = release_args, 19270d20ed3SAlexander Motin }; 19370d20ed3SAlexander Motin 19470d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, release_cmd); 19570d20ed3SAlexander Motin 19670d20ed3SAlexander Motin static struct report_options { 19770d20ed3SAlexander Motin bool hex; 19870d20ed3SAlexander Motin bool verbose; 19970d20ed3SAlexander Motin bool eds; 20070d20ed3SAlexander Motin const char *dev; 20170d20ed3SAlexander Motin } report_opt = { 20270d20ed3SAlexander Motin .hex = false, 20370d20ed3SAlexander Motin .verbose = false, 20470d20ed3SAlexander Motin .eds = false, 20570d20ed3SAlexander Motin .dev = NULL, 20670d20ed3SAlexander Motin }; 20770d20ed3SAlexander Motin 20870d20ed3SAlexander Motin static const struct opts report_opts[] = { 20970d20ed3SAlexander Motin OPT("hex", 'x', arg_none, report_opt, hex, 21070d20ed3SAlexander Motin "Print reservation status in hex"), 21170d20ed3SAlexander Motin OPT("verbose", 'v', arg_none, report_opt, verbose, 21270d20ed3SAlexander Motin "More verbosity"), 21370d20ed3SAlexander Motin OPT("eds", 'e', arg_none, report_opt, eds, 21470d20ed3SAlexander Motin "Extended Data Structure"), 21570d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 21670d20ed3SAlexander Motin }; 21770d20ed3SAlexander Motin 21870d20ed3SAlexander Motin static const struct args report_args[] = { 21970d20ed3SAlexander Motin { arg_string, &report_opt.dev, "namespace-id" }, 22070d20ed3SAlexander Motin { arg_none, NULL, NULL }, 22170d20ed3SAlexander Motin }; 22270d20ed3SAlexander Motin 22370d20ed3SAlexander Motin static struct cmd report_cmd = { 22470d20ed3SAlexander Motin .name = "report", 22570d20ed3SAlexander Motin .fn = resvreport, 22670d20ed3SAlexander Motin .descr = "Print reservation status", 22770d20ed3SAlexander Motin .ctx_size = sizeof(report_opt), 22870d20ed3SAlexander Motin .opts = report_opts, 22970d20ed3SAlexander Motin .args = report_args, 23070d20ed3SAlexander Motin }; 23170d20ed3SAlexander Motin 23270d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, report_cmd); 23370d20ed3SAlexander Motin 23470d20ed3SAlexander Motin /* handles NVME_OPC_RESERVATION_* NVM commands */ 23570d20ed3SAlexander Motin 23670d20ed3SAlexander Motin static void 23770d20ed3SAlexander Motin resvacquire(const struct cmd *f, int argc, char *argv[]) 23870d20ed3SAlexander Motin { 23970d20ed3SAlexander Motin struct nvme_pt_command pt; 24070d20ed3SAlexander Motin uint64_t data[2]; 24170d20ed3SAlexander Motin int fd; 24270d20ed3SAlexander Motin uint32_t nsid; 24370d20ed3SAlexander Motin 24470d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 24570d20ed3SAlexander Motin return; 2461f15d49eSAlexander Motin open_dev(acquire_opt.dev, &fd, 0, 1); 24770d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 24870d20ed3SAlexander Motin if (nsid == 0) { 24970d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 25070d20ed3SAlexander Motin arg_help(argc, argv, f); 25170d20ed3SAlexander Motin } 25270d20ed3SAlexander Motin 25370d20ed3SAlexander Motin data[0] = htole64(acquire_opt.crkey); 25470d20ed3SAlexander Motin data[1] = htole64(acquire_opt.prkey); 25570d20ed3SAlexander Motin 25670d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 25770d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_ACQUIRE; 258*6aa5b10dSYuri Pankov pt.cmd.nsid = htole32(nsid); 25970d20ed3SAlexander Motin pt.cmd.cdw10 = htole32((acquire_opt.racqa & 7) | 26070d20ed3SAlexander Motin (acquire_opt.rtype << 8)); 26170d20ed3SAlexander Motin pt.buf = &data; 26270d20ed3SAlexander Motin pt.len = sizeof(data); 26370d20ed3SAlexander Motin pt.is_read = 0; 26470d20ed3SAlexander Motin 26570d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 2665dc463f9SAlexander Motin err(EX_IOERR, "acquire request failed"); 26770d20ed3SAlexander Motin 26870d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 2695dc463f9SAlexander Motin errx(EX_IOERR, "acquire request returned error"); 27070d20ed3SAlexander Motin 27170d20ed3SAlexander Motin close(fd); 27270d20ed3SAlexander Motin exit(0); 27370d20ed3SAlexander Motin } 27470d20ed3SAlexander Motin 27570d20ed3SAlexander Motin static void 27670d20ed3SAlexander Motin resvregister(const struct cmd *f, int argc, char *argv[]) 27770d20ed3SAlexander Motin { 27870d20ed3SAlexander Motin struct nvme_pt_command pt; 27970d20ed3SAlexander Motin uint64_t data[2]; 28070d20ed3SAlexander Motin int fd; 28170d20ed3SAlexander Motin uint32_t nsid; 28270d20ed3SAlexander Motin 28370d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 28470d20ed3SAlexander Motin return; 2851f15d49eSAlexander Motin open_dev(register_opt.dev, &fd, 0, 1); 28670d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 28770d20ed3SAlexander Motin if (nsid == 0) { 28870d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 28970d20ed3SAlexander Motin arg_help(argc, argv, f); 29070d20ed3SAlexander Motin } 29170d20ed3SAlexander Motin 29270d20ed3SAlexander Motin data[0] = htole64(register_opt.crkey); 29370d20ed3SAlexander Motin data[1] = htole64(register_opt.nrkey); 29470d20ed3SAlexander Motin 29570d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 29670d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_REGISTER; 297*6aa5b10dSYuri Pankov pt.cmd.nsid = htole32(nsid); 29870d20ed3SAlexander Motin pt.cmd.cdw10 = htole32((register_opt.rrega & 7) | 29970d20ed3SAlexander Motin (register_opt.iekey << 3) | (register_opt.cptpl << 30)); 30070d20ed3SAlexander Motin pt.buf = &data; 30170d20ed3SAlexander Motin pt.len = sizeof(data); 30270d20ed3SAlexander Motin pt.is_read = 0; 30370d20ed3SAlexander Motin 30470d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 3055dc463f9SAlexander Motin err(EX_IOERR, "register request failed"); 30670d20ed3SAlexander Motin 30770d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 3085dc463f9SAlexander Motin errx(EX_IOERR, "register request returned error"); 30970d20ed3SAlexander Motin 31070d20ed3SAlexander Motin close(fd); 31170d20ed3SAlexander Motin exit(0); 31270d20ed3SAlexander Motin } 31370d20ed3SAlexander Motin 31470d20ed3SAlexander Motin static void 31570d20ed3SAlexander Motin resvrelease(const struct cmd *f, int argc, char *argv[]) 31670d20ed3SAlexander Motin { 31770d20ed3SAlexander Motin struct nvme_pt_command pt; 31870d20ed3SAlexander Motin uint64_t data[1]; 31970d20ed3SAlexander Motin int fd; 32070d20ed3SAlexander Motin uint32_t nsid; 32170d20ed3SAlexander Motin 32270d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 32370d20ed3SAlexander Motin return; 3241f15d49eSAlexander Motin open_dev(release_opt.dev, &fd, 0, 1); 32570d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 32670d20ed3SAlexander Motin if (nsid == 0) { 32770d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 32870d20ed3SAlexander Motin arg_help(argc, argv, f); 32970d20ed3SAlexander Motin } 33070d20ed3SAlexander Motin 33170d20ed3SAlexander Motin data[0] = htole64(release_opt.crkey); 33270d20ed3SAlexander Motin 33370d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 33470d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_RELEASE; 335*6aa5b10dSYuri Pankov pt.cmd.nsid = htole32(nsid); 33670d20ed3SAlexander Motin pt.cmd.cdw10 = htole32((release_opt.rrela & 7) | 33770d20ed3SAlexander Motin (release_opt.rtype << 8)); 33870d20ed3SAlexander Motin pt.buf = &data; 33970d20ed3SAlexander Motin pt.len = sizeof(data); 34070d20ed3SAlexander Motin pt.is_read = 0; 34170d20ed3SAlexander Motin 34270d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 3435dc463f9SAlexander Motin err(EX_IOERR, "release request failed"); 34470d20ed3SAlexander Motin 34570d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 3465dc463f9SAlexander Motin errx(EX_IOERR, "release request returned error"); 34770d20ed3SAlexander Motin 34870d20ed3SAlexander Motin close(fd); 34970d20ed3SAlexander Motin exit(0); 35070d20ed3SAlexander Motin } 35170d20ed3SAlexander Motin 35270d20ed3SAlexander Motin static void 35370d20ed3SAlexander Motin resvreport(const struct cmd *f, int argc, char *argv[]) 35470d20ed3SAlexander Motin { 35570d20ed3SAlexander Motin struct nvme_pt_command pt; 35670d20ed3SAlexander Motin struct nvme_resv_status *s; 35770d20ed3SAlexander Motin struct nvme_resv_status_ext *e; 358217c81f3SAlexander Motin uint8_t data[4096] __aligned(4); 35970d20ed3SAlexander Motin int fd; 36070d20ed3SAlexander Motin u_int i, n; 36170d20ed3SAlexander Motin uint32_t nsid; 36270d20ed3SAlexander Motin 36370d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 36470d20ed3SAlexander Motin return; 3651f15d49eSAlexander Motin open_dev(report_opt.dev, &fd, 0, 1); 36670d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 36770d20ed3SAlexander Motin if (nsid == 0) { 36870d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 36970d20ed3SAlexander Motin arg_help(argc, argv, f); 37070d20ed3SAlexander Motin } 37170d20ed3SAlexander Motin 37270d20ed3SAlexander Motin bzero(data, sizeof(data)); 37370d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 37470d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_REPORT; 375*6aa5b10dSYuri Pankov pt.cmd.nsid = htole32(nsid); 37670d20ed3SAlexander Motin pt.cmd.cdw10 = htole32(sizeof(data) / 4 - 1); 37770d20ed3SAlexander Motin pt.cmd.cdw11 = htole32(report_opt.eds); /* EDS */ 37870d20ed3SAlexander Motin pt.buf = &data; 37970d20ed3SAlexander Motin pt.len = sizeof(data); 38070d20ed3SAlexander Motin pt.is_read = 1; 38170d20ed3SAlexander Motin 38270d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 3835dc463f9SAlexander Motin err(EX_IOERR, "report request failed"); 38470d20ed3SAlexander Motin 38570d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 3865dc463f9SAlexander Motin errx(EX_IOERR, "report request returned error"); 38770d20ed3SAlexander Motin 38870d20ed3SAlexander Motin close(fd); 38970d20ed3SAlexander Motin 39070d20ed3SAlexander Motin if (report_opt.eds) 39170d20ed3SAlexander Motin nvme_resv_status_ext_swapbytes((void *)data, sizeof(data)); 39270d20ed3SAlexander Motin else 39370d20ed3SAlexander Motin nvme_resv_status_swapbytes((void *)data, sizeof(data)); 39470d20ed3SAlexander Motin 39570d20ed3SAlexander Motin if (report_opt.hex) { 39670d20ed3SAlexander Motin i = sizeof(data); 39770d20ed3SAlexander Motin if (!report_opt.verbose) { 39870d20ed3SAlexander Motin for (; i > 64; i--) { 39970d20ed3SAlexander Motin if (data[i - 1] != 0) 40070d20ed3SAlexander Motin break; 40170d20ed3SAlexander Motin } 40270d20ed3SAlexander Motin } 40370d20ed3SAlexander Motin print_hex(&data, i); 40470d20ed3SAlexander Motin exit(0); 40570d20ed3SAlexander Motin } 40670d20ed3SAlexander Motin 40770d20ed3SAlexander Motin s = (struct nvme_resv_status *)data; 40870d20ed3SAlexander Motin n = (s->regctl[1] << 8) | s->regctl[0]; 40970d20ed3SAlexander Motin printf("Generation: %u\n", s->gen); 41070d20ed3SAlexander Motin printf("Reservation Type: %u\n", s->rtype); 41170d20ed3SAlexander Motin printf("Number of Registered Controllers: %u\n", n); 41270d20ed3SAlexander Motin printf("Persist Through Power Loss State: %u\n", s->ptpls); 41370d20ed3SAlexander Motin if (report_opt.eds) { 41470d20ed3SAlexander Motin e = (struct nvme_resv_status_ext *)data; 41570d20ed3SAlexander Motin n = MIN(n, (sizeof(data) - sizeof(e)) / sizeof(e->ctrlr[0])); 41670d20ed3SAlexander Motin for (i = 0; i < n; i++) { 41770d20ed3SAlexander Motin printf("Controller ID: 0x%04x\n", 41870d20ed3SAlexander Motin e->ctrlr[i].ctrlr_id); 41970d20ed3SAlexander Motin printf(" Reservation Status: %u\n", 42070d20ed3SAlexander Motin e->ctrlr[i].rcsts); 42170d20ed3SAlexander Motin printf(" Reservation Key: 0x%08jx\n", 42270d20ed3SAlexander Motin e->ctrlr[i].rkey); 42370d20ed3SAlexander Motin printf(" Host Identifier: 0x%08jx%08jx\n", 42470d20ed3SAlexander Motin e->ctrlr[i].hostid[0], e->ctrlr[i].hostid[1]); 42570d20ed3SAlexander Motin } 42670d20ed3SAlexander Motin } else { 42770d20ed3SAlexander Motin n = MIN(n, (sizeof(data) - sizeof(s)) / sizeof(s->ctrlr[0])); 42870d20ed3SAlexander Motin for (i = 0; i < n; i++) { 42970d20ed3SAlexander Motin printf("Controller ID: 0x%04x\n", 43070d20ed3SAlexander Motin s->ctrlr[i].ctrlr_id); 43170d20ed3SAlexander Motin printf(" Reservation Status: %u\n", 43270d20ed3SAlexander Motin s->ctrlr[i].rcsts); 43370d20ed3SAlexander Motin printf(" Host Identifier: 0x%08jx\n", 43470d20ed3SAlexander Motin s->ctrlr[i].hostid); 43570d20ed3SAlexander Motin printf(" Reservation Key: 0x%08jx\n", 43670d20ed3SAlexander Motin s->ctrlr[i].rkey); 43770d20ed3SAlexander Motin } 43870d20ed3SAlexander Motin } 43970d20ed3SAlexander Motin exit(0); 44070d20ed3SAlexander Motin } 44170d20ed3SAlexander Motin 44270d20ed3SAlexander Motin static void 44370d20ed3SAlexander Motin resv(const struct cmd *nf __unused, int argc, char *argv[]) 44470d20ed3SAlexander Motin { 44570d20ed3SAlexander Motin 44670d20ed3SAlexander Motin cmd_dispatch(argc, argv, &resv_cmd); 44770d20ed3SAlexander Motin } 448