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