1ba405bc8SAlexander Motin /*- 2ba405bc8SAlexander Motin * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3ba405bc8SAlexander Motin * 452467047SWarner Losh * Copyright (c) 2017 Netflix, Inc. 5a7bf63beSAlexander Motin * Copyright (C) 2018-2019 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> 373b3dd3f7SAlexander Motin #include <stdbool.h> 383b3dd3f7SAlexander Motin #include <stddef.h> 39ba405bc8SAlexander Motin #include <stdio.h> 40ba405bc8SAlexander Motin #include <stdlib.h> 41ba405bc8SAlexander Motin #include <string.h> 425dc463f9SAlexander Motin #include <sysexits.h> 43ba405bc8SAlexander Motin #include <unistd.h> 44ba405bc8SAlexander Motin 45ba405bc8SAlexander Motin #include "nvmecontrol.h" 46ba405bc8SAlexander Motin 47f634b4c1SWarner Losh /* Tables for command line parsing */ 48f634b4c1SWarner Losh 49f634b4c1SWarner Losh static cmd_fn_t ns; 503b3dd3f7SAlexander Motin static cmd_fn_t nsactive; 513b3dd3f7SAlexander Motin static cmd_fn_t nsallocated; 523b3dd3f7SAlexander Motin static cmd_fn_t nscontrollers; 53f634b4c1SWarner Losh static cmd_fn_t nscreate; 54f634b4c1SWarner Losh static cmd_fn_t nsdelete; 55f634b4c1SWarner Losh static cmd_fn_t nsattach; 56f634b4c1SWarner Losh static cmd_fn_t nsdetach; 573b3dd3f7SAlexander Motin static cmd_fn_t nsattached; 583b3dd3f7SAlexander Motin static cmd_fn_t nsidentify; 59f634b4c1SWarner Losh 60f634b4c1SWarner Losh #define NONE 0xffffffffu 61f634b4c1SWarner Losh #define NONE64 0xffffffffffffffffull 62f634b4c1SWarner Losh #define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc } 63f634b4c1SWarner Losh #define OPT_END { NULL, 0, arg_none, NULL, NULL } 64f634b4c1SWarner Losh 65f634b4c1SWarner Losh static struct cmd ns_cmd = { 663b3dd3f7SAlexander Motin .name = "ns", 673b3dd3f7SAlexander Motin .fn = ns, 683b3dd3f7SAlexander Motin .descr = "Namespace management commands", 693b3dd3f7SAlexander Motin .ctx_size = 0, 703b3dd3f7SAlexander Motin .opts = NULL, 713b3dd3f7SAlexander Motin .args = NULL, 72f634b4c1SWarner Losh }; 73f634b4c1SWarner Losh 74f634b4c1SWarner Losh CMD_COMMAND(ns_cmd); 75f634b4c1SWarner Losh 763b3dd3f7SAlexander Motin static struct active_options { 773b3dd3f7SAlexander Motin const char *dev; 783b3dd3f7SAlexander Motin } active_opt = { 793b3dd3f7SAlexander Motin .dev = NULL, 803b3dd3f7SAlexander Motin }; 813b3dd3f7SAlexander Motin 823b3dd3f7SAlexander Motin static const struct args active_args[] = { 835458a1c8SAlexander Motin { arg_string, &active_opt.dev, "controller-id|namespace-id" }, 843b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 853b3dd3f7SAlexander Motin }; 863b3dd3f7SAlexander Motin 873b3dd3f7SAlexander Motin static struct cmd active_cmd = { 883b3dd3f7SAlexander Motin .name = "active", 893b3dd3f7SAlexander Motin .fn = nsactive, 903b3dd3f7SAlexander Motin .descr = "List active (attached) namespaces", 913b3dd3f7SAlexander Motin .ctx_size = sizeof(active_opt), 923b3dd3f7SAlexander Motin .opts = NULL, 933b3dd3f7SAlexander Motin .args = active_args, 943b3dd3f7SAlexander Motin }; 953b3dd3f7SAlexander Motin 963b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, active_cmd); 973b3dd3f7SAlexander Motin 983b3dd3f7SAlexander Motin static struct cmd allocated_cmd = { 993b3dd3f7SAlexander Motin .name = "allocated", 1003b3dd3f7SAlexander Motin .fn = nsallocated, 1013b3dd3f7SAlexander Motin .descr = "List allocated (created) namespaces", 1023b3dd3f7SAlexander Motin .ctx_size = sizeof(active_opt), 1033b3dd3f7SAlexander Motin .opts = NULL, 1043b3dd3f7SAlexander Motin .args = active_args, 1053b3dd3f7SAlexander Motin }; 1063b3dd3f7SAlexander Motin 1073b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, allocated_cmd); 1083b3dd3f7SAlexander Motin 1093b3dd3f7SAlexander Motin static struct controllers_options { 1103b3dd3f7SAlexander Motin const char *dev; 1113b3dd3f7SAlexander Motin } controllers_opt = { 1123b3dd3f7SAlexander Motin .dev = NULL, 1133b3dd3f7SAlexander Motin }; 1143b3dd3f7SAlexander Motin 1153b3dd3f7SAlexander Motin static const struct args controllers_args[] = { 1165458a1c8SAlexander Motin { arg_string, &controllers_opt.dev, "controller-id|namespace-id" }, 1173b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 1183b3dd3f7SAlexander Motin }; 1193b3dd3f7SAlexander Motin 1203b3dd3f7SAlexander Motin static struct cmd controllers_cmd = { 1213b3dd3f7SAlexander Motin .name = "controllers", 1223b3dd3f7SAlexander Motin .fn = nscontrollers, 1233b3dd3f7SAlexander Motin .descr = "List all controllers in NVM subsystem", 1243b3dd3f7SAlexander Motin .ctx_size = sizeof(controllers_opt), 1253b3dd3f7SAlexander Motin .opts = NULL, 1263b3dd3f7SAlexander Motin .args = controllers_args, 1273b3dd3f7SAlexander Motin }; 1283b3dd3f7SAlexander Motin 1293b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, controllers_cmd); 1303b3dd3f7SAlexander Motin 131f634b4c1SWarner Losh static struct create_options { 132f634b4c1SWarner Losh uint64_t nsze; 133f634b4c1SWarner Losh uint64_t cap; 134f634b4c1SWarner Losh uint32_t lbaf; 135f634b4c1SWarner Losh uint32_t mset; 136f634b4c1SWarner Losh uint32_t nmic; 137f634b4c1SWarner Losh uint32_t pi; 138f634b4c1SWarner Losh uint32_t pil; 139f634b4c1SWarner Losh uint32_t flbas; 140f634b4c1SWarner Losh uint32_t dps; 141f634b4c1SWarner Losh // uint32_t block_size; 142f634b4c1SWarner Losh const char *dev; 143f634b4c1SWarner Losh } create_opt = { 144f634b4c1SWarner Losh .nsze = NONE64, 145f634b4c1SWarner Losh .cap = NONE64, 146f634b4c1SWarner Losh .lbaf = NONE, 147f634b4c1SWarner Losh .mset = NONE, 148f634b4c1SWarner Losh .nmic = NONE, 149f634b4c1SWarner Losh .pi = NONE, 150f634b4c1SWarner Losh .pil = NONE, 151f634b4c1SWarner Losh .flbas = NONE, 152f634b4c1SWarner Losh .dps = NONE, 153f634b4c1SWarner Losh .dev = NULL, 154f634b4c1SWarner Losh // .block_size = NONE, 155f634b4c1SWarner Losh }; 156f634b4c1SWarner Losh 157f634b4c1SWarner Losh static const struct opts create_opts[] = { 158f634b4c1SWarner Losh OPT("nsze", 's', arg_uint64, create_opt, nsze, 159f634b4c1SWarner Losh "The namespace size"), 160f634b4c1SWarner Losh OPT("ncap", 'c', arg_uint64, create_opt, cap, 161f634b4c1SWarner Losh "The capacity of the namespace (<= ns size)"), 162f634b4c1SWarner Losh OPT("lbaf", 'f', arg_uint32, create_opt, lbaf, 163f634b4c1SWarner Losh "The FMT field of the FLBAS"), 164f634b4c1SWarner Losh OPT("mset", 'm', arg_uint32, create_opt, mset, 165f634b4c1SWarner Losh "The MSET field of the FLBAS"), 166f634b4c1SWarner Losh OPT("nmic", 'n', arg_uint32, create_opt, nmic, 167f634b4c1SWarner Losh "Namespace multipath and sharing capabilities"), 168f634b4c1SWarner Losh OPT("pi", 'p', arg_uint32, create_opt, pi, 169f634b4c1SWarner Losh "PI field of FLBAS"), 170f634b4c1SWarner Losh OPT("pil", 'l', arg_uint32, create_opt, pil, 171f634b4c1SWarner Losh "PIL field of FLBAS"), 1723b3dd3f7SAlexander Motin OPT("flbas", 'L', arg_uint32, create_opt, flbas, 173f634b4c1SWarner Losh "Namespace formatted logical block size setting"), 174f634b4c1SWarner Losh OPT("dps", 'd', arg_uint32, create_opt, dps, 175f634b4c1SWarner Losh "Data protection settings"), 176f634b4c1SWarner Losh // OPT("block-size", 'b', arg_uint32, create_opt, block_size, 177f634b4c1SWarner Losh // "Blocksize of the namespace"), 178f634b4c1SWarner Losh OPT_END 179f634b4c1SWarner Losh }; 180f634b4c1SWarner Losh 181f634b4c1SWarner Losh static const struct args create_args[] = { 1825458a1c8SAlexander Motin { arg_string, &create_opt.dev, "controller-id|namespace-id" }, 183f634b4c1SWarner Losh { arg_none, NULL, NULL }, 184f634b4c1SWarner Losh }; 185f634b4c1SWarner Losh 186f634b4c1SWarner Losh static struct cmd create_cmd = { 187f634b4c1SWarner Losh .name = "create", 188f634b4c1SWarner Losh .fn = nscreate, 1893b3dd3f7SAlexander Motin .descr = "Create a namespace", 190f634b4c1SWarner Losh .ctx_size = sizeof(create_opt), 191f634b4c1SWarner Losh .opts = create_opts, 192f634b4c1SWarner Losh .args = create_args, 193f634b4c1SWarner Losh }; 194f634b4c1SWarner Losh 195f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, create_cmd); 196f634b4c1SWarner Losh 197f634b4c1SWarner Losh static struct delete_options { 198f634b4c1SWarner Losh uint32_t nsid; 199f634b4c1SWarner Losh const char *dev; 200f634b4c1SWarner Losh } delete_opt = { 201dbf1dce8SAlexander Motin .nsid = NONE - 1, 202f634b4c1SWarner Losh .dev = NULL, 203f634b4c1SWarner Losh }; 204f634b4c1SWarner Losh 205f634b4c1SWarner Losh static const struct opts delete_opts[] = { 206f634b4c1SWarner Losh OPT("namespace-id", 'n', arg_uint32, delete_opt, nsid, 207f634b4c1SWarner Losh "The namespace ID to delete"), 208f634b4c1SWarner Losh OPT_END 209f634b4c1SWarner Losh }; 210f634b4c1SWarner Losh 211f634b4c1SWarner Losh static const struct args delete_args[] = { 2125458a1c8SAlexander Motin { arg_string, &delete_opt.dev, "controller-id|namespace-id" }, 213f634b4c1SWarner Losh { arg_none, NULL, NULL }, 214f634b4c1SWarner Losh }; 215f634b4c1SWarner Losh 216f634b4c1SWarner Losh static struct cmd delete_cmd = { 217f634b4c1SWarner Losh .name = "delete", 218f634b4c1SWarner Losh .fn = nsdelete, 2193b3dd3f7SAlexander Motin .descr = "Delete a namespace", 220f634b4c1SWarner Losh .ctx_size = sizeof(delete_opt), 221f634b4c1SWarner Losh .opts = delete_opts, 222f634b4c1SWarner Losh .args = delete_args, 223f634b4c1SWarner Losh }; 224f634b4c1SWarner Losh 225f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, delete_cmd); 226f634b4c1SWarner Losh 227f634b4c1SWarner Losh static struct attach_options { 228f634b4c1SWarner Losh uint32_t nsid; 229f634b4c1SWarner Losh uint32_t ctrlrid; 230f634b4c1SWarner Losh const char *dev; 231f634b4c1SWarner Losh } attach_opt = { 232f634b4c1SWarner Losh .nsid = NONE, 233f634b4c1SWarner Losh .ctrlrid = NONE - 1, 234f634b4c1SWarner Losh .dev = NULL, 235f634b4c1SWarner Losh }; 236f634b4c1SWarner Losh 237f634b4c1SWarner Losh static const struct opts attach_opts[] = { 238f634b4c1SWarner Losh OPT("namespace-id", 'n', arg_uint32, attach_opt, nsid, 239f634b4c1SWarner Losh "The namespace ID to attach"), 2403b3dd3f7SAlexander Motin OPT("controller", 'c', arg_uint32, attach_opt, ctrlrid, 241f634b4c1SWarner Losh "The controller ID to attach"), 242f634b4c1SWarner Losh OPT_END 243f634b4c1SWarner Losh }; 244f634b4c1SWarner Losh 245f634b4c1SWarner Losh static const struct args attach_args[] = { 2465458a1c8SAlexander Motin { arg_string, &attach_opt.dev, "controller-id|namespace-id" }, 247f634b4c1SWarner Losh { arg_none, NULL, NULL }, 248f634b4c1SWarner Losh }; 249f634b4c1SWarner Losh 250f634b4c1SWarner Losh static struct cmd attach_cmd = { 251f634b4c1SWarner Losh .name = "attach", 252f634b4c1SWarner Losh .fn = nsattach, 2533b3dd3f7SAlexander Motin .descr = "Attach a controller to a namespace", 254f634b4c1SWarner Losh .ctx_size = sizeof(attach_opt), 255f634b4c1SWarner Losh .opts = attach_opts, 256f634b4c1SWarner Losh .args = attach_args, 257f634b4c1SWarner Losh }; 258f634b4c1SWarner Losh 259f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, attach_cmd); 260f634b4c1SWarner Losh 2613b3dd3f7SAlexander Motin static struct attached_options { 2623b3dd3f7SAlexander Motin uint32_t nsid; 2633b3dd3f7SAlexander Motin const char *dev; 2643b3dd3f7SAlexander Motin } attached_opt = { 2653b3dd3f7SAlexander Motin .nsid = NONE, 2663b3dd3f7SAlexander Motin .dev = NULL, 2673b3dd3f7SAlexander Motin }; 2683b3dd3f7SAlexander Motin 2693b3dd3f7SAlexander Motin static const struct opts attached_opts[] = { 2703b3dd3f7SAlexander Motin OPT("namespace-id", 'n', arg_uint32, attached_opt, nsid, 2713b3dd3f7SAlexander Motin "The namespace ID to request attached controllers"), 2723b3dd3f7SAlexander Motin OPT_END 2733b3dd3f7SAlexander Motin }; 2743b3dd3f7SAlexander Motin 2753b3dd3f7SAlexander Motin static const struct args attached_args[] = { 2765458a1c8SAlexander Motin { arg_string, &attached_opt.dev, "controller-id|namespace-id" }, 2773b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 2783b3dd3f7SAlexander Motin }; 2793b3dd3f7SAlexander Motin 2803b3dd3f7SAlexander Motin static struct cmd attached_cmd = { 2813b3dd3f7SAlexander Motin .name = "attached", 2823b3dd3f7SAlexander Motin .fn = nsattached, 2833b3dd3f7SAlexander Motin .descr = "List controllers attached to a namespace", 2843b3dd3f7SAlexander Motin .ctx_size = sizeof(attached_opt), 2853b3dd3f7SAlexander Motin .opts = attached_opts, 2863b3dd3f7SAlexander Motin .args = attached_args, 2873b3dd3f7SAlexander Motin }; 2883b3dd3f7SAlexander Motin 2893b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, attached_cmd); 2903b3dd3f7SAlexander Motin 291f634b4c1SWarner Losh static struct detach_options { 292f634b4c1SWarner Losh uint32_t nsid; 293f634b4c1SWarner Losh uint32_t ctrlrid; 294f634b4c1SWarner Losh const char *dev; 295f634b4c1SWarner Losh } detach_opt = { 296f634b4c1SWarner Losh .nsid = NONE, 297f634b4c1SWarner Losh .ctrlrid = NONE - 1, 298f634b4c1SWarner Losh .dev = NULL, 299f634b4c1SWarner Losh }; 300f634b4c1SWarner Losh 301f634b4c1SWarner Losh static const struct opts detach_opts[] = { 302f634b4c1SWarner Losh OPT("namespace-id", 'n', arg_uint32, detach_opt, nsid, 303f634b4c1SWarner Losh "The namespace ID to detach"), 3043b3dd3f7SAlexander Motin OPT("controller", 'c', arg_uint32, detach_opt, ctrlrid, 305f634b4c1SWarner Losh "The controller ID to detach"), 306f634b4c1SWarner Losh OPT_END 307f634b4c1SWarner Losh }; 308f634b4c1SWarner Losh 309f634b4c1SWarner Losh static const struct args detach_args[] = { 3105458a1c8SAlexander Motin { arg_string, &detach_opt.dev, "controller-id|namespace-id" }, 311f634b4c1SWarner Losh { arg_none, NULL, NULL }, 312f634b4c1SWarner Losh }; 313f634b4c1SWarner Losh 314f634b4c1SWarner Losh static struct cmd detach_cmd = { 315f634b4c1SWarner Losh .name = "detach", 316f634b4c1SWarner Losh .fn = nsdetach, 3173b3dd3f7SAlexander Motin .descr = "Detach a controller from a namespace", 318f634b4c1SWarner Losh .ctx_size = sizeof(detach_opt), 319f634b4c1SWarner Losh .opts = detach_opts, 320f634b4c1SWarner Losh .args = detach_args, 321f634b4c1SWarner Losh }; 322f634b4c1SWarner Losh 323f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, detach_cmd); 324a13a291aSWarner Losh 3253b3dd3f7SAlexander Motin static struct identify_options { 3263b3dd3f7SAlexander Motin bool hex; 3273b3dd3f7SAlexander Motin bool verbose; 3283b3dd3f7SAlexander Motin const char *dev; 3293b3dd3f7SAlexander Motin uint32_t nsid; 3303b3dd3f7SAlexander Motin } identify_opt = { 3313b3dd3f7SAlexander Motin .hex = false, 3323b3dd3f7SAlexander Motin .verbose = false, 3333b3dd3f7SAlexander Motin .dev = NULL, 334*d1a0eab9SAlexander Motin .nsid = NONE, 3353b3dd3f7SAlexander Motin }; 3363b3dd3f7SAlexander Motin 3373b3dd3f7SAlexander Motin static const struct opts identify_opts[] = { 3383b3dd3f7SAlexander Motin OPT("hex", 'x', arg_none, identify_opt, hex, 3393b3dd3f7SAlexander Motin "Print identiy information in hex"), 3403b3dd3f7SAlexander Motin OPT("verbose", 'v', arg_none, identify_opt, verbose, 3413b3dd3f7SAlexander Motin "More verbosity: print entire identify table"), 3423b3dd3f7SAlexander Motin OPT("nsid", 'n', arg_uint32, identify_opt, nsid, 3433b3dd3f7SAlexander Motin "The namespace ID to print IDENTIFY for"), 3443b3dd3f7SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 3453b3dd3f7SAlexander Motin }; 3463b3dd3f7SAlexander Motin 3473b3dd3f7SAlexander Motin static const struct args identify_args[] = { 3485458a1c8SAlexander Motin { arg_string, &identify_opt.dev, "controller-id|namespace-id" }, 3493b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 3503b3dd3f7SAlexander Motin }; 3513b3dd3f7SAlexander Motin 3523b3dd3f7SAlexander Motin static struct cmd identify_cmd = { 3533b3dd3f7SAlexander Motin .name = "identify", 3543b3dd3f7SAlexander Motin .fn = nsidentify, 3553b3dd3f7SAlexander Motin .descr = "Print IDENTIFY for allocated namespace", 3563b3dd3f7SAlexander Motin .ctx_size = sizeof(identify_opt), 3573b3dd3f7SAlexander Motin .opts = identify_opts, 3583b3dd3f7SAlexander Motin .args = identify_args, 3593b3dd3f7SAlexander Motin }; 3603b3dd3f7SAlexander Motin 3613b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, identify_cmd); 362a13a291aSWarner Losh 363ba405bc8SAlexander Motin /* handles NVME_OPC_NAMESPACE_MANAGEMENT and ATTACHMENT admin cmds */ 364ba405bc8SAlexander Motin 365ba405bc8SAlexander Motin struct ns_result_str { 366ba405bc8SAlexander Motin uint16_t res; 367ba405bc8SAlexander Motin const char * str; 368ba405bc8SAlexander Motin }; 369ba405bc8SAlexander Motin 370ba405bc8SAlexander Motin static struct ns_result_str ns_result[] = { 371ba405bc8SAlexander Motin { 0x2, "Invalid Field"}, 372ba405bc8SAlexander Motin { 0xa, "Invalid Format"}, 373ba405bc8SAlexander Motin { 0xb, "Invalid Namespace or format"}, 374ba405bc8SAlexander Motin { 0x15, "Namespace insufficent capacity"}, 375ba405bc8SAlexander Motin { 0x16, "Namespace ID unavaliable"}, 376ba405bc8SAlexander Motin { 0x18, "Namespace already attached"}, 377ba405bc8SAlexander Motin { 0x19, "Namespace is private"}, 378ba405bc8SAlexander Motin { 0x1a, "Namespace is not attached"}, 379ba405bc8SAlexander Motin { 0x1b, "Thin provisioning not supported"}, 380ba405bc8SAlexander Motin { 0x1c, "Controller list invalid"}, 3813b3dd3f7SAlexander Motin { 0x24, "ANA Group Identifier Invalid"}, 3823b3dd3f7SAlexander Motin { 0x25, "ANA Attach Failed"}, 383ba405bc8SAlexander Motin { 0xFFFF, "Unknown"} 384ba405bc8SAlexander Motin }; 385ba405bc8SAlexander Motin 386ba405bc8SAlexander Motin static const char * 387ba405bc8SAlexander Motin get_res_str(uint16_t res) 388ba405bc8SAlexander Motin { 389ba405bc8SAlexander Motin struct ns_result_str *t = ns_result; 390ba405bc8SAlexander Motin 391ba405bc8SAlexander Motin while (t->res != 0xFFFF) { 392ba405bc8SAlexander Motin if (t->res == res) 393ba405bc8SAlexander Motin return (t->str); 394ba405bc8SAlexander Motin t++; 395ba405bc8SAlexander Motin } 396ba405bc8SAlexander Motin return t->str; 397ba405bc8SAlexander Motin } 398ba405bc8SAlexander Motin 3993b3dd3f7SAlexander Motin static void 4003b3dd3f7SAlexander Motin nsactive(const struct cmd *f, int argc, char *argv[]) 4013b3dd3f7SAlexander Motin { 4023b3dd3f7SAlexander Motin struct nvme_pt_command pt; 4035458a1c8SAlexander Motin struct nvme_controller_data cd; 4043b3dd3f7SAlexander Motin int fd, i; 4055458a1c8SAlexander Motin char *path; 4065458a1c8SAlexander Motin uint32_t nsid; 4073b3dd3f7SAlexander Motin uint32_t list[1024]; 4083b3dd3f7SAlexander Motin 4093b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 4103b3dd3f7SAlexander Motin return; 4111f15d49eSAlexander Motin open_dev(active_opt.dev, &fd, 0, 1); 4125458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 4135458a1c8SAlexander Motin if (nsid != 0) { 4145458a1c8SAlexander Motin close(fd); 4155458a1c8SAlexander Motin open_dev(path, &fd, 0, 1); 4165458a1c8SAlexander Motin } 4175458a1c8SAlexander Motin free(path); 4185dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 4195dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 4205458a1c8SAlexander Motin 4215458a1c8SAlexander Motin /* Check that controller can execute this command. */ 4225458a1c8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 4235458a1c8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 4245dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 4253b3dd3f7SAlexander Motin 4263b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 4273b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 4283b3dd3f7SAlexander Motin pt.cmd.nsid = htole32(0); 4293b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x02); 4303b3dd3f7SAlexander Motin pt.buf = list; 4313b3dd3f7SAlexander Motin pt.len = sizeof(list); 4323b3dd3f7SAlexander Motin pt.is_read = 1; 4333b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 4345dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 4353b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 4365dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 4373b3dd3f7SAlexander Motin 4383b3dd3f7SAlexander Motin printf("Active namespaces:\n"); 4393b3dd3f7SAlexander Motin for (i = 0; list[i] != 0; i++) 4403b3dd3f7SAlexander Motin printf("%10d\n", le32toh(list[i])); 4413b3dd3f7SAlexander Motin 4423b3dd3f7SAlexander Motin exit(0); 4433b3dd3f7SAlexander Motin } 4443b3dd3f7SAlexander Motin 4453b3dd3f7SAlexander Motin static void 4463b3dd3f7SAlexander Motin nsallocated(const struct cmd *f, int argc, char *argv[]) 4473b3dd3f7SAlexander Motin { 4483b3dd3f7SAlexander Motin struct nvme_pt_command pt; 4493b3dd3f7SAlexander Motin struct nvme_controller_data cd; 4503b3dd3f7SAlexander Motin int fd, i; 4515458a1c8SAlexander Motin char *path; 4525458a1c8SAlexander Motin uint32_t nsid; 4533b3dd3f7SAlexander Motin uint32_t list[1024]; 4543b3dd3f7SAlexander Motin 4553b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 4563b3dd3f7SAlexander Motin return; 4571f15d49eSAlexander Motin open_dev(active_opt.dev, &fd, 0, 1); 4585458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 4595458a1c8SAlexander Motin if (nsid != 0) { 4605458a1c8SAlexander Motin close(fd); 4615458a1c8SAlexander Motin open_dev(path, &fd, 0, 1); 4625458a1c8SAlexander Motin } 4635458a1c8SAlexander Motin free(path); 4645dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 4655dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 4663b3dd3f7SAlexander Motin 4673b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 4683b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 4693b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 4705dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 4713b3dd3f7SAlexander Motin 4723b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 4733b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 4743b3dd3f7SAlexander Motin pt.cmd.nsid = htole32(0); 4753b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x10); 4763b3dd3f7SAlexander Motin pt.buf = list; 4773b3dd3f7SAlexander Motin pt.len = sizeof(list); 4783b3dd3f7SAlexander Motin pt.is_read = 1; 4793b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 4805dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 4813b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 4825dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 4833b3dd3f7SAlexander Motin 4843b3dd3f7SAlexander Motin printf("Allocated namespaces:\n"); 4853b3dd3f7SAlexander Motin for (i = 0; list[i] != 0; i++) 4863b3dd3f7SAlexander Motin printf("%10d\n", le32toh(list[i])); 4873b3dd3f7SAlexander Motin 4883b3dd3f7SAlexander Motin exit(0); 4893b3dd3f7SAlexander Motin } 4903b3dd3f7SAlexander Motin 4913b3dd3f7SAlexander Motin static void 4923b3dd3f7SAlexander Motin nscontrollers(const struct cmd *f, int argc, char *argv[]) 4933b3dd3f7SAlexander Motin { 4943b3dd3f7SAlexander Motin struct nvme_pt_command pt; 4953b3dd3f7SAlexander Motin struct nvme_controller_data cd; 4963b3dd3f7SAlexander Motin int fd, i, n; 4975458a1c8SAlexander Motin char *path; 4985458a1c8SAlexander Motin uint32_t nsid; 4993b3dd3f7SAlexander Motin uint16_t clist[2048]; 5003b3dd3f7SAlexander Motin 5013b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 5023b3dd3f7SAlexander Motin return; 5031f15d49eSAlexander Motin open_dev(controllers_opt.dev, &fd, 0, 1); 5045458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 5055458a1c8SAlexander Motin if (nsid != 0) { 5065458a1c8SAlexander Motin close(fd); 5075458a1c8SAlexander Motin open_dev(path, &fd, 0, 1); 5085458a1c8SAlexander Motin } 5095458a1c8SAlexander Motin free(path); 5105dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 5115dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 5123b3dd3f7SAlexander Motin 5133b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 5143b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 5153b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 5165dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 5173b3dd3f7SAlexander Motin 5183b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 5193b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 5203b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x13); 5213b3dd3f7SAlexander Motin pt.buf = clist; 5223b3dd3f7SAlexander Motin pt.len = sizeof(clist); 5233b3dd3f7SAlexander Motin pt.is_read = 1; 5243b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 5255dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 5263b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 5275dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 5283b3dd3f7SAlexander Motin 5293b3dd3f7SAlexander Motin n = le16toh(clist[0]); 5303b3dd3f7SAlexander Motin printf("NVM subsystem includes %d controller(s):\n", n); 5313b3dd3f7SAlexander Motin for (i = 0; i < n; i++) 5323b3dd3f7SAlexander Motin printf(" 0x%04x\n", le16toh(clist[i + 1])); 5333b3dd3f7SAlexander Motin 5343b3dd3f7SAlexander Motin exit(0); 5353b3dd3f7SAlexander Motin } 5363b3dd3f7SAlexander Motin 537ba405bc8SAlexander Motin /* 538ba405bc8SAlexander Motin * NS MGMT Command specific status values: 539ba405bc8SAlexander Motin * 0xa = Invalid Format 540ba405bc8SAlexander Motin * 0x15 = Namespace Insuffience capacity 541ba405bc8SAlexander Motin * 0x16 = Namespace ID unavailable (number namespaces exceeded) 542ba405bc8SAlexander Motin * 0xb = Thin Provisioning Not supported 543ba405bc8SAlexander Motin */ 5440d095c23SWarner Losh static void 545f634b4c1SWarner Losh nscreate(const struct cmd *f, int argc, char *argv[]) 546ba405bc8SAlexander Motin { 547ba405bc8SAlexander Motin struct nvme_pt_command pt; 548ba405bc8SAlexander Motin struct nvme_controller_data cd; 549ba405bc8SAlexander Motin struct nvme_namespace_data nsdata; 550f634b4c1SWarner Losh int fd, result; 5515458a1c8SAlexander Motin char *path; 5525458a1c8SAlexander Motin uint32_t nsid; 553ba405bc8SAlexander Motin 554f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 555f634b4c1SWarner Losh return; 556ba405bc8SAlexander Motin 557f634b4c1SWarner Losh if (create_opt.cap == NONE64) 558f634b4c1SWarner Losh create_opt.cap = create_opt.nsze; 559f634b4c1SWarner Losh if (create_opt.nsze == NONE64) { 560f634b4c1SWarner Losh fprintf(stderr, 561f634b4c1SWarner Losh "Size not specified\n"); 562f634b4c1SWarner Losh arg_help(argc, argv, f); 563ba405bc8SAlexander Motin } 564ba405bc8SAlexander Motin 565f634b4c1SWarner Losh open_dev(create_opt.dev, &fd, 1, 1); 5665458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 5675458a1c8SAlexander Motin if (nsid != 0) { 5685458a1c8SAlexander Motin close(fd); 5695458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 5705458a1c8SAlexander Motin } 5715458a1c8SAlexander Motin free(path); 5725dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 5735dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 574ba405bc8SAlexander Motin 575ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 576ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 577ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 5785dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 579ba405bc8SAlexander Motin 580ba405bc8SAlexander Motin /* Allow namespaces sharing if Multi-Path I/O is supported. */ 581f634b4c1SWarner Losh if (create_opt.nmic == NONE) { 582f634b4c1SWarner Losh create_opt.nmic = cd.mic ? (NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK << 583ba405bc8SAlexander Motin NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) : 0; 584ba405bc8SAlexander Motin } 585ba405bc8SAlexander Motin 586ba405bc8SAlexander Motin memset(&nsdata, 0, sizeof(nsdata)); 587f634b4c1SWarner Losh nsdata.nsze = create_opt.nsze; 588f634b4c1SWarner Losh nsdata.ncap = create_opt.cap; 589f634b4c1SWarner Losh if (create_opt.flbas == NONE) 590f634b4c1SWarner Losh nsdata.flbas = ((create_opt.lbaf & NVME_NS_DATA_FLBAS_FORMAT_MASK) 591ba405bc8SAlexander Motin << NVME_NS_DATA_FLBAS_FORMAT_SHIFT) | 592f634b4c1SWarner Losh ((create_opt.mset & NVME_NS_DATA_FLBAS_EXTENDED_MASK) 593ba405bc8SAlexander Motin << NVME_NS_DATA_FLBAS_EXTENDED_SHIFT); 594f634b4c1SWarner Losh else 595f634b4c1SWarner Losh nsdata.flbas = create_opt.flbas; 596f634b4c1SWarner Losh if (create_opt.dps == NONE) 597f634b4c1SWarner Losh nsdata.dps = ((create_opt.pi & NVME_NS_DATA_DPS_MD_START_MASK) 598ba405bc8SAlexander Motin << NVME_NS_DATA_DPS_MD_START_SHIFT) | 599f634b4c1SWarner Losh ((create_opt.pil & NVME_NS_DATA_DPS_PIT_MASK) 600ba405bc8SAlexander Motin << NVME_NS_DATA_DPS_PIT_SHIFT); 601f634b4c1SWarner Losh else 602f634b4c1SWarner Losh nsdata.dps = create_opt.dps; 603f634b4c1SWarner Losh nsdata.nmic = create_opt.nmic; 604ba405bc8SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 605ba405bc8SAlexander Motin 606ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 6079544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 6083b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0); /* create */ 609ba405bc8SAlexander Motin pt.buf = &nsdata; 610ba405bc8SAlexander Motin pt.len = sizeof(struct nvme_namespace_data); 611ba405bc8SAlexander Motin pt.is_read = 0; /* passthrough writes data to ctrlr */ 612ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 6135dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", create_opt.dev, result); 614ba405bc8SAlexander Motin 615ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 6165dc463f9SAlexander Motin errx(EX_IOERR, "namespace creation failed: %s", 617ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 618ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 619ba405bc8SAlexander Motin } 620ba405bc8SAlexander Motin printf("namespace %d created\n", pt.cpl.cdw0); 621ba405bc8SAlexander Motin exit(0); 622ba405bc8SAlexander Motin } 623ba405bc8SAlexander Motin 6240d095c23SWarner Losh static void 625f634b4c1SWarner Losh nsdelete(const struct cmd *f, int argc, char *argv[]) 626ba405bc8SAlexander Motin { 627ba405bc8SAlexander Motin struct nvme_pt_command pt; 628ba405bc8SAlexander Motin struct nvme_controller_data cd; 629f634b4c1SWarner Losh int fd, result; 6305458a1c8SAlexander Motin char *path; 6315458a1c8SAlexander Motin uint32_t nsid; 632ba405bc8SAlexander Motin char buf[2]; 633ba405bc8SAlexander Motin 634f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 635f634b4c1SWarner Losh return; 636ba405bc8SAlexander Motin 637f634b4c1SWarner Losh open_dev(delete_opt.dev, &fd, 1, 1); 6385458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 6395458a1c8SAlexander Motin if (nsid != 0) { 6405458a1c8SAlexander Motin close(fd); 6415458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 642dbf1dce8SAlexander Motin } else if (delete_opt.nsid == NONE - 1) { 6435458a1c8SAlexander Motin close(fd); 6445458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 6455458a1c8SAlexander Motin arg_help(argc, argv, f); 6465458a1c8SAlexander Motin } 647dbf1dce8SAlexander Motin if (delete_opt.nsid != NONE - 1) 6485458a1c8SAlexander Motin nsid = delete_opt.nsid; 6495458a1c8SAlexander Motin free(path); 6505dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 6515dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 652ba405bc8SAlexander Motin 653ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 654ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 655ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 6565dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 657ba405bc8SAlexander Motin 658ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 6599544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 6603b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(1); /* delete */ 661ba405bc8SAlexander Motin pt.buf = buf; 662ba405bc8SAlexander Motin pt.len = sizeof(buf); 663ba405bc8SAlexander Motin pt.is_read = 1; 6645458a1c8SAlexander Motin pt.cmd.nsid = nsid; 665ba405bc8SAlexander Motin 666ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 6675dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", delete_opt.dev, result); 668ba405bc8SAlexander Motin 669ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 6705dc463f9SAlexander Motin errx(EX_IOERR, "namespace deletion failed: %s", 671ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 672ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 673ba405bc8SAlexander Motin } 6745458a1c8SAlexander Motin printf("namespace %d deleted\n", nsid); 675ba405bc8SAlexander Motin exit(0); 676ba405bc8SAlexander Motin } 677ba405bc8SAlexander Motin 678ba405bc8SAlexander Motin /* 679ba405bc8SAlexander Motin * Attach and Detach use Dword 10, and a controller list (section 4.9) 680ba405bc8SAlexander Motin * This struct is 4096 bytes in size. 681ba405bc8SAlexander Motin * 0h = attach 682ba405bc8SAlexander Motin * 1h = detach 683ba405bc8SAlexander Motin * 684ba405bc8SAlexander Motin * Result values for both attach/detach: 685ba405bc8SAlexander Motin * 686ba405bc8SAlexander Motin * Completion 18h = Already attached 687ba405bc8SAlexander Motin * 19h = NS is private and already attached to a controller 688ba405bc8SAlexander Motin * 1Ah = Not attached, request could not be completed 689ba405bc8SAlexander Motin * 1Ch = Controller list invalid. 690ba405bc8SAlexander Motin * 691ba405bc8SAlexander Motin * 0x2 Invalid Field can occur if ctrlrid d.n.e in system. 692ba405bc8SAlexander Motin */ 6930d095c23SWarner Losh static void 694f634b4c1SWarner Losh nsattach(const struct cmd *f, int argc, char *argv[]) 695ba405bc8SAlexander Motin { 696ba405bc8SAlexander Motin struct nvme_pt_command pt; 697ba405bc8SAlexander Motin struct nvme_controller_data cd; 698f634b4c1SWarner Losh int fd, result; 6995458a1c8SAlexander Motin char *path; 7005458a1c8SAlexander Motin uint32_t nsid; 701ba405bc8SAlexander Motin uint16_t clist[2048]; 702ba405bc8SAlexander Motin 703f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 704f634b4c1SWarner Losh return; 7055458a1c8SAlexander Motin open_dev(attach_opt.dev, &fd, 1, 1); 7065458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 7075458a1c8SAlexander Motin if (nsid != 0) { 7085458a1c8SAlexander Motin close(fd); 7095458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 7105458a1c8SAlexander Motin } else if (attach_opt.nsid == NONE) { 7115458a1c8SAlexander Motin close(fd); 7125458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 713f634b4c1SWarner Losh arg_help(argc, argv, f); 714ba405bc8SAlexander Motin } 7155458a1c8SAlexander Motin if (attach_opt.nsid != NONE) 7165458a1c8SAlexander Motin nsid = attach_opt.nsid; 7175dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 7185dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 719ba405bc8SAlexander Motin 720ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 721ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 722ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 7235dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 724ba405bc8SAlexander Motin 725f634b4c1SWarner Losh if (attach_opt.ctrlrid == NONE) { 726ba405bc8SAlexander Motin /* Get full list of controllers to attach to. */ 727ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 7289544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 729ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x13); 730ba405bc8SAlexander Motin pt.buf = clist; 731ba405bc8SAlexander Motin pt.len = sizeof(clist); 732ba405bc8SAlexander Motin pt.is_read = 1; 733ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 7345dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 735ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 7365dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 737ba405bc8SAlexander Motin } else { 738ba405bc8SAlexander Motin /* By default attach to this controller. */ 739f634b4c1SWarner Losh if (attach_opt.ctrlrid == NONE - 1) 740f634b4c1SWarner Losh attach_opt.ctrlrid = cd.ctrlr_id; 741ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 742ba405bc8SAlexander Motin clist[0] = htole16(1); 743f634b4c1SWarner Losh clist[1] = htole16(attach_opt.ctrlrid); 744ba405bc8SAlexander Motin } 745ba405bc8SAlexander Motin 746ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 7479544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 7483b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0); /* attach */ 7495458a1c8SAlexander Motin pt.cmd.nsid = nsid; 750ba405bc8SAlexander Motin pt.buf = &clist; 751ba405bc8SAlexander Motin pt.len = sizeof(clist); 752ba405bc8SAlexander Motin 753ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 7545dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", attach_opt.dev, result); 755ba405bc8SAlexander Motin 756ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 7575dc463f9SAlexander Motin errx(EX_IOERR, "namespace attach failed: %s", 758ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 759ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 760ba405bc8SAlexander Motin } 7615458a1c8SAlexander Motin printf("namespace %d attached\n", nsid); 762ba405bc8SAlexander Motin exit(0); 763ba405bc8SAlexander Motin } 764ba405bc8SAlexander Motin 7650d095c23SWarner Losh static void 766f634b4c1SWarner Losh nsdetach(const struct cmd *f, int argc, char *argv[]) 767ba405bc8SAlexander Motin { 768ba405bc8SAlexander Motin struct nvme_pt_command pt; 769ba405bc8SAlexander Motin struct nvme_controller_data cd; 770f634b4c1SWarner Losh int fd, result; 7715458a1c8SAlexander Motin char *path; 7725458a1c8SAlexander Motin uint32_t nsid; 773ba405bc8SAlexander Motin uint16_t clist[2048]; 774ba405bc8SAlexander Motin 775f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 776f634b4c1SWarner Losh return; 7775458a1c8SAlexander Motin open_dev(detach_opt.dev, &fd, 1, 1); 7785458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 7795458a1c8SAlexander Motin if (nsid != 0) { 7805458a1c8SAlexander Motin close(fd); 7815458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 7825458a1c8SAlexander Motin } else if (detach_opt.nsid == NONE) { 7835458a1c8SAlexander Motin close(fd); 7845458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 785f634b4c1SWarner Losh arg_help(argc, argv, f); 786ba405bc8SAlexander Motin } 7875458a1c8SAlexander Motin if (detach_opt.nsid != NONE) 7885458a1c8SAlexander Motin nsid = detach_opt.nsid; 7895dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 7905dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 791ba405bc8SAlexander Motin 792ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 793ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 794ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 7955dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 796ba405bc8SAlexander Motin 797f634b4c1SWarner Losh if (detach_opt.ctrlrid == NONE) { 798ba405bc8SAlexander Motin /* Get list of controllers this namespace attached to. */ 799ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 8009544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 8015458a1c8SAlexander Motin pt.cmd.nsid = htole32(nsid); 802ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 803ba405bc8SAlexander Motin pt.buf = clist; 804ba405bc8SAlexander Motin pt.len = sizeof(clist); 805ba405bc8SAlexander Motin pt.is_read = 1; 806ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 8075dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 808ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 8095dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 810ba405bc8SAlexander Motin if (clist[0] == 0) { 811f634b4c1SWarner Losh detach_opt.ctrlrid = cd.ctrlr_id; 812ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 813ba405bc8SAlexander Motin clist[0] = htole16(1); 814f634b4c1SWarner Losh clist[1] = htole16(detach_opt.ctrlrid); 815ba405bc8SAlexander Motin } 816ba405bc8SAlexander Motin } else { 817ba405bc8SAlexander Motin /* By default detach from this controller. */ 818f634b4c1SWarner Losh if (detach_opt.ctrlrid == NONE - 1) 819f634b4c1SWarner Losh detach_opt.ctrlrid = cd.ctrlr_id; 820ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 821ba405bc8SAlexander Motin clist[0] = htole16(1); 822f634b4c1SWarner Losh clist[1] = htole16(detach_opt.ctrlrid); 823ba405bc8SAlexander Motin } 824ba405bc8SAlexander Motin 825ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 8269544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 8273b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(1); /* detach */ 8285458a1c8SAlexander Motin pt.cmd.nsid = nsid; 829ba405bc8SAlexander Motin pt.buf = &clist; 830ba405bc8SAlexander Motin pt.len = sizeof(clist); 831ba405bc8SAlexander Motin 832ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 8335dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", detach_opt.dev, result); 834ba405bc8SAlexander Motin 835ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 8365dc463f9SAlexander Motin errx(EX_IOERR, "namespace detach failed: %s", 837ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 838ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 839ba405bc8SAlexander Motin } 8405458a1c8SAlexander Motin printf("namespace %d detached\n", nsid); 841ba405bc8SAlexander Motin exit(0); 842ba405bc8SAlexander Motin } 843ba405bc8SAlexander Motin 844a13a291aSWarner Losh static void 8453b3dd3f7SAlexander Motin nsattached(const struct cmd *f, int argc, char *argv[]) 8463b3dd3f7SAlexander Motin { 8473b3dd3f7SAlexander Motin struct nvme_pt_command pt; 8483b3dd3f7SAlexander Motin struct nvme_controller_data cd; 8493b3dd3f7SAlexander Motin int fd, i, n; 8505458a1c8SAlexander Motin char *path; 8515458a1c8SAlexander Motin uint32_t nsid; 8523b3dd3f7SAlexander Motin uint16_t clist[2048]; 8533b3dd3f7SAlexander Motin 8543b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 8553b3dd3f7SAlexander Motin return; 8565458a1c8SAlexander Motin open_dev(attached_opt.dev, &fd, 0, 1); 8575458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 8585458a1c8SAlexander Motin if (nsid != 0) { 8595458a1c8SAlexander Motin close(fd); 8605458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 8615458a1c8SAlexander Motin } else if (attached_opt.nsid == NONE) { 8625458a1c8SAlexander Motin close(fd); 8635458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 8643b3dd3f7SAlexander Motin arg_help(argc, argv, f); 8653b3dd3f7SAlexander Motin } 8665458a1c8SAlexander Motin if (attached_opt.nsid != NONE) 8675458a1c8SAlexander Motin nsid = attached_opt.nsid; 8685dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 8695dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 8703b3dd3f7SAlexander Motin 8713b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 8723b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 8733b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 8745dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 8753b3dd3f7SAlexander Motin 8763b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 8773b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 8785458a1c8SAlexander Motin pt.cmd.nsid = htole32(nsid); 8793b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 8803b3dd3f7SAlexander Motin pt.buf = clist; 8813b3dd3f7SAlexander Motin pt.len = sizeof(clist); 8823b3dd3f7SAlexander Motin pt.is_read = 1; 8833b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 8845dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 8853b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 8865dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 8873b3dd3f7SAlexander Motin 8883b3dd3f7SAlexander Motin n = le16toh(clist[0]); 8893b3dd3f7SAlexander Motin printf("Attached %d controller(s):\n", n); 8903b3dd3f7SAlexander Motin for (i = 0; i < n; i++) 8913b3dd3f7SAlexander Motin printf(" 0x%04x\n", le16toh(clist[i + 1])); 8923b3dd3f7SAlexander Motin 8933b3dd3f7SAlexander Motin exit(0); 8943b3dd3f7SAlexander Motin } 8953b3dd3f7SAlexander Motin 8963b3dd3f7SAlexander Motin static void 8973b3dd3f7SAlexander Motin nsidentify(const struct cmd *f, int argc, char *argv[]) 8983b3dd3f7SAlexander Motin { 8993b3dd3f7SAlexander Motin struct nvme_pt_command pt; 9003b3dd3f7SAlexander Motin struct nvme_controller_data cd; 9013b3dd3f7SAlexander Motin struct nvme_namespace_data nsdata; 9023b3dd3f7SAlexander Motin uint8_t *data; 9033b3dd3f7SAlexander Motin int fd; 9045458a1c8SAlexander Motin char *path; 9055458a1c8SAlexander Motin uint32_t nsid; 9063b3dd3f7SAlexander Motin u_int i; 9073b3dd3f7SAlexander Motin 9083b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 9093b3dd3f7SAlexander Motin return; 9105458a1c8SAlexander Motin open_dev(identify_opt.dev, &fd, 0, 1); 9115458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 9125458a1c8SAlexander Motin if (nsid != 0) { 9135458a1c8SAlexander Motin close(fd); 9145458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 915*d1a0eab9SAlexander Motin } else if (identify_opt.nsid == NONE) { 9165458a1c8SAlexander Motin close(fd); 9175458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 9183b3dd3f7SAlexander Motin arg_help(argc, argv, f); 9193b3dd3f7SAlexander Motin } 920*d1a0eab9SAlexander Motin if (identify_opt.nsid != NONE) 9215458a1c8SAlexander Motin nsid = identify_opt.nsid; 9225dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 9235dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 9243b3dd3f7SAlexander Motin 9253b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 9263b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 9273b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 9285dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 9293b3dd3f7SAlexander Motin 9303b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 9313b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 9325458a1c8SAlexander Motin pt.cmd.nsid = htole32(nsid); 9333b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x11); 9343b3dd3f7SAlexander Motin pt.buf = &nsdata; 9353b3dd3f7SAlexander Motin pt.len = sizeof(nsdata); 9363b3dd3f7SAlexander Motin pt.is_read = 1; 9373b3dd3f7SAlexander Motin 9383b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 9395dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 9403b3dd3f7SAlexander Motin 9413b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 9425dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 9433b3dd3f7SAlexander Motin 9443b3dd3f7SAlexander Motin close(fd); 9453b3dd3f7SAlexander Motin 9463b3dd3f7SAlexander Motin data = (uint8_t *)&nsdata; 9473b3dd3f7SAlexander Motin for (i = 0; i < sizeof(nsdata); i++) { 9483b3dd3f7SAlexander Motin if (data[i] != 0) 9493b3dd3f7SAlexander Motin break; 9503b3dd3f7SAlexander Motin } 9513b3dd3f7SAlexander Motin if (i == sizeof(nsdata)) 9525dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "namespace %d is not allocated", nsid); 9533b3dd3f7SAlexander Motin 9543b3dd3f7SAlexander Motin /* Convert data to host endian */ 9553b3dd3f7SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 9563b3dd3f7SAlexander Motin 9573b3dd3f7SAlexander Motin if (identify_opt.hex) { 9583b3dd3f7SAlexander Motin i = sizeof(struct nvme_namespace_data); 9593b3dd3f7SAlexander Motin if (!identify_opt.verbose) { 9603b3dd3f7SAlexander Motin for (; i > 384; i--) { 9613b3dd3f7SAlexander Motin if (data[i - 1] != 0) 9623b3dd3f7SAlexander Motin break; 9633b3dd3f7SAlexander Motin } 9643b3dd3f7SAlexander Motin } 9653b3dd3f7SAlexander Motin print_hex(&nsdata, i); 9663b3dd3f7SAlexander Motin exit(0); 9673b3dd3f7SAlexander Motin } 9683b3dd3f7SAlexander Motin 9693b3dd3f7SAlexander Motin print_namespace(&nsdata); 9703b3dd3f7SAlexander Motin exit(0); 9713b3dd3f7SAlexander Motin } 9723b3dd3f7SAlexander Motin 9733b3dd3f7SAlexander Motin static void 974f634b4c1SWarner Losh ns(const struct cmd *nf __unused, int argc, char *argv[]) 975ba405bc8SAlexander Motin { 976ba405bc8SAlexander Motin 977f634b4c1SWarner Losh cmd_dispatch(argc, argv, &ns_cmd); 978ba405bc8SAlexander Motin } 979