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