1*70d20ed3SAlexander Motin /*- 2*70d20ed3SAlexander Motin * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*70d20ed3SAlexander Motin * 4*70d20ed3SAlexander Motin * Copyright (C) 2019 Alexander Motin <mav@FreeBSD.org> 5*70d20ed3SAlexander Motin * 6*70d20ed3SAlexander Motin * Redistribution and use in source and binary forms, with or without 7*70d20ed3SAlexander Motin * modification, are permitted provided that the following conditions 8*70d20ed3SAlexander Motin * are met: 9*70d20ed3SAlexander Motin * 1. Redistributions of source code must retain the above copyright 10*70d20ed3SAlexander Motin * notice, this list of conditions and the following disclaimer, 11*70d20ed3SAlexander Motin * without modification, immediately at the beginning of the file. 12*70d20ed3SAlexander Motin * 2. Redistributions in binary form must reproduce the above copyright 13*70d20ed3SAlexander Motin * notice, this list of conditions and the following disclaimer in the 14*70d20ed3SAlexander Motin * documentation and/or other materials provided with the distribution. 15*70d20ed3SAlexander Motin * 16*70d20ed3SAlexander Motin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17*70d20ed3SAlexander Motin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18*70d20ed3SAlexander Motin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19*70d20ed3SAlexander Motin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20*70d20ed3SAlexander Motin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21*70d20ed3SAlexander Motin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22*70d20ed3SAlexander Motin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23*70d20ed3SAlexander Motin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24*70d20ed3SAlexander Motin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25*70d20ed3SAlexander Motin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*70d20ed3SAlexander Motin */ 27*70d20ed3SAlexander Motin 28*70d20ed3SAlexander Motin #include <sys/cdefs.h> 29*70d20ed3SAlexander Motin __FBSDID("$FreeBSD$"); 30*70d20ed3SAlexander Motin 31*70d20ed3SAlexander Motin #include <sys/param.h> 32*70d20ed3SAlexander Motin #include <sys/ioccom.h> 33*70d20ed3SAlexander Motin 34*70d20ed3SAlexander Motin #include <err.h> 35*70d20ed3SAlexander Motin #include <fcntl.h> 36*70d20ed3SAlexander Motin #include <stdbool.h> 37*70d20ed3SAlexander Motin #include <stddef.h> 38*70d20ed3SAlexander Motin #include <stdio.h> 39*70d20ed3SAlexander Motin #include <stdlib.h> 40*70d20ed3SAlexander Motin #include <string.h> 41*70d20ed3SAlexander Motin #include <unistd.h> 42*70d20ed3SAlexander Motin 43*70d20ed3SAlexander Motin #include "nvmecontrol.h" 44*70d20ed3SAlexander Motin 45*70d20ed3SAlexander Motin /* Tables for command line parsing */ 46*70d20ed3SAlexander Motin 47*70d20ed3SAlexander Motin static cmd_fn_t resv; 48*70d20ed3SAlexander Motin static cmd_fn_t resvacquire; 49*70d20ed3SAlexander Motin static cmd_fn_t resvregister; 50*70d20ed3SAlexander Motin static cmd_fn_t resvrelease; 51*70d20ed3SAlexander Motin static cmd_fn_t resvreport; 52*70d20ed3SAlexander Motin 53*70d20ed3SAlexander Motin #define NONE 0xffffffffu 54*70d20ed3SAlexander Motin #define NONE64 0xffffffffffffffffull 55*70d20ed3SAlexander Motin #define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc } 56*70d20ed3SAlexander Motin #define OPT_END { NULL, 0, arg_none, NULL, NULL } 57*70d20ed3SAlexander Motin 58*70d20ed3SAlexander Motin static struct cmd resv_cmd = { 59*70d20ed3SAlexander Motin .name = "resv", 60*70d20ed3SAlexander Motin .fn = resv, 61*70d20ed3SAlexander Motin .descr = "Reservation commands", 62*70d20ed3SAlexander Motin .ctx_size = 0, 63*70d20ed3SAlexander Motin .opts = NULL, 64*70d20ed3SAlexander Motin .args = NULL, 65*70d20ed3SAlexander Motin }; 66*70d20ed3SAlexander Motin 67*70d20ed3SAlexander Motin CMD_COMMAND(resv_cmd); 68*70d20ed3SAlexander Motin 69*70d20ed3SAlexander Motin static struct acquire_options { 70*70d20ed3SAlexander Motin uint64_t crkey; 71*70d20ed3SAlexander Motin uint64_t prkey; 72*70d20ed3SAlexander Motin uint8_t rtype; 73*70d20ed3SAlexander Motin uint8_t racqa; 74*70d20ed3SAlexander Motin const char *dev; 75*70d20ed3SAlexander Motin } acquire_opt = { 76*70d20ed3SAlexander Motin .crkey = 0, 77*70d20ed3SAlexander Motin .prkey = 0, 78*70d20ed3SAlexander Motin .rtype = 0, 79*70d20ed3SAlexander Motin .racqa = 0, 80*70d20ed3SAlexander Motin .dev = NULL, 81*70d20ed3SAlexander Motin }; 82*70d20ed3SAlexander Motin 83*70d20ed3SAlexander Motin static const struct opts acquire_opts[] = { 84*70d20ed3SAlexander Motin OPT("crkey", 'c', arg_uint64, acquire_opt, crkey, 85*70d20ed3SAlexander Motin "Current Reservation Key"), 86*70d20ed3SAlexander Motin OPT("prkey", 'p', arg_uint64, acquire_opt, prkey, 87*70d20ed3SAlexander Motin "Preempt Reservation Key"), 88*70d20ed3SAlexander Motin OPT("rtype", 't', arg_uint8, acquire_opt, rtype, 89*70d20ed3SAlexander Motin "Reservation Type"), 90*70d20ed3SAlexander Motin OPT("racqa", 'a', arg_uint8, acquire_opt, racqa, 91*70d20ed3SAlexander Motin "Acquire Action (0=acq, 1=pre, 2=pre+ab)"), 92*70d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 93*70d20ed3SAlexander Motin }; 94*70d20ed3SAlexander Motin 95*70d20ed3SAlexander Motin static const struct args acquire_args[] = { 96*70d20ed3SAlexander Motin { arg_string, &acquire_opt.dev, "namespace-id" }, 97*70d20ed3SAlexander Motin { arg_none, NULL, NULL }, 98*70d20ed3SAlexander Motin }; 99*70d20ed3SAlexander Motin 100*70d20ed3SAlexander Motin static struct cmd acquire_cmd = { 101*70d20ed3SAlexander Motin .name = "acquire", 102*70d20ed3SAlexander Motin .fn = resvacquire, 103*70d20ed3SAlexander Motin .descr = "Acquire/preempt reservation", 104*70d20ed3SAlexander Motin .ctx_size = sizeof(acquire_opt), 105*70d20ed3SAlexander Motin .opts = acquire_opts, 106*70d20ed3SAlexander Motin .args = acquire_args, 107*70d20ed3SAlexander Motin }; 108*70d20ed3SAlexander Motin 109*70d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, acquire_cmd); 110*70d20ed3SAlexander Motin 111*70d20ed3SAlexander Motin static struct register_options { 112*70d20ed3SAlexander Motin uint64_t crkey; 113*70d20ed3SAlexander Motin uint64_t nrkey; 114*70d20ed3SAlexander Motin uint8_t rrega; 115*70d20ed3SAlexander Motin bool iekey; 116*70d20ed3SAlexander Motin uint8_t cptpl; 117*70d20ed3SAlexander Motin const char *dev; 118*70d20ed3SAlexander Motin } register_opt = { 119*70d20ed3SAlexander Motin .crkey = 0, 120*70d20ed3SAlexander Motin .nrkey = 0, 121*70d20ed3SAlexander Motin .rrega = 0, 122*70d20ed3SAlexander Motin .iekey = false, 123*70d20ed3SAlexander Motin .cptpl = 0, 124*70d20ed3SAlexander Motin .dev = NULL, 125*70d20ed3SAlexander Motin }; 126*70d20ed3SAlexander Motin 127*70d20ed3SAlexander Motin static const struct opts register_opts[] = { 128*70d20ed3SAlexander Motin OPT("crkey", 'c', arg_uint64, register_opt, crkey, 129*70d20ed3SAlexander Motin "Current Reservation Key"), 130*70d20ed3SAlexander Motin OPT("nrkey", 'k', arg_uint64, register_opt, nrkey, 131*70d20ed3SAlexander Motin "New Reservation Key"), 132*70d20ed3SAlexander Motin OPT("rrega", 'r', arg_uint8, register_opt, rrega, 133*70d20ed3SAlexander Motin "Register Action (0=reg, 1=unreg, 2=replace)"), 134*70d20ed3SAlexander Motin OPT("iekey", 'i', arg_none, register_opt, iekey, 135*70d20ed3SAlexander Motin "Ignore Existing Key"), 136*70d20ed3SAlexander Motin OPT("cptpl", 'p', arg_uint8, register_opt, cptpl, 137*70d20ed3SAlexander Motin "Change Persist Through Power Loss State"), 138*70d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 139*70d20ed3SAlexander Motin }; 140*70d20ed3SAlexander Motin 141*70d20ed3SAlexander Motin static const struct args register_args[] = { 142*70d20ed3SAlexander Motin { arg_string, ®ister_opt.dev, "namespace-id" }, 143*70d20ed3SAlexander Motin { arg_none, NULL, NULL }, 144*70d20ed3SAlexander Motin }; 145*70d20ed3SAlexander Motin 146*70d20ed3SAlexander Motin static struct cmd register_cmd = { 147*70d20ed3SAlexander Motin .name = "register", 148*70d20ed3SAlexander Motin .fn = resvregister, 149*70d20ed3SAlexander Motin .descr = "Register/unregister reservation", 150*70d20ed3SAlexander Motin .ctx_size = sizeof(register_opt), 151*70d20ed3SAlexander Motin .opts = register_opts, 152*70d20ed3SAlexander Motin .args = register_args, 153*70d20ed3SAlexander Motin }; 154*70d20ed3SAlexander Motin 155*70d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, register_cmd); 156*70d20ed3SAlexander Motin 157*70d20ed3SAlexander Motin static struct release_options { 158*70d20ed3SAlexander Motin uint64_t crkey; 159*70d20ed3SAlexander Motin uint8_t rtype; 160*70d20ed3SAlexander Motin uint8_t rrela; 161*70d20ed3SAlexander Motin const char *dev; 162*70d20ed3SAlexander Motin } release_opt = { 163*70d20ed3SAlexander Motin .crkey = 0, 164*70d20ed3SAlexander Motin .rtype = 0, 165*70d20ed3SAlexander Motin .rrela = 0, 166*70d20ed3SAlexander Motin .dev = NULL, 167*70d20ed3SAlexander Motin }; 168*70d20ed3SAlexander Motin 169*70d20ed3SAlexander Motin static const struct opts release_opts[] = { 170*70d20ed3SAlexander Motin OPT("crkey", 'c', arg_uint64, release_opt, crkey, 171*70d20ed3SAlexander Motin "Current Reservation Key"), 172*70d20ed3SAlexander Motin OPT("rtype", 't', arg_uint8, release_opt, rtype, 173*70d20ed3SAlexander Motin "Reservation Type"), 174*70d20ed3SAlexander Motin OPT("rrela", 'a', arg_uint8, release_opt, rrela, 175*70d20ed3SAlexander Motin "Release Action (0=release, 1=clear)"), 176*70d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 177*70d20ed3SAlexander Motin }; 178*70d20ed3SAlexander Motin 179*70d20ed3SAlexander Motin static const struct args release_args[] = { 180*70d20ed3SAlexander Motin { arg_string, &release_opt.dev, "namespace-id" }, 181*70d20ed3SAlexander Motin { arg_none, NULL, NULL }, 182*70d20ed3SAlexander Motin }; 183*70d20ed3SAlexander Motin 184*70d20ed3SAlexander Motin static struct cmd release_cmd = { 185*70d20ed3SAlexander Motin .name = "release", 186*70d20ed3SAlexander Motin .fn = resvrelease, 187*70d20ed3SAlexander Motin .descr = "Release/clear reservation", 188*70d20ed3SAlexander Motin .ctx_size = sizeof(release_opt), 189*70d20ed3SAlexander Motin .opts = release_opts, 190*70d20ed3SAlexander Motin .args = release_args, 191*70d20ed3SAlexander Motin }; 192*70d20ed3SAlexander Motin 193*70d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, release_cmd); 194*70d20ed3SAlexander Motin 195*70d20ed3SAlexander Motin static struct report_options { 196*70d20ed3SAlexander Motin bool hex; 197*70d20ed3SAlexander Motin bool verbose; 198*70d20ed3SAlexander Motin bool eds; 199*70d20ed3SAlexander Motin const char *dev; 200*70d20ed3SAlexander Motin } report_opt = { 201*70d20ed3SAlexander Motin .hex = false, 202*70d20ed3SAlexander Motin .verbose = false, 203*70d20ed3SAlexander Motin .eds = false, 204*70d20ed3SAlexander Motin .dev = NULL, 205*70d20ed3SAlexander Motin }; 206*70d20ed3SAlexander Motin 207*70d20ed3SAlexander Motin static const struct opts report_opts[] = { 208*70d20ed3SAlexander Motin OPT("hex", 'x', arg_none, report_opt, hex, 209*70d20ed3SAlexander Motin "Print reservation status in hex"), 210*70d20ed3SAlexander Motin OPT("verbose", 'v', arg_none, report_opt, verbose, 211*70d20ed3SAlexander Motin "More verbosity"), 212*70d20ed3SAlexander Motin OPT("eds", 'e', arg_none, report_opt, eds, 213*70d20ed3SAlexander Motin "Extended Data Structure"), 214*70d20ed3SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 215*70d20ed3SAlexander Motin }; 216*70d20ed3SAlexander Motin 217*70d20ed3SAlexander Motin static const struct args report_args[] = { 218*70d20ed3SAlexander Motin { arg_string, &report_opt.dev, "namespace-id" }, 219*70d20ed3SAlexander Motin { arg_none, NULL, NULL }, 220*70d20ed3SAlexander Motin }; 221*70d20ed3SAlexander Motin 222*70d20ed3SAlexander Motin static struct cmd report_cmd = { 223*70d20ed3SAlexander Motin .name = "report", 224*70d20ed3SAlexander Motin .fn = resvreport, 225*70d20ed3SAlexander Motin .descr = "Print reservation status", 226*70d20ed3SAlexander Motin .ctx_size = sizeof(report_opt), 227*70d20ed3SAlexander Motin .opts = report_opts, 228*70d20ed3SAlexander Motin .args = report_args, 229*70d20ed3SAlexander Motin }; 230*70d20ed3SAlexander Motin 231*70d20ed3SAlexander Motin CMD_SUBCOMMAND(resv_cmd, report_cmd); 232*70d20ed3SAlexander Motin 233*70d20ed3SAlexander Motin /* handles NVME_OPC_RESERVATION_* NVM commands */ 234*70d20ed3SAlexander Motin 235*70d20ed3SAlexander Motin static void 236*70d20ed3SAlexander Motin resvacquire(const struct cmd *f, int argc, char *argv[]) 237*70d20ed3SAlexander Motin { 238*70d20ed3SAlexander Motin struct nvme_pt_command pt; 239*70d20ed3SAlexander Motin uint64_t data[2]; 240*70d20ed3SAlexander Motin int fd; 241*70d20ed3SAlexander Motin uint32_t nsid; 242*70d20ed3SAlexander Motin 243*70d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 244*70d20ed3SAlexander Motin return; 245*70d20ed3SAlexander Motin open_dev(acquire_opt.dev, &fd, 1, 1); 246*70d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 247*70d20ed3SAlexander Motin if (nsid == 0) { 248*70d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 249*70d20ed3SAlexander Motin arg_help(argc, argv, f); 250*70d20ed3SAlexander Motin } 251*70d20ed3SAlexander Motin 252*70d20ed3SAlexander Motin data[0] = htole64(acquire_opt.crkey); 253*70d20ed3SAlexander Motin data[1] = htole64(acquire_opt.prkey); 254*70d20ed3SAlexander Motin 255*70d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 256*70d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_ACQUIRE; 257*70d20ed3SAlexander Motin pt.cmd.cdw10 = htole32((acquire_opt.racqa & 7) | 258*70d20ed3SAlexander Motin (acquire_opt.rtype << 8)); 259*70d20ed3SAlexander Motin pt.buf = &data; 260*70d20ed3SAlexander Motin pt.len = sizeof(data); 261*70d20ed3SAlexander Motin pt.is_read = 0; 262*70d20ed3SAlexander Motin 263*70d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 264*70d20ed3SAlexander Motin err(1, "acquire request failed"); 265*70d20ed3SAlexander Motin 266*70d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 267*70d20ed3SAlexander Motin errx(1, "acquire request returned error"); 268*70d20ed3SAlexander Motin 269*70d20ed3SAlexander Motin close(fd); 270*70d20ed3SAlexander Motin exit(0); 271*70d20ed3SAlexander Motin } 272*70d20ed3SAlexander Motin 273*70d20ed3SAlexander Motin static void 274*70d20ed3SAlexander Motin resvregister(const struct cmd *f, int argc, char *argv[]) 275*70d20ed3SAlexander Motin { 276*70d20ed3SAlexander Motin struct nvme_pt_command pt; 277*70d20ed3SAlexander Motin uint64_t data[2]; 278*70d20ed3SAlexander Motin int fd; 279*70d20ed3SAlexander Motin uint32_t nsid; 280*70d20ed3SAlexander Motin 281*70d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 282*70d20ed3SAlexander Motin return; 283*70d20ed3SAlexander Motin open_dev(register_opt.dev, &fd, 1, 1); 284*70d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 285*70d20ed3SAlexander Motin if (nsid == 0) { 286*70d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 287*70d20ed3SAlexander Motin arg_help(argc, argv, f); 288*70d20ed3SAlexander Motin } 289*70d20ed3SAlexander Motin 290*70d20ed3SAlexander Motin data[0] = htole64(register_opt.crkey); 291*70d20ed3SAlexander Motin data[1] = htole64(register_opt.nrkey); 292*70d20ed3SAlexander Motin 293*70d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 294*70d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_REGISTER; 295*70d20ed3SAlexander Motin pt.cmd.cdw10 = htole32((register_opt.rrega & 7) | 296*70d20ed3SAlexander Motin (register_opt.iekey << 3) | (register_opt.cptpl << 30)); 297*70d20ed3SAlexander Motin pt.buf = &data; 298*70d20ed3SAlexander Motin pt.len = sizeof(data); 299*70d20ed3SAlexander Motin pt.is_read = 0; 300*70d20ed3SAlexander Motin 301*70d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 302*70d20ed3SAlexander Motin err(1, "register request failed"); 303*70d20ed3SAlexander Motin 304*70d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 305*70d20ed3SAlexander Motin errx(1, "register request returned error"); 306*70d20ed3SAlexander Motin 307*70d20ed3SAlexander Motin close(fd); 308*70d20ed3SAlexander Motin exit(0); 309*70d20ed3SAlexander Motin } 310*70d20ed3SAlexander Motin 311*70d20ed3SAlexander Motin static void 312*70d20ed3SAlexander Motin resvrelease(const struct cmd *f, int argc, char *argv[]) 313*70d20ed3SAlexander Motin { 314*70d20ed3SAlexander Motin struct nvme_pt_command pt; 315*70d20ed3SAlexander Motin uint64_t data[1]; 316*70d20ed3SAlexander Motin int fd; 317*70d20ed3SAlexander Motin uint32_t nsid; 318*70d20ed3SAlexander Motin 319*70d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 320*70d20ed3SAlexander Motin return; 321*70d20ed3SAlexander Motin open_dev(release_opt.dev, &fd, 1, 1); 322*70d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 323*70d20ed3SAlexander Motin if (nsid == 0) { 324*70d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 325*70d20ed3SAlexander Motin arg_help(argc, argv, f); 326*70d20ed3SAlexander Motin } 327*70d20ed3SAlexander Motin 328*70d20ed3SAlexander Motin data[0] = htole64(release_opt.crkey); 329*70d20ed3SAlexander Motin 330*70d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 331*70d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_RELEASE; 332*70d20ed3SAlexander Motin pt.cmd.cdw10 = htole32((release_opt.rrela & 7) | 333*70d20ed3SAlexander Motin (release_opt.rtype << 8)); 334*70d20ed3SAlexander Motin pt.buf = &data; 335*70d20ed3SAlexander Motin pt.len = sizeof(data); 336*70d20ed3SAlexander Motin pt.is_read = 0; 337*70d20ed3SAlexander Motin 338*70d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 339*70d20ed3SAlexander Motin err(1, "release request failed"); 340*70d20ed3SAlexander Motin 341*70d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 342*70d20ed3SAlexander Motin errx(1, "release request returned error"); 343*70d20ed3SAlexander Motin 344*70d20ed3SAlexander Motin close(fd); 345*70d20ed3SAlexander Motin exit(0); 346*70d20ed3SAlexander Motin } 347*70d20ed3SAlexander Motin 348*70d20ed3SAlexander Motin static void 349*70d20ed3SAlexander Motin resvreport(const struct cmd *f, int argc, char *argv[]) 350*70d20ed3SAlexander Motin { 351*70d20ed3SAlexander Motin struct nvme_pt_command pt; 352*70d20ed3SAlexander Motin struct nvme_resv_status *s; 353*70d20ed3SAlexander Motin struct nvme_resv_status_ext *e; 354*70d20ed3SAlexander Motin uint8_t data[4096]; 355*70d20ed3SAlexander Motin int fd; 356*70d20ed3SAlexander Motin u_int i, n; 357*70d20ed3SAlexander Motin uint32_t nsid; 358*70d20ed3SAlexander Motin 359*70d20ed3SAlexander Motin if (arg_parse(argc, argv, f)) 360*70d20ed3SAlexander Motin return; 361*70d20ed3SAlexander Motin open_dev(report_opt.dev, &fd, 1, 1); 362*70d20ed3SAlexander Motin get_nsid(fd, NULL, &nsid); 363*70d20ed3SAlexander Motin if (nsid == 0) { 364*70d20ed3SAlexander Motin fprintf(stderr, "This command require namespace-id\n"); 365*70d20ed3SAlexander Motin arg_help(argc, argv, f); 366*70d20ed3SAlexander Motin } 367*70d20ed3SAlexander Motin 368*70d20ed3SAlexander Motin bzero(data, sizeof(data)); 369*70d20ed3SAlexander Motin memset(&pt, 0, sizeof(pt)); 370*70d20ed3SAlexander Motin pt.cmd.opc = NVME_OPC_RESERVATION_REPORT; 371*70d20ed3SAlexander Motin pt.cmd.cdw10 = htole32(sizeof(data) / 4 - 1); 372*70d20ed3SAlexander Motin pt.cmd.cdw11 = htole32(report_opt.eds); /* EDS */ 373*70d20ed3SAlexander Motin pt.buf = &data; 374*70d20ed3SAlexander Motin pt.len = sizeof(data); 375*70d20ed3SAlexander Motin pt.is_read = 1; 376*70d20ed3SAlexander Motin 377*70d20ed3SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 378*70d20ed3SAlexander Motin err(1, "report request failed"); 379*70d20ed3SAlexander Motin 380*70d20ed3SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 381*70d20ed3SAlexander Motin errx(1, "report request returned error"); 382*70d20ed3SAlexander Motin 383*70d20ed3SAlexander Motin close(fd); 384*70d20ed3SAlexander Motin 385*70d20ed3SAlexander Motin if (report_opt.eds) 386*70d20ed3SAlexander Motin nvme_resv_status_ext_swapbytes((void *)data, sizeof(data)); 387*70d20ed3SAlexander Motin else 388*70d20ed3SAlexander Motin nvme_resv_status_swapbytes((void *)data, sizeof(data)); 389*70d20ed3SAlexander Motin 390*70d20ed3SAlexander Motin if (report_opt.hex) { 391*70d20ed3SAlexander Motin i = sizeof(data); 392*70d20ed3SAlexander Motin if (!report_opt.verbose) { 393*70d20ed3SAlexander Motin for (; i > 64; i--) { 394*70d20ed3SAlexander Motin if (data[i - 1] != 0) 395*70d20ed3SAlexander Motin break; 396*70d20ed3SAlexander Motin } 397*70d20ed3SAlexander Motin } 398*70d20ed3SAlexander Motin print_hex(&data, i); 399*70d20ed3SAlexander Motin exit(0); 400*70d20ed3SAlexander Motin } 401*70d20ed3SAlexander Motin 402*70d20ed3SAlexander Motin s = (struct nvme_resv_status *)data; 403*70d20ed3SAlexander Motin n = (s->regctl[1] << 8) | s->regctl[0]; 404*70d20ed3SAlexander Motin printf("Generation: %u\n", s->gen); 405*70d20ed3SAlexander Motin printf("Reservation Type: %u\n", s->rtype); 406*70d20ed3SAlexander Motin printf("Number of Registered Controllers: %u\n", n); 407*70d20ed3SAlexander Motin printf("Persist Through Power Loss State: %u\n", s->ptpls); 408*70d20ed3SAlexander Motin if (report_opt.eds) { 409*70d20ed3SAlexander Motin e = (struct nvme_resv_status_ext *)data; 410*70d20ed3SAlexander Motin n = MIN(n, (sizeof(data) - sizeof(e)) / sizeof(e->ctrlr[0])); 411*70d20ed3SAlexander Motin for (i = 0; i < n; i++) { 412*70d20ed3SAlexander Motin printf("Controller ID: 0x%04x\n", 413*70d20ed3SAlexander Motin e->ctrlr[i].ctrlr_id); 414*70d20ed3SAlexander Motin printf(" Reservation Status: %u\n", 415*70d20ed3SAlexander Motin e->ctrlr[i].rcsts); 416*70d20ed3SAlexander Motin printf(" Reservation Key: 0x%08jx\n", 417*70d20ed3SAlexander Motin e->ctrlr[i].rkey); 418*70d20ed3SAlexander Motin printf(" Host Identifier: 0x%08jx%08jx\n", 419*70d20ed3SAlexander Motin e->ctrlr[i].hostid[0], e->ctrlr[i].hostid[1]); 420*70d20ed3SAlexander Motin } 421*70d20ed3SAlexander Motin } else { 422*70d20ed3SAlexander Motin n = MIN(n, (sizeof(data) - sizeof(s)) / sizeof(s->ctrlr[0])); 423*70d20ed3SAlexander Motin for (i = 0; i < n; i++) { 424*70d20ed3SAlexander Motin printf("Controller ID: 0x%04x\n", 425*70d20ed3SAlexander Motin s->ctrlr[i].ctrlr_id); 426*70d20ed3SAlexander Motin printf(" Reservation Status: %u\n", 427*70d20ed3SAlexander Motin s->ctrlr[i].rcsts); 428*70d20ed3SAlexander Motin printf(" Host Identifier: 0x%08jx\n", 429*70d20ed3SAlexander Motin s->ctrlr[i].hostid); 430*70d20ed3SAlexander Motin printf(" Reservation Key: 0x%08jx\n", 431*70d20ed3SAlexander Motin s->ctrlr[i].rkey); 432*70d20ed3SAlexander Motin } 433*70d20ed3SAlexander Motin } 434*70d20ed3SAlexander Motin exit(0); 435*70d20ed3SAlexander Motin } 436*70d20ed3SAlexander Motin 437*70d20ed3SAlexander Motin static void 438*70d20ed3SAlexander Motin resv(const struct cmd *nf __unused, int argc, char *argv[]) 439*70d20ed3SAlexander Motin { 440*70d20ed3SAlexander Motin 441*70d20ed3SAlexander Motin cmd_dispatch(argc, argv, &resv_cmd); 442*70d20ed3SAlexander Motin } 443