1*ba405bc8SAlexander Motin /*- 2*ba405bc8SAlexander Motin * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*ba405bc8SAlexander Motin * 4*ba405bc8SAlexander Motin * Copyright (c) 2017 Netflix, Inc 5*ba405bc8SAlexander Motin * Copyright (C) 2018 Alexander Motin <mav@FreeBSD.org> 6*ba405bc8SAlexander Motin * 7*ba405bc8SAlexander Motin * Redistribution and use in source and binary forms, with or without 8*ba405bc8SAlexander Motin * modification, are permitted provided that the following conditions 9*ba405bc8SAlexander Motin * are met: 10*ba405bc8SAlexander Motin * 1. Redistributions of source code must retain the above copyright 11*ba405bc8SAlexander Motin * notice, this list of conditions and the following disclaimer, 12*ba405bc8SAlexander Motin * without modification, immediately at the beginning of the file. 13*ba405bc8SAlexander Motin * 2. Redistributions in binary form must reproduce the above copyright 14*ba405bc8SAlexander Motin * notice, this list of conditions and the following disclaimer in the 15*ba405bc8SAlexander Motin * documentation and/or other materials provided with the distribution. 16*ba405bc8SAlexander Motin * 17*ba405bc8SAlexander Motin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18*ba405bc8SAlexander Motin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19*ba405bc8SAlexander Motin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20*ba405bc8SAlexander Motin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21*ba405bc8SAlexander Motin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22*ba405bc8SAlexander Motin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23*ba405bc8SAlexander Motin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24*ba405bc8SAlexander Motin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25*ba405bc8SAlexander Motin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26*ba405bc8SAlexander Motin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27*ba405bc8SAlexander Motin */ 28*ba405bc8SAlexander Motin 29*ba405bc8SAlexander Motin #include <sys/cdefs.h> 30*ba405bc8SAlexander Motin __FBSDID("$FreeBSD$"); 31*ba405bc8SAlexander Motin 32*ba405bc8SAlexander Motin #include <sys/param.h> 33*ba405bc8SAlexander Motin #include <sys/ioccom.h> 34*ba405bc8SAlexander Motin 35*ba405bc8SAlexander Motin #include <err.h> 36*ba405bc8SAlexander Motin #include <fcntl.h> 37*ba405bc8SAlexander Motin #include <stdio.h> 38*ba405bc8SAlexander Motin #include <stdlib.h> 39*ba405bc8SAlexander Motin #include <string.h> 40*ba405bc8SAlexander Motin #include <unistd.h> 41*ba405bc8SAlexander Motin 42*ba405bc8SAlexander Motin #include "nvmecontrol.h" 43*ba405bc8SAlexander Motin 44*ba405bc8SAlexander Motin /* handles NVME_OPC_NAMESPACE_MANAGEMENT and ATTACHMENT admin cmds */ 45*ba405bc8SAlexander Motin 46*ba405bc8SAlexander Motin #define NSCREATE_USAGE \ 47*ba405bc8SAlexander Motin " nvmecontrol ns create -s size [-c cap] [-f fmt] [-m mset] [-n nmic] [-p pi] [-l pil] nvmeN\n" 48*ba405bc8SAlexander Motin 49*ba405bc8SAlexander Motin #define NSDELETE_USAGE \ 50*ba405bc8SAlexander Motin " nvmecontrol ns delete -n nsid nvmeN\n" 51*ba405bc8SAlexander Motin 52*ba405bc8SAlexander Motin #define NSATTACH_USAGE \ 53*ba405bc8SAlexander Motin " nvmecontrol ns attach -n nsid [-c ctrlrid] nvmeN \n" 54*ba405bc8SAlexander Motin 55*ba405bc8SAlexander Motin #define NSDETACH_USAGE \ 56*ba405bc8SAlexander Motin " nvmecontrol ns detach -n nsid [-c ctrlrid] nvmeN\n" 57*ba405bc8SAlexander Motin 58*ba405bc8SAlexander Motin void nscreate(int argc, char *argv[]); 59*ba405bc8SAlexander Motin void nsdelete(int argc, char *argv[]); 60*ba405bc8SAlexander Motin void nsattach(int argc, char *argv[]); 61*ba405bc8SAlexander Motin void nsdetach(int argc, char *argv[]); 62*ba405bc8SAlexander Motin 63*ba405bc8SAlexander Motin static struct nvme_function ns_funcs[] = { 64*ba405bc8SAlexander Motin {"create", nscreate, NSCREATE_USAGE}, 65*ba405bc8SAlexander Motin {"delete", nsdelete, NSDELETE_USAGE}, 66*ba405bc8SAlexander Motin {"attach", nsattach, NSATTACH_USAGE}, 67*ba405bc8SAlexander Motin {"detach", nsdetach, NSDETACH_USAGE}, 68*ba405bc8SAlexander Motin {NULL, NULL, NULL}, 69*ba405bc8SAlexander Motin }; 70*ba405bc8SAlexander Motin 71*ba405bc8SAlexander Motin static void 72*ba405bc8SAlexander Motin nscreate_usage(void) 73*ba405bc8SAlexander Motin { 74*ba405bc8SAlexander Motin fprintf(stderr, "usage:\n"); 75*ba405bc8SAlexander Motin fprintf(stderr, NSCREATE_USAGE); 76*ba405bc8SAlexander Motin exit(1); 77*ba405bc8SAlexander Motin } 78*ba405bc8SAlexander Motin 79*ba405bc8SAlexander Motin static void 80*ba405bc8SAlexander Motin nsdelete_usage(void) 81*ba405bc8SAlexander Motin { 82*ba405bc8SAlexander Motin fprintf(stderr, "usage:\n"); 83*ba405bc8SAlexander Motin fprintf(stderr, NSDELETE_USAGE); 84*ba405bc8SAlexander Motin exit(1); 85*ba405bc8SAlexander Motin } 86*ba405bc8SAlexander Motin 87*ba405bc8SAlexander Motin static void 88*ba405bc8SAlexander Motin nsattach_usage(void) 89*ba405bc8SAlexander Motin { 90*ba405bc8SAlexander Motin fprintf(stderr, "usage:\n"); 91*ba405bc8SAlexander Motin fprintf(stderr, NSATTACH_USAGE); 92*ba405bc8SAlexander Motin exit(1); 93*ba405bc8SAlexander Motin } 94*ba405bc8SAlexander Motin 95*ba405bc8SAlexander Motin static void 96*ba405bc8SAlexander Motin nsdetach_usage(void) 97*ba405bc8SAlexander Motin { 98*ba405bc8SAlexander Motin fprintf(stderr, "usage:\n"); 99*ba405bc8SAlexander Motin fprintf(stderr, NSDETACH_USAGE); 100*ba405bc8SAlexander Motin exit(1); 101*ba405bc8SAlexander Motin } 102*ba405bc8SAlexander Motin 103*ba405bc8SAlexander Motin struct ns_result_str { 104*ba405bc8SAlexander Motin uint16_t res; 105*ba405bc8SAlexander Motin const char * str; 106*ba405bc8SAlexander Motin }; 107*ba405bc8SAlexander Motin 108*ba405bc8SAlexander Motin static struct ns_result_str ns_result[] = { 109*ba405bc8SAlexander Motin { 0x2, "Invalid Field"}, 110*ba405bc8SAlexander Motin { 0xa, "Invalid Format"}, 111*ba405bc8SAlexander Motin { 0xb, "Invalid Namespace or format"}, 112*ba405bc8SAlexander Motin { 0x15, "Namespace insufficent capacity"}, 113*ba405bc8SAlexander Motin { 0x16, "Namespace ID unavaliable"}, 114*ba405bc8SAlexander Motin { 0x18, "Namespace already attached"}, 115*ba405bc8SAlexander Motin { 0x19, "Namespace is private"}, 116*ba405bc8SAlexander Motin { 0x1a, "Namespace is not attached"}, 117*ba405bc8SAlexander Motin { 0x1b, "Thin provisioning not supported"}, 118*ba405bc8SAlexander Motin { 0x1c, "Controller list invalid"}, 119*ba405bc8SAlexander Motin { 0xFFFF, "Unknown"} 120*ba405bc8SAlexander Motin }; 121*ba405bc8SAlexander Motin 122*ba405bc8SAlexander Motin static const char * 123*ba405bc8SAlexander Motin get_res_str(uint16_t res) 124*ba405bc8SAlexander Motin { 125*ba405bc8SAlexander Motin struct ns_result_str *t = ns_result; 126*ba405bc8SAlexander Motin 127*ba405bc8SAlexander Motin while (t->res != 0xFFFF) { 128*ba405bc8SAlexander Motin if (t->res == res) 129*ba405bc8SAlexander Motin return (t->str); 130*ba405bc8SAlexander Motin t++; 131*ba405bc8SAlexander Motin } 132*ba405bc8SAlexander Motin return t->str; 133*ba405bc8SAlexander Motin } 134*ba405bc8SAlexander Motin 135*ba405bc8SAlexander Motin /* 136*ba405bc8SAlexander Motin * NS MGMT Command specific status values: 137*ba405bc8SAlexander Motin * 0xa = Invalid Format 138*ba405bc8SAlexander Motin * 0x15 = Namespace Insuffience capacity 139*ba405bc8SAlexander Motin * 0x16 = Namespace ID unavailable (number namespaces exceeded) 140*ba405bc8SAlexander Motin * 0xb = Thin Provisioning Not supported 141*ba405bc8SAlexander Motin */ 142*ba405bc8SAlexander Motin void 143*ba405bc8SAlexander Motin nscreate(int argc, char *argv[]) 144*ba405bc8SAlexander Motin { 145*ba405bc8SAlexander Motin struct nvme_pt_command pt; 146*ba405bc8SAlexander Motin struct nvme_controller_data cd; 147*ba405bc8SAlexander Motin struct nvme_namespace_data nsdata; 148*ba405bc8SAlexander Motin int64_t nsze = -1, cap = -1; 149*ba405bc8SAlexander Motin int ch, fd, result, lbaf = 0, mset = 0, nmic = -1, pi = 0, pil = 0; 150*ba405bc8SAlexander Motin 151*ba405bc8SAlexander Motin if (optind >= argc) 152*ba405bc8SAlexander Motin nscreate_usage(); 153*ba405bc8SAlexander Motin 154*ba405bc8SAlexander Motin while ((ch = getopt(argc, argv, "s:c:f:m:n:p:l:")) != -1) { 155*ba405bc8SAlexander Motin switch (ch) { 156*ba405bc8SAlexander Motin case 's': 157*ba405bc8SAlexander Motin nsze = strtol(optarg, (char **)NULL, 0); 158*ba405bc8SAlexander Motin break; 159*ba405bc8SAlexander Motin case 'c': 160*ba405bc8SAlexander Motin cap = strtol(optarg, (char **)NULL, 0); 161*ba405bc8SAlexander Motin break; 162*ba405bc8SAlexander Motin case 'f': 163*ba405bc8SAlexander Motin lbaf = strtol(optarg, (char **)NULL, 0); 164*ba405bc8SAlexander Motin break; 165*ba405bc8SAlexander Motin case 'm': 166*ba405bc8SAlexander Motin mset = strtol(optarg, NULL, 0); 167*ba405bc8SAlexander Motin break; 168*ba405bc8SAlexander Motin case 'n': 169*ba405bc8SAlexander Motin nmic = strtol(optarg, NULL, 0); 170*ba405bc8SAlexander Motin break; 171*ba405bc8SAlexander Motin case 'p': 172*ba405bc8SAlexander Motin pi = strtol(optarg, NULL, 0); 173*ba405bc8SAlexander Motin break; 174*ba405bc8SAlexander Motin case 'l': 175*ba405bc8SAlexander Motin pil = strtol(optarg, NULL, 0); 176*ba405bc8SAlexander Motin break; 177*ba405bc8SAlexander Motin default: 178*ba405bc8SAlexander Motin nscreate_usage(); 179*ba405bc8SAlexander Motin } 180*ba405bc8SAlexander Motin } 181*ba405bc8SAlexander Motin 182*ba405bc8SAlexander Motin if (optind >= argc) 183*ba405bc8SAlexander Motin nscreate_usage(); 184*ba405bc8SAlexander Motin 185*ba405bc8SAlexander Motin if (cap == -1) 186*ba405bc8SAlexander Motin cap = nsze; 187*ba405bc8SAlexander Motin if (nsze == -1 || cap == -1) 188*ba405bc8SAlexander Motin nscreate_usage(); 189*ba405bc8SAlexander Motin 190*ba405bc8SAlexander Motin open_dev(argv[optind], &fd, 1, 1); 191*ba405bc8SAlexander Motin read_controller_data(fd, &cd); 192*ba405bc8SAlexander Motin 193*ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 194*ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 195*ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 196*ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 197*ba405bc8SAlexander Motin 198*ba405bc8SAlexander Motin /* Allow namespaces sharing if Multi-Path I/O is supported. */ 199*ba405bc8SAlexander Motin if (nmic == -1) { 200*ba405bc8SAlexander Motin nmic = cd.mic ? (NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK << 201*ba405bc8SAlexander Motin NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) : 0; 202*ba405bc8SAlexander Motin } 203*ba405bc8SAlexander Motin 204*ba405bc8SAlexander Motin memset(&nsdata, 0, sizeof(nsdata)); 205*ba405bc8SAlexander Motin nsdata.nsze = (uint64_t)nsze; 206*ba405bc8SAlexander Motin nsdata.ncap = (uint64_t)cap; 207*ba405bc8SAlexander Motin nsdata.flbas = ((lbaf & NVME_NS_DATA_FLBAS_FORMAT_MASK) 208*ba405bc8SAlexander Motin << NVME_NS_DATA_FLBAS_FORMAT_SHIFT) | 209*ba405bc8SAlexander Motin ((mset & NVME_NS_DATA_FLBAS_EXTENDED_MASK) 210*ba405bc8SAlexander Motin << NVME_NS_DATA_FLBAS_EXTENDED_SHIFT); 211*ba405bc8SAlexander Motin nsdata.dps = ((pi & NVME_NS_DATA_DPS_MD_START_MASK) 212*ba405bc8SAlexander Motin << NVME_NS_DATA_DPS_MD_START_SHIFT) | 213*ba405bc8SAlexander Motin ((pil & NVME_NS_DATA_DPS_PIT_MASK) 214*ba405bc8SAlexander Motin << NVME_NS_DATA_DPS_PIT_SHIFT); 215*ba405bc8SAlexander Motin nsdata.nmic = nmic; 216*ba405bc8SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 217*ba405bc8SAlexander Motin 218*ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 219*ba405bc8SAlexander Motin pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_NAMESPACE_MANAGEMENT); 220*ba405bc8SAlexander Motin 221*ba405bc8SAlexander Motin pt.cmd.cdw10 = 0; /* create */ 222*ba405bc8SAlexander Motin pt.buf = &nsdata; 223*ba405bc8SAlexander Motin pt.len = sizeof(struct nvme_namespace_data); 224*ba405bc8SAlexander Motin pt.is_read = 0; /* passthrough writes data to ctrlr */ 225*ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 226*ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 227*ba405bc8SAlexander Motin 228*ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 229*ba405bc8SAlexander Motin errx(1, "namespace creation failed: %s", 230*ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 231*ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 232*ba405bc8SAlexander Motin } 233*ba405bc8SAlexander Motin printf("namespace %d created\n", pt.cpl.cdw0); 234*ba405bc8SAlexander Motin exit(0); 235*ba405bc8SAlexander Motin } 236*ba405bc8SAlexander Motin 237*ba405bc8SAlexander Motin void 238*ba405bc8SAlexander Motin nsdelete(int argc, char *argv[]) 239*ba405bc8SAlexander Motin { 240*ba405bc8SAlexander Motin struct nvme_pt_command pt; 241*ba405bc8SAlexander Motin struct nvme_controller_data cd; 242*ba405bc8SAlexander Motin int ch, fd, result, nsid = -2; 243*ba405bc8SAlexander Motin char buf[2]; 244*ba405bc8SAlexander Motin 245*ba405bc8SAlexander Motin if (optind >= argc) 246*ba405bc8SAlexander Motin nsdelete_usage(); 247*ba405bc8SAlexander Motin 248*ba405bc8SAlexander Motin while ((ch = getopt(argc, argv, "n:")) != -1) { 249*ba405bc8SAlexander Motin switch ((char)ch) { 250*ba405bc8SAlexander Motin case 'n': 251*ba405bc8SAlexander Motin nsid = strtol(optarg, (char **)NULL, 0); 252*ba405bc8SAlexander Motin break; 253*ba405bc8SAlexander Motin default: 254*ba405bc8SAlexander Motin nsdelete_usage(); 255*ba405bc8SAlexander Motin } 256*ba405bc8SAlexander Motin } 257*ba405bc8SAlexander Motin 258*ba405bc8SAlexander Motin if (optind >= argc || nsid == -2) 259*ba405bc8SAlexander Motin nsdelete_usage(); 260*ba405bc8SAlexander Motin 261*ba405bc8SAlexander Motin open_dev(argv[optind], &fd, 1, 1); 262*ba405bc8SAlexander Motin read_controller_data(fd, &cd); 263*ba405bc8SAlexander Motin 264*ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 265*ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 266*ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 267*ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 268*ba405bc8SAlexander Motin 269*ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 270*ba405bc8SAlexander Motin pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_NAMESPACE_MANAGEMENT); 271*ba405bc8SAlexander Motin pt.cmd.cdw10 = 1; /* delete */ 272*ba405bc8SAlexander Motin pt.buf = buf; 273*ba405bc8SAlexander Motin pt.len = sizeof(buf); 274*ba405bc8SAlexander Motin pt.is_read = 1; 275*ba405bc8SAlexander Motin pt.cmd.nsid = (uint32_t)nsid; 276*ba405bc8SAlexander Motin 277*ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 278*ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 279*ba405bc8SAlexander Motin 280*ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 281*ba405bc8SAlexander Motin errx(1, "namespace deletion failed: %s", 282*ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 283*ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 284*ba405bc8SAlexander Motin } 285*ba405bc8SAlexander Motin printf("namespace %d deleted\n", nsid); 286*ba405bc8SAlexander Motin exit(0); 287*ba405bc8SAlexander Motin } 288*ba405bc8SAlexander Motin 289*ba405bc8SAlexander Motin /* 290*ba405bc8SAlexander Motin * Attach and Detach use Dword 10, and a controller list (section 4.9) 291*ba405bc8SAlexander Motin * This struct is 4096 bytes in size. 292*ba405bc8SAlexander Motin * 0h = attach 293*ba405bc8SAlexander Motin * 1h = detach 294*ba405bc8SAlexander Motin * 295*ba405bc8SAlexander Motin * Result values for both attach/detach: 296*ba405bc8SAlexander Motin * 297*ba405bc8SAlexander Motin * Completion 18h = Already attached 298*ba405bc8SAlexander Motin * 19h = NS is private and already attached to a controller 299*ba405bc8SAlexander Motin * 1Ah = Not attached, request could not be completed 300*ba405bc8SAlexander Motin * 1Ch = Controller list invalid. 301*ba405bc8SAlexander Motin * 302*ba405bc8SAlexander Motin * 0x2 Invalid Field can occur if ctrlrid d.n.e in system. 303*ba405bc8SAlexander Motin */ 304*ba405bc8SAlexander Motin void 305*ba405bc8SAlexander Motin nsattach(int argc, char *argv[]) 306*ba405bc8SAlexander Motin { 307*ba405bc8SAlexander Motin struct nvme_pt_command pt; 308*ba405bc8SAlexander Motin struct nvme_controller_data cd; 309*ba405bc8SAlexander Motin int ctrlrid = -2; 310*ba405bc8SAlexander Motin int fd, ch, result, nsid = -1; 311*ba405bc8SAlexander Motin uint16_t clist[2048]; 312*ba405bc8SAlexander Motin 313*ba405bc8SAlexander Motin if (optind >= argc) 314*ba405bc8SAlexander Motin nsattach_usage(); 315*ba405bc8SAlexander Motin 316*ba405bc8SAlexander Motin while ((ch = getopt(argc, argv, "n:c:")) != -1) { 317*ba405bc8SAlexander Motin switch (ch) { 318*ba405bc8SAlexander Motin case 'n': 319*ba405bc8SAlexander Motin nsid = strtol(optarg, (char **)NULL, 0); 320*ba405bc8SAlexander Motin break; 321*ba405bc8SAlexander Motin case 'c': 322*ba405bc8SAlexander Motin ctrlrid = strtol(optarg, (char **)NULL, 0); 323*ba405bc8SAlexander Motin break; 324*ba405bc8SAlexander Motin default: 325*ba405bc8SAlexander Motin nsattach_usage(); 326*ba405bc8SAlexander Motin } 327*ba405bc8SAlexander Motin } 328*ba405bc8SAlexander Motin 329*ba405bc8SAlexander Motin if (optind >= argc) 330*ba405bc8SAlexander Motin nsattach_usage(); 331*ba405bc8SAlexander Motin 332*ba405bc8SAlexander Motin if (nsid == -1 ) 333*ba405bc8SAlexander Motin nsattach_usage(); 334*ba405bc8SAlexander Motin 335*ba405bc8SAlexander Motin open_dev(argv[optind], &fd, 1, 1); 336*ba405bc8SAlexander Motin read_controller_data(fd, &cd); 337*ba405bc8SAlexander Motin 338*ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 339*ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 340*ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 341*ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 342*ba405bc8SAlexander Motin 343*ba405bc8SAlexander Motin if (ctrlrid == -1) { 344*ba405bc8SAlexander Motin /* Get full list of controllers to attach to. */ 345*ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 346*ba405bc8SAlexander Motin pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY); 347*ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x13); 348*ba405bc8SAlexander Motin pt.buf = clist; 349*ba405bc8SAlexander Motin pt.len = sizeof(clist); 350*ba405bc8SAlexander Motin pt.is_read = 1; 351*ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 352*ba405bc8SAlexander Motin err(1, "identify request failed"); 353*ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 354*ba405bc8SAlexander Motin errx(1, "identify request returned error"); 355*ba405bc8SAlexander Motin } else { 356*ba405bc8SAlexander Motin /* By default attach to this controller. */ 357*ba405bc8SAlexander Motin if (ctrlrid == -2) 358*ba405bc8SAlexander Motin ctrlrid = cd.ctrlr_id; 359*ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 360*ba405bc8SAlexander Motin clist[0] = htole16(1); 361*ba405bc8SAlexander Motin clist[1] = htole16(ctrlrid); 362*ba405bc8SAlexander Motin } 363*ba405bc8SAlexander Motin 364*ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 365*ba405bc8SAlexander Motin pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_NAMESPACE_ATTACHMENT); 366*ba405bc8SAlexander Motin pt.cmd.cdw10 = 0; /* attach */ 367*ba405bc8SAlexander Motin pt.cmd.nsid = (uint32_t)nsid; 368*ba405bc8SAlexander Motin pt.buf = &clist; 369*ba405bc8SAlexander Motin pt.len = sizeof(clist); 370*ba405bc8SAlexander Motin 371*ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 372*ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 373*ba405bc8SAlexander Motin 374*ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 375*ba405bc8SAlexander Motin errx(1, "namespace attach failed: %s", 376*ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 377*ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 378*ba405bc8SAlexander Motin } 379*ba405bc8SAlexander Motin printf("namespace %d attached\n", nsid); 380*ba405bc8SAlexander Motin exit(0); 381*ba405bc8SAlexander Motin } 382*ba405bc8SAlexander Motin 383*ba405bc8SAlexander Motin void 384*ba405bc8SAlexander Motin nsdetach(int argc, char *argv[]) 385*ba405bc8SAlexander Motin { 386*ba405bc8SAlexander Motin struct nvme_pt_command pt; 387*ba405bc8SAlexander Motin struct nvme_controller_data cd; 388*ba405bc8SAlexander Motin int ctrlrid = -2; 389*ba405bc8SAlexander Motin int fd, ch, result, nsid = -1; 390*ba405bc8SAlexander Motin uint16_t clist[2048]; 391*ba405bc8SAlexander Motin 392*ba405bc8SAlexander Motin if (optind >= argc) 393*ba405bc8SAlexander Motin nsdetach_usage(); 394*ba405bc8SAlexander Motin 395*ba405bc8SAlexander Motin while ((ch = getopt(argc, argv, "n:c:")) != -1) { 396*ba405bc8SAlexander Motin switch (ch) { 397*ba405bc8SAlexander Motin case 'n': 398*ba405bc8SAlexander Motin nsid = strtol(optarg, (char **)NULL, 0); 399*ba405bc8SAlexander Motin break; 400*ba405bc8SAlexander Motin case 'c': 401*ba405bc8SAlexander Motin ctrlrid = strtol(optarg, (char **)NULL, 0); 402*ba405bc8SAlexander Motin break; 403*ba405bc8SAlexander Motin default: 404*ba405bc8SAlexander Motin nsdetach_usage(); 405*ba405bc8SAlexander Motin } 406*ba405bc8SAlexander Motin } 407*ba405bc8SAlexander Motin 408*ba405bc8SAlexander Motin if (optind >= argc) 409*ba405bc8SAlexander Motin nsdetach_usage(); 410*ba405bc8SAlexander Motin 411*ba405bc8SAlexander Motin if (nsid == -1) 412*ba405bc8SAlexander Motin nsdetach_usage(); 413*ba405bc8SAlexander Motin 414*ba405bc8SAlexander Motin open_dev(argv[optind], &fd, 1, 1); 415*ba405bc8SAlexander Motin read_controller_data(fd, &cd); 416*ba405bc8SAlexander Motin 417*ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 418*ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 419*ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 420*ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 421*ba405bc8SAlexander Motin 422*ba405bc8SAlexander Motin if (ctrlrid == -1) { 423*ba405bc8SAlexander Motin /* Get list of controllers this namespace attached to. */ 424*ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 425*ba405bc8SAlexander Motin pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY); 426*ba405bc8SAlexander Motin pt.cmd.nsid = htole32(nsid); 427*ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 428*ba405bc8SAlexander Motin pt.buf = clist; 429*ba405bc8SAlexander Motin pt.len = sizeof(clist); 430*ba405bc8SAlexander Motin pt.is_read = 1; 431*ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 432*ba405bc8SAlexander Motin err(1, "identify request failed"); 433*ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 434*ba405bc8SAlexander Motin errx(1, "identify request returned error"); 435*ba405bc8SAlexander Motin if (clist[0] == 0) { 436*ba405bc8SAlexander Motin ctrlrid = cd.ctrlr_id; 437*ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 438*ba405bc8SAlexander Motin clist[0] = htole16(1); 439*ba405bc8SAlexander Motin clist[1] = htole16(ctrlrid); 440*ba405bc8SAlexander Motin } 441*ba405bc8SAlexander Motin } else { 442*ba405bc8SAlexander Motin /* By default detach from this controller. */ 443*ba405bc8SAlexander Motin if (ctrlrid == -2) 444*ba405bc8SAlexander Motin ctrlrid = cd.ctrlr_id; 445*ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 446*ba405bc8SAlexander Motin clist[0] = htole16(1); 447*ba405bc8SAlexander Motin clist[1] = htole16(ctrlrid); 448*ba405bc8SAlexander Motin } 449*ba405bc8SAlexander Motin 450*ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 451*ba405bc8SAlexander Motin pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_NAMESPACE_ATTACHMENT); 452*ba405bc8SAlexander Motin pt.cmd.cdw10 = 1; /* detach */ 453*ba405bc8SAlexander Motin pt.cmd.nsid = (uint32_t)nsid; 454*ba405bc8SAlexander Motin pt.buf = &clist; 455*ba405bc8SAlexander Motin pt.len = sizeof(clist); 456*ba405bc8SAlexander Motin 457*ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 458*ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 459*ba405bc8SAlexander Motin 460*ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 461*ba405bc8SAlexander Motin errx(1, "namespace detach failed: %s", 462*ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 463*ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 464*ba405bc8SAlexander Motin } 465*ba405bc8SAlexander Motin printf("namespace %d detached\n", nsid); 466*ba405bc8SAlexander Motin exit(0); 467*ba405bc8SAlexander Motin } 468*ba405bc8SAlexander Motin 469*ba405bc8SAlexander Motin void 470*ba405bc8SAlexander Motin ns(int argc, char *argv[]) 471*ba405bc8SAlexander Motin { 472*ba405bc8SAlexander Motin 473*ba405bc8SAlexander Motin dispatch(argc, argv, ns_funcs); 474*ba405bc8SAlexander Motin } 475