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 44*a13a291aSWarner Losh SET_DECLARE(ns, struct nvme_function); 45*a13a291aSWarner Losh 46*a13a291aSWarner Losh #define NS_USAGE \ 47*a13a291aSWarner Losh " nvmecontrol ns (create|delete|attach|detach)\n" 48*a13a291aSWarner Losh 49ba405bc8SAlexander Motin /* handles NVME_OPC_NAMESPACE_MANAGEMENT and ATTACHMENT admin cmds */ 50ba405bc8SAlexander Motin 51ba405bc8SAlexander Motin #define NSCREATE_USAGE \ 52ba405bc8SAlexander Motin " nvmecontrol ns create -s size [-c cap] [-f fmt] [-m mset] [-n nmic] [-p pi] [-l pil] nvmeN\n" 53ba405bc8SAlexander Motin 54ba405bc8SAlexander Motin #define NSDELETE_USAGE \ 55ba405bc8SAlexander Motin " nvmecontrol ns delete -n nsid nvmeN\n" 56ba405bc8SAlexander Motin 57ba405bc8SAlexander Motin #define NSATTACH_USAGE \ 58ba405bc8SAlexander Motin " nvmecontrol ns attach -n nsid [-c ctrlrid] nvmeN \n" 59ba405bc8SAlexander Motin 60ba405bc8SAlexander Motin #define NSDETACH_USAGE \ 61ba405bc8SAlexander Motin " nvmecontrol ns detach -n nsid [-c ctrlrid] nvmeN\n" 62ba405bc8SAlexander Motin 63ba405bc8SAlexander Motin void nscreate(int argc, char *argv[]); 64ba405bc8SAlexander Motin void nsdelete(int argc, char *argv[]); 65ba405bc8SAlexander Motin void nsattach(int argc, char *argv[]); 66ba405bc8SAlexander Motin void nsdetach(int argc, char *argv[]); 67ba405bc8SAlexander Motin 68*a13a291aSWarner Losh NVME_COMMAND(ns, create, nscreate, NSCREATE_USAGE); 69*a13a291aSWarner Losh NVME_COMMAND(ns, delete, nsdelete, NSDELETE_USAGE); 70*a13a291aSWarner Losh NVME_COMMAND(ns, attach, nsattach, NSATTACH_USAGE); 71*a13a291aSWarner Losh NVME_COMMAND(ns, detach, nsdetach, NSDETACH_USAGE); 72ba405bc8SAlexander Motin 73ba405bc8SAlexander Motin static void 74ba405bc8SAlexander Motin nscreate_usage(void) 75ba405bc8SAlexander Motin { 76ba405bc8SAlexander Motin fprintf(stderr, "usage:\n"); 77ba405bc8SAlexander Motin fprintf(stderr, NSCREATE_USAGE); 78ba405bc8SAlexander Motin exit(1); 79ba405bc8SAlexander Motin } 80ba405bc8SAlexander Motin 81ba405bc8SAlexander Motin static void 82ba405bc8SAlexander Motin nsdelete_usage(void) 83ba405bc8SAlexander Motin { 84ba405bc8SAlexander Motin fprintf(stderr, "usage:\n"); 85ba405bc8SAlexander Motin fprintf(stderr, NSDELETE_USAGE); 86ba405bc8SAlexander Motin exit(1); 87ba405bc8SAlexander Motin } 88ba405bc8SAlexander Motin 89ba405bc8SAlexander Motin static void 90ba405bc8SAlexander Motin nsattach_usage(void) 91ba405bc8SAlexander Motin { 92ba405bc8SAlexander Motin fprintf(stderr, "usage:\n"); 93ba405bc8SAlexander Motin fprintf(stderr, NSATTACH_USAGE); 94ba405bc8SAlexander Motin exit(1); 95ba405bc8SAlexander Motin } 96ba405bc8SAlexander Motin 97ba405bc8SAlexander Motin static void 98ba405bc8SAlexander Motin nsdetach_usage(void) 99ba405bc8SAlexander Motin { 100ba405bc8SAlexander Motin fprintf(stderr, "usage:\n"); 101ba405bc8SAlexander Motin fprintf(stderr, NSDETACH_USAGE); 102ba405bc8SAlexander Motin exit(1); 103ba405bc8SAlexander Motin } 104ba405bc8SAlexander Motin 105ba405bc8SAlexander Motin struct ns_result_str { 106ba405bc8SAlexander Motin uint16_t res; 107ba405bc8SAlexander Motin const char * str; 108ba405bc8SAlexander Motin }; 109ba405bc8SAlexander Motin 110ba405bc8SAlexander Motin static struct ns_result_str ns_result[] = { 111ba405bc8SAlexander Motin { 0x2, "Invalid Field"}, 112ba405bc8SAlexander Motin { 0xa, "Invalid Format"}, 113ba405bc8SAlexander Motin { 0xb, "Invalid Namespace or format"}, 114ba405bc8SAlexander Motin { 0x15, "Namespace insufficent capacity"}, 115ba405bc8SAlexander Motin { 0x16, "Namespace ID unavaliable"}, 116ba405bc8SAlexander Motin { 0x18, "Namespace already attached"}, 117ba405bc8SAlexander Motin { 0x19, "Namespace is private"}, 118ba405bc8SAlexander Motin { 0x1a, "Namespace is not attached"}, 119ba405bc8SAlexander Motin { 0x1b, "Thin provisioning not supported"}, 120ba405bc8SAlexander Motin { 0x1c, "Controller list invalid"}, 121ba405bc8SAlexander Motin { 0xFFFF, "Unknown"} 122ba405bc8SAlexander Motin }; 123ba405bc8SAlexander Motin 124ba405bc8SAlexander Motin static const char * 125ba405bc8SAlexander Motin get_res_str(uint16_t res) 126ba405bc8SAlexander Motin { 127ba405bc8SAlexander Motin struct ns_result_str *t = ns_result; 128ba405bc8SAlexander Motin 129ba405bc8SAlexander Motin while (t->res != 0xFFFF) { 130ba405bc8SAlexander Motin if (t->res == res) 131ba405bc8SAlexander Motin return (t->str); 132ba405bc8SAlexander Motin t++; 133ba405bc8SAlexander Motin } 134ba405bc8SAlexander Motin return t->str; 135ba405bc8SAlexander Motin } 136ba405bc8SAlexander Motin 137ba405bc8SAlexander Motin /* 138ba405bc8SAlexander Motin * NS MGMT Command specific status values: 139ba405bc8SAlexander Motin * 0xa = Invalid Format 140ba405bc8SAlexander Motin * 0x15 = Namespace Insuffience capacity 141ba405bc8SAlexander Motin * 0x16 = Namespace ID unavailable (number namespaces exceeded) 142ba405bc8SAlexander Motin * 0xb = Thin Provisioning Not supported 143ba405bc8SAlexander Motin */ 144ba405bc8SAlexander Motin void 145ba405bc8SAlexander Motin nscreate(int argc, char *argv[]) 146ba405bc8SAlexander Motin { 147ba405bc8SAlexander Motin struct nvme_pt_command pt; 148ba405bc8SAlexander Motin struct nvme_controller_data cd; 149ba405bc8SAlexander Motin struct nvme_namespace_data nsdata; 150ba405bc8SAlexander Motin int64_t nsze = -1, cap = -1; 151ba405bc8SAlexander Motin int ch, fd, result, lbaf = 0, mset = 0, nmic = -1, pi = 0, pil = 0; 152ba405bc8SAlexander Motin 153ba405bc8SAlexander Motin if (optind >= argc) 154ba405bc8SAlexander Motin nscreate_usage(); 155ba405bc8SAlexander Motin 156ba405bc8SAlexander Motin while ((ch = getopt(argc, argv, "s:c:f:m:n:p:l:")) != -1) { 157ba405bc8SAlexander Motin switch (ch) { 158ba405bc8SAlexander Motin case 's': 159ba405bc8SAlexander Motin nsze = strtol(optarg, (char **)NULL, 0); 160ba405bc8SAlexander Motin break; 161ba405bc8SAlexander Motin case 'c': 162ba405bc8SAlexander Motin cap = strtol(optarg, (char **)NULL, 0); 163ba405bc8SAlexander Motin break; 164ba405bc8SAlexander Motin case 'f': 165ba405bc8SAlexander Motin lbaf = strtol(optarg, (char **)NULL, 0); 166ba405bc8SAlexander Motin break; 167ba405bc8SAlexander Motin case 'm': 168ba405bc8SAlexander Motin mset = strtol(optarg, NULL, 0); 169ba405bc8SAlexander Motin break; 170ba405bc8SAlexander Motin case 'n': 171ba405bc8SAlexander Motin nmic = strtol(optarg, NULL, 0); 172ba405bc8SAlexander Motin break; 173ba405bc8SAlexander Motin case 'p': 174ba405bc8SAlexander Motin pi = strtol(optarg, NULL, 0); 175ba405bc8SAlexander Motin break; 176ba405bc8SAlexander Motin case 'l': 177ba405bc8SAlexander Motin pil = strtol(optarg, NULL, 0); 178ba405bc8SAlexander Motin break; 179ba405bc8SAlexander Motin default: 180ba405bc8SAlexander Motin nscreate_usage(); 181ba405bc8SAlexander Motin } 182ba405bc8SAlexander Motin } 183ba405bc8SAlexander Motin 184ba405bc8SAlexander Motin if (optind >= argc) 185ba405bc8SAlexander Motin nscreate_usage(); 186ba405bc8SAlexander Motin 187ba405bc8SAlexander Motin if (cap == -1) 188ba405bc8SAlexander Motin cap = nsze; 189ba405bc8SAlexander Motin if (nsze == -1 || cap == -1) 190ba405bc8SAlexander Motin nscreate_usage(); 191ba405bc8SAlexander Motin 192ba405bc8SAlexander Motin open_dev(argv[optind], &fd, 1, 1); 193ba405bc8SAlexander Motin read_controller_data(fd, &cd); 194ba405bc8SAlexander Motin 195ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 196ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 197ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 198ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 199ba405bc8SAlexander Motin 200ba405bc8SAlexander Motin /* Allow namespaces sharing if Multi-Path I/O is supported. */ 201ba405bc8SAlexander Motin if (nmic == -1) { 202ba405bc8SAlexander Motin nmic = cd.mic ? (NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK << 203ba405bc8SAlexander Motin NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) : 0; 204ba405bc8SAlexander Motin } 205ba405bc8SAlexander Motin 206ba405bc8SAlexander Motin memset(&nsdata, 0, sizeof(nsdata)); 207ba405bc8SAlexander Motin nsdata.nsze = (uint64_t)nsze; 208ba405bc8SAlexander Motin nsdata.ncap = (uint64_t)cap; 209ba405bc8SAlexander Motin nsdata.flbas = ((lbaf & NVME_NS_DATA_FLBAS_FORMAT_MASK) 210ba405bc8SAlexander Motin << NVME_NS_DATA_FLBAS_FORMAT_SHIFT) | 211ba405bc8SAlexander Motin ((mset & NVME_NS_DATA_FLBAS_EXTENDED_MASK) 212ba405bc8SAlexander Motin << NVME_NS_DATA_FLBAS_EXTENDED_SHIFT); 213ba405bc8SAlexander Motin nsdata.dps = ((pi & NVME_NS_DATA_DPS_MD_START_MASK) 214ba405bc8SAlexander Motin << NVME_NS_DATA_DPS_MD_START_SHIFT) | 215ba405bc8SAlexander Motin ((pil & NVME_NS_DATA_DPS_PIT_MASK) 216ba405bc8SAlexander Motin << NVME_NS_DATA_DPS_PIT_SHIFT); 217ba405bc8SAlexander Motin nsdata.nmic = nmic; 218ba405bc8SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 219ba405bc8SAlexander Motin 220ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 2219544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 222ba405bc8SAlexander Motin 223ba405bc8SAlexander Motin pt.cmd.cdw10 = 0; /* create */ 224ba405bc8SAlexander Motin pt.buf = &nsdata; 225ba405bc8SAlexander Motin pt.len = sizeof(struct nvme_namespace_data); 226ba405bc8SAlexander Motin pt.is_read = 0; /* passthrough writes data to ctrlr */ 227ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 228ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 229ba405bc8SAlexander Motin 230ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 231ba405bc8SAlexander Motin errx(1, "namespace creation failed: %s", 232ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 233ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 234ba405bc8SAlexander Motin } 235ba405bc8SAlexander Motin printf("namespace %d created\n", pt.cpl.cdw0); 236ba405bc8SAlexander Motin exit(0); 237ba405bc8SAlexander Motin } 238ba405bc8SAlexander Motin 239ba405bc8SAlexander Motin void 240ba405bc8SAlexander Motin nsdelete(int argc, char *argv[]) 241ba405bc8SAlexander Motin { 242ba405bc8SAlexander Motin struct nvme_pt_command pt; 243ba405bc8SAlexander Motin struct nvme_controller_data cd; 244ba405bc8SAlexander Motin int ch, fd, result, nsid = -2; 245ba405bc8SAlexander Motin char buf[2]; 246ba405bc8SAlexander Motin 247ba405bc8SAlexander Motin if (optind >= argc) 248ba405bc8SAlexander Motin nsdelete_usage(); 249ba405bc8SAlexander Motin 250ba405bc8SAlexander Motin while ((ch = getopt(argc, argv, "n:")) != -1) { 251ba405bc8SAlexander Motin switch ((char)ch) { 252ba405bc8SAlexander Motin case 'n': 253ba405bc8SAlexander Motin nsid = strtol(optarg, (char **)NULL, 0); 254ba405bc8SAlexander Motin break; 255ba405bc8SAlexander Motin default: 256ba405bc8SAlexander Motin nsdelete_usage(); 257ba405bc8SAlexander Motin } 258ba405bc8SAlexander Motin } 259ba405bc8SAlexander Motin 260ba405bc8SAlexander Motin if (optind >= argc || nsid == -2) 261ba405bc8SAlexander Motin nsdelete_usage(); 262ba405bc8SAlexander Motin 263ba405bc8SAlexander Motin open_dev(argv[optind], &fd, 1, 1); 264ba405bc8SAlexander Motin read_controller_data(fd, &cd); 265ba405bc8SAlexander Motin 266ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 267ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 268ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 269ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 270ba405bc8SAlexander Motin 271ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 2729544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 273ba405bc8SAlexander Motin pt.cmd.cdw10 = 1; /* delete */ 274ba405bc8SAlexander Motin pt.buf = buf; 275ba405bc8SAlexander Motin pt.len = sizeof(buf); 276ba405bc8SAlexander Motin pt.is_read = 1; 277ba405bc8SAlexander Motin pt.cmd.nsid = (uint32_t)nsid; 278ba405bc8SAlexander Motin 279ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 280ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 281ba405bc8SAlexander Motin 282ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 283ba405bc8SAlexander Motin errx(1, "namespace deletion failed: %s", 284ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 285ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 286ba405bc8SAlexander Motin } 287ba405bc8SAlexander Motin printf("namespace %d deleted\n", nsid); 288ba405bc8SAlexander Motin exit(0); 289ba405bc8SAlexander Motin } 290ba405bc8SAlexander Motin 291ba405bc8SAlexander Motin /* 292ba405bc8SAlexander Motin * Attach and Detach use Dword 10, and a controller list (section 4.9) 293ba405bc8SAlexander Motin * This struct is 4096 bytes in size. 294ba405bc8SAlexander Motin * 0h = attach 295ba405bc8SAlexander Motin * 1h = detach 296ba405bc8SAlexander Motin * 297ba405bc8SAlexander Motin * Result values for both attach/detach: 298ba405bc8SAlexander Motin * 299ba405bc8SAlexander Motin * Completion 18h = Already attached 300ba405bc8SAlexander Motin * 19h = NS is private and already attached to a controller 301ba405bc8SAlexander Motin * 1Ah = Not attached, request could not be completed 302ba405bc8SAlexander Motin * 1Ch = Controller list invalid. 303ba405bc8SAlexander Motin * 304ba405bc8SAlexander Motin * 0x2 Invalid Field can occur if ctrlrid d.n.e in system. 305ba405bc8SAlexander Motin */ 306ba405bc8SAlexander Motin void 307ba405bc8SAlexander Motin nsattach(int argc, char *argv[]) 308ba405bc8SAlexander Motin { 309ba405bc8SAlexander Motin struct nvme_pt_command pt; 310ba405bc8SAlexander Motin struct nvme_controller_data cd; 311ba405bc8SAlexander Motin int ctrlrid = -2; 312ba405bc8SAlexander Motin int fd, ch, result, nsid = -1; 313ba405bc8SAlexander Motin uint16_t clist[2048]; 314ba405bc8SAlexander Motin 315ba405bc8SAlexander Motin if (optind >= argc) 316ba405bc8SAlexander Motin nsattach_usage(); 317ba405bc8SAlexander Motin 318ba405bc8SAlexander Motin while ((ch = getopt(argc, argv, "n:c:")) != -1) { 319ba405bc8SAlexander Motin switch (ch) { 320ba405bc8SAlexander Motin case 'n': 321ba405bc8SAlexander Motin nsid = strtol(optarg, (char **)NULL, 0); 322ba405bc8SAlexander Motin break; 323ba405bc8SAlexander Motin case 'c': 324ba405bc8SAlexander Motin ctrlrid = strtol(optarg, (char **)NULL, 0); 325ba405bc8SAlexander Motin break; 326ba405bc8SAlexander Motin default: 327ba405bc8SAlexander Motin nsattach_usage(); 328ba405bc8SAlexander Motin } 329ba405bc8SAlexander Motin } 330ba405bc8SAlexander Motin 331ba405bc8SAlexander Motin if (optind >= argc) 332ba405bc8SAlexander Motin nsattach_usage(); 333ba405bc8SAlexander Motin 334ba405bc8SAlexander Motin if (nsid == -1 ) 335ba405bc8SAlexander Motin nsattach_usage(); 336ba405bc8SAlexander Motin 337ba405bc8SAlexander Motin open_dev(argv[optind], &fd, 1, 1); 338ba405bc8SAlexander Motin read_controller_data(fd, &cd); 339ba405bc8SAlexander Motin 340ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 341ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 342ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 343ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 344ba405bc8SAlexander Motin 345ba405bc8SAlexander Motin if (ctrlrid == -1) { 346ba405bc8SAlexander Motin /* Get full list of controllers to attach to. */ 347ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 3489544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 349ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x13); 350ba405bc8SAlexander Motin pt.buf = clist; 351ba405bc8SAlexander Motin pt.len = sizeof(clist); 352ba405bc8SAlexander Motin pt.is_read = 1; 353ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 354ba405bc8SAlexander Motin err(1, "identify request failed"); 355ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 356ba405bc8SAlexander Motin errx(1, "identify request returned error"); 357ba405bc8SAlexander Motin } else { 358ba405bc8SAlexander Motin /* By default attach to this controller. */ 359ba405bc8SAlexander Motin if (ctrlrid == -2) 360ba405bc8SAlexander Motin ctrlrid = cd.ctrlr_id; 361ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 362ba405bc8SAlexander Motin clist[0] = htole16(1); 363ba405bc8SAlexander Motin clist[1] = htole16(ctrlrid); 364ba405bc8SAlexander Motin } 365ba405bc8SAlexander Motin 366ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 3679544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 368ba405bc8SAlexander Motin pt.cmd.cdw10 = 0; /* attach */ 369ba405bc8SAlexander Motin pt.cmd.nsid = (uint32_t)nsid; 370ba405bc8SAlexander Motin pt.buf = &clist; 371ba405bc8SAlexander Motin pt.len = sizeof(clist); 372ba405bc8SAlexander Motin 373ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 374ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 375ba405bc8SAlexander Motin 376ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 377ba405bc8SAlexander Motin errx(1, "namespace attach failed: %s", 378ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 379ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 380ba405bc8SAlexander Motin } 381ba405bc8SAlexander Motin printf("namespace %d attached\n", nsid); 382ba405bc8SAlexander Motin exit(0); 383ba405bc8SAlexander Motin } 384ba405bc8SAlexander Motin 385ba405bc8SAlexander Motin void 386ba405bc8SAlexander Motin nsdetach(int argc, char *argv[]) 387ba405bc8SAlexander Motin { 388ba405bc8SAlexander Motin struct nvme_pt_command pt; 389ba405bc8SAlexander Motin struct nvme_controller_data cd; 390ba405bc8SAlexander Motin int ctrlrid = -2; 391ba405bc8SAlexander Motin int fd, ch, result, nsid = -1; 392ba405bc8SAlexander Motin uint16_t clist[2048]; 393ba405bc8SAlexander Motin 394ba405bc8SAlexander Motin if (optind >= argc) 395ba405bc8SAlexander Motin nsdetach_usage(); 396ba405bc8SAlexander Motin 397ba405bc8SAlexander Motin while ((ch = getopt(argc, argv, "n:c:")) != -1) { 398ba405bc8SAlexander Motin switch (ch) { 399ba405bc8SAlexander Motin case 'n': 400ba405bc8SAlexander Motin nsid = strtol(optarg, (char **)NULL, 0); 401ba405bc8SAlexander Motin break; 402ba405bc8SAlexander Motin case 'c': 403ba405bc8SAlexander Motin ctrlrid = strtol(optarg, (char **)NULL, 0); 404ba405bc8SAlexander Motin break; 405ba405bc8SAlexander Motin default: 406ba405bc8SAlexander Motin nsdetach_usage(); 407ba405bc8SAlexander Motin } 408ba405bc8SAlexander Motin } 409ba405bc8SAlexander Motin 410ba405bc8SAlexander Motin if (optind >= argc) 411ba405bc8SAlexander Motin nsdetach_usage(); 412ba405bc8SAlexander Motin 413ba405bc8SAlexander Motin if (nsid == -1) 414ba405bc8SAlexander Motin nsdetach_usage(); 415ba405bc8SAlexander Motin 416ba405bc8SAlexander Motin open_dev(argv[optind], &fd, 1, 1); 417ba405bc8SAlexander Motin read_controller_data(fd, &cd); 418ba405bc8SAlexander Motin 419ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 420ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 421ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 422ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 423ba405bc8SAlexander Motin 424ba405bc8SAlexander Motin if (ctrlrid == -1) { 425ba405bc8SAlexander Motin /* Get list of controllers this namespace attached to. */ 426ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 4279544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 428ba405bc8SAlexander Motin pt.cmd.nsid = htole32(nsid); 429ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 430ba405bc8SAlexander Motin pt.buf = clist; 431ba405bc8SAlexander Motin pt.len = sizeof(clist); 432ba405bc8SAlexander Motin pt.is_read = 1; 433ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 434ba405bc8SAlexander Motin err(1, "identify request failed"); 435ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 436ba405bc8SAlexander Motin errx(1, "identify request returned error"); 437ba405bc8SAlexander Motin if (clist[0] == 0) { 438ba405bc8SAlexander Motin ctrlrid = cd.ctrlr_id; 439ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 440ba405bc8SAlexander Motin clist[0] = htole16(1); 441ba405bc8SAlexander Motin clist[1] = htole16(ctrlrid); 442ba405bc8SAlexander Motin } 443ba405bc8SAlexander Motin } else { 444ba405bc8SAlexander Motin /* By default detach from this controller. */ 445ba405bc8SAlexander Motin if (ctrlrid == -2) 446ba405bc8SAlexander Motin ctrlrid = cd.ctrlr_id; 447ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 448ba405bc8SAlexander Motin clist[0] = htole16(1); 449ba405bc8SAlexander Motin clist[1] = htole16(ctrlrid); 450ba405bc8SAlexander Motin } 451ba405bc8SAlexander Motin 452ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 4539544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 454ba405bc8SAlexander Motin pt.cmd.cdw10 = 1; /* detach */ 455ba405bc8SAlexander Motin pt.cmd.nsid = (uint32_t)nsid; 456ba405bc8SAlexander Motin pt.buf = &clist; 457ba405bc8SAlexander Motin pt.len = sizeof(clist); 458ba405bc8SAlexander Motin 459ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 460ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 461ba405bc8SAlexander Motin 462ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 463ba405bc8SAlexander Motin errx(1, "namespace detach failed: %s", 464ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 465ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 466ba405bc8SAlexander Motin } 467ba405bc8SAlexander Motin printf("namespace %d detached\n", nsid); 468ba405bc8SAlexander Motin exit(0); 469ba405bc8SAlexander Motin } 470ba405bc8SAlexander Motin 471*a13a291aSWarner Losh static void 472ba405bc8SAlexander Motin ns(int argc, char *argv[]) 473ba405bc8SAlexander Motin { 474ba405bc8SAlexander Motin 475*a13a291aSWarner Losh DISPATCH(argc, argv, ns); 476ba405bc8SAlexander Motin } 477*a13a291aSWarner Losh 478*a13a291aSWarner Losh NVME_COMMAND(top, ns, ns, NS_USAGE); 479