1ba405bc8SAlexander Motin /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 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, 334d1a0eab9SAlexander 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"}, 374e2dfabb5SGordon Bergling { 0x15, "Namespace insufficient capacity"}, 3755d7c65ffSJens Schweikhardt { 0x16, "Namespace ID unavailable"}, 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 memset(&nsdata, 0, sizeof(nsdata)); 581f634b4c1SWarner Losh nsdata.nsze = create_opt.nsze; 582f634b4c1SWarner Losh nsdata.ncap = create_opt.cap; 58320dc2c4dSAlexander Motin if (create_opt.flbas != NONE) { 584f634b4c1SWarner Losh nsdata.flbas = create_opt.flbas; 58520dc2c4dSAlexander Motin } else { 58620dc2c4dSAlexander Motin /* Default to the first format, whatever it is. */ 58720dc2c4dSAlexander Motin nsdata.flbas = 0; 58820dc2c4dSAlexander Motin if (create_opt.lbaf != NONE) { 58920dc2c4dSAlexander Motin nsdata.flbas |= (create_opt.lbaf & 59020dc2c4dSAlexander Motin NVME_NS_DATA_FLBAS_FORMAT_MASK) 59120dc2c4dSAlexander Motin << NVME_NS_DATA_FLBAS_FORMAT_SHIFT; 59220dc2c4dSAlexander Motin } 59320dc2c4dSAlexander Motin if (create_opt.mset != NONE) { 59420dc2c4dSAlexander Motin nsdata.flbas |= (create_opt.mset & 59520dc2c4dSAlexander Motin NVME_NS_DATA_FLBAS_EXTENDED_MASK) 59620dc2c4dSAlexander Motin << NVME_NS_DATA_FLBAS_EXTENDED_SHIFT; 59720dc2c4dSAlexander Motin } 59820dc2c4dSAlexander Motin } 59920dc2c4dSAlexander Motin if (create_opt.dps != NONE) { 600f634b4c1SWarner Losh nsdata.dps = create_opt.dps; 60120dc2c4dSAlexander Motin } else { 60220dc2c4dSAlexander Motin /* Default to protection disabled. */ 60320dc2c4dSAlexander Motin nsdata.dps = 0; 60420dc2c4dSAlexander Motin if (create_opt.pi != NONE) { 60520dc2c4dSAlexander Motin nsdata.dps |= (create_opt.pi & 60620dc2c4dSAlexander Motin NVME_NS_DATA_DPS_MD_START_MASK) 60720dc2c4dSAlexander Motin << NVME_NS_DATA_DPS_MD_START_SHIFT; 60820dc2c4dSAlexander Motin } 60920dc2c4dSAlexander Motin if (create_opt.pil != NONE) { 61020dc2c4dSAlexander Motin nsdata.dps |= (create_opt.pil & 61120dc2c4dSAlexander Motin NVME_NS_DATA_DPS_PIT_MASK) 61220dc2c4dSAlexander Motin << NVME_NS_DATA_DPS_PIT_SHIFT; 61320dc2c4dSAlexander Motin } 61420dc2c4dSAlexander Motin } 61520dc2c4dSAlexander Motin if (create_opt.nmic != NONE) { 616f634b4c1SWarner Losh nsdata.nmic = create_opt.nmic; 61720dc2c4dSAlexander Motin } else { 61820dc2c4dSAlexander Motin /* Allow namespaces sharing if Multi-Path I/O is supported. */ 61920dc2c4dSAlexander Motin nsdata.nmic = cd.mic ? (NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK << 62020dc2c4dSAlexander Motin NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) : 0; 62120dc2c4dSAlexander Motin } 622ba405bc8SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 623ba405bc8SAlexander Motin 624ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 6259544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 6263b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0); /* create */ 627ba405bc8SAlexander Motin pt.buf = &nsdata; 628ba405bc8SAlexander Motin pt.len = sizeof(struct nvme_namespace_data); 629ba405bc8SAlexander Motin pt.is_read = 0; /* passthrough writes data to ctrlr */ 630ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 6315dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", create_opt.dev, result); 632ba405bc8SAlexander Motin 633ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 6345dc463f9SAlexander Motin errx(EX_IOERR, "namespace creation failed: %s", 635ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 636ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 637ba405bc8SAlexander Motin } 638ba405bc8SAlexander Motin printf("namespace %d created\n", pt.cpl.cdw0); 639ba405bc8SAlexander Motin exit(0); 640ba405bc8SAlexander Motin } 641ba405bc8SAlexander Motin 6420d095c23SWarner Losh static void 643f634b4c1SWarner Losh nsdelete(const struct cmd *f, int argc, char *argv[]) 644ba405bc8SAlexander Motin { 645ba405bc8SAlexander Motin struct nvme_pt_command pt; 646ba405bc8SAlexander Motin struct nvme_controller_data cd; 647f634b4c1SWarner Losh int fd, result; 6485458a1c8SAlexander Motin char *path; 6495458a1c8SAlexander Motin uint32_t nsid; 650ba405bc8SAlexander Motin char buf[2]; 651ba405bc8SAlexander Motin 652f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 653f634b4c1SWarner Losh return; 654ba405bc8SAlexander Motin 655f634b4c1SWarner Losh open_dev(delete_opt.dev, &fd, 1, 1); 6565458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 6575458a1c8SAlexander Motin if (nsid != 0) { 6585458a1c8SAlexander Motin close(fd); 6595458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 660dbf1dce8SAlexander Motin } else if (delete_opt.nsid == NONE - 1) { 6615458a1c8SAlexander Motin close(fd); 6625458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 6635458a1c8SAlexander Motin arg_help(argc, argv, f); 6645458a1c8SAlexander Motin } 665dbf1dce8SAlexander Motin if (delete_opt.nsid != NONE - 1) 6665458a1c8SAlexander Motin nsid = delete_opt.nsid; 6675458a1c8SAlexander Motin free(path); 6685dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 6695dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 670ba405bc8SAlexander Motin 671ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 672ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 673ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 6745dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 675ba405bc8SAlexander Motin 676ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 6779544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 6783b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(1); /* delete */ 679ba405bc8SAlexander Motin pt.buf = buf; 680ba405bc8SAlexander Motin pt.len = sizeof(buf); 681ba405bc8SAlexander Motin pt.is_read = 1; 6825458a1c8SAlexander Motin pt.cmd.nsid = nsid; 683ba405bc8SAlexander Motin 684ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 6855dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", delete_opt.dev, result); 686ba405bc8SAlexander Motin 687ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 6885dc463f9SAlexander Motin errx(EX_IOERR, "namespace deletion failed: %s", 689ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 690ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 691ba405bc8SAlexander Motin } 6925458a1c8SAlexander Motin printf("namespace %d deleted\n", nsid); 693ba405bc8SAlexander Motin exit(0); 694ba405bc8SAlexander Motin } 695ba405bc8SAlexander Motin 696ba405bc8SAlexander Motin /* 697ba405bc8SAlexander Motin * Attach and Detach use Dword 10, and a controller list (section 4.9) 698ba405bc8SAlexander Motin * This struct is 4096 bytes in size. 699ba405bc8SAlexander Motin * 0h = attach 700ba405bc8SAlexander Motin * 1h = detach 701ba405bc8SAlexander Motin * 702ba405bc8SAlexander Motin * Result values for both attach/detach: 703ba405bc8SAlexander Motin * 704ba405bc8SAlexander Motin * Completion 18h = Already attached 705ba405bc8SAlexander Motin * 19h = NS is private and already attached to a controller 706ba405bc8SAlexander Motin * 1Ah = Not attached, request could not be completed 707ba405bc8SAlexander Motin * 1Ch = Controller list invalid. 708ba405bc8SAlexander Motin * 709ba405bc8SAlexander Motin * 0x2 Invalid Field can occur if ctrlrid d.n.e in system. 710ba405bc8SAlexander Motin */ 7110d095c23SWarner Losh static void 712f634b4c1SWarner Losh nsattach(const struct cmd *f, int argc, char *argv[]) 713ba405bc8SAlexander Motin { 714ba405bc8SAlexander Motin struct nvme_pt_command pt; 715ba405bc8SAlexander Motin struct nvme_controller_data cd; 716f634b4c1SWarner Losh int fd, result; 7175458a1c8SAlexander Motin char *path; 7185458a1c8SAlexander Motin uint32_t nsid; 719ba405bc8SAlexander Motin uint16_t clist[2048]; 720ba405bc8SAlexander Motin 721f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 722f634b4c1SWarner Losh return; 7235458a1c8SAlexander Motin open_dev(attach_opt.dev, &fd, 1, 1); 7245458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 7255458a1c8SAlexander Motin if (nsid != 0) { 7265458a1c8SAlexander Motin close(fd); 7275458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 7285458a1c8SAlexander Motin } else if (attach_opt.nsid == NONE) { 7295458a1c8SAlexander Motin close(fd); 7305458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 731f634b4c1SWarner Losh arg_help(argc, argv, f); 732ba405bc8SAlexander Motin } 7335458a1c8SAlexander Motin if (attach_opt.nsid != NONE) 7345458a1c8SAlexander Motin nsid = attach_opt.nsid; 7355dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 7365dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 737ba405bc8SAlexander Motin 738ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 739ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 740ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 7415dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 742ba405bc8SAlexander Motin 743f634b4c1SWarner Losh if (attach_opt.ctrlrid == NONE) { 744ba405bc8SAlexander Motin /* Get full list of controllers to attach to. */ 745ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 7469544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 747ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x13); 748ba405bc8SAlexander Motin pt.buf = clist; 749ba405bc8SAlexander Motin pt.len = sizeof(clist); 750ba405bc8SAlexander Motin pt.is_read = 1; 751ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 7525dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 753ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 7545dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 755ba405bc8SAlexander Motin } else { 756ba405bc8SAlexander Motin /* By default attach to this controller. */ 757f634b4c1SWarner Losh if (attach_opt.ctrlrid == NONE - 1) 758f634b4c1SWarner Losh attach_opt.ctrlrid = cd.ctrlr_id; 759ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 760ba405bc8SAlexander Motin clist[0] = htole16(1); 761f634b4c1SWarner Losh clist[1] = htole16(attach_opt.ctrlrid); 762ba405bc8SAlexander Motin } 763ba405bc8SAlexander Motin 764ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 7659544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 7663b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0); /* attach */ 7675458a1c8SAlexander Motin pt.cmd.nsid = nsid; 768ba405bc8SAlexander Motin pt.buf = &clist; 769ba405bc8SAlexander Motin pt.len = sizeof(clist); 770ba405bc8SAlexander Motin 771ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 7725dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", attach_opt.dev, result); 773ba405bc8SAlexander Motin 774ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 7755dc463f9SAlexander Motin errx(EX_IOERR, "namespace attach failed: %s", 776ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 777ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 778ba405bc8SAlexander Motin } 7795458a1c8SAlexander Motin printf("namespace %d attached\n", nsid); 780ba405bc8SAlexander Motin exit(0); 781ba405bc8SAlexander Motin } 782ba405bc8SAlexander Motin 7830d095c23SWarner Losh static void 784f634b4c1SWarner Losh nsdetach(const struct cmd *f, int argc, char *argv[]) 785ba405bc8SAlexander Motin { 786ba405bc8SAlexander Motin struct nvme_pt_command pt; 787ba405bc8SAlexander Motin struct nvme_controller_data cd; 788f634b4c1SWarner Losh int fd, result; 7895458a1c8SAlexander Motin char *path; 7905458a1c8SAlexander Motin uint32_t nsid; 791ba405bc8SAlexander Motin uint16_t clist[2048]; 792ba405bc8SAlexander Motin 793f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 794f634b4c1SWarner Losh return; 7955458a1c8SAlexander Motin open_dev(detach_opt.dev, &fd, 1, 1); 7965458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 7975458a1c8SAlexander Motin if (nsid != 0) { 7985458a1c8SAlexander Motin close(fd); 7995458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 8005458a1c8SAlexander Motin } else if (detach_opt.nsid == NONE) { 8015458a1c8SAlexander Motin close(fd); 8025458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 803f634b4c1SWarner Losh arg_help(argc, argv, f); 804ba405bc8SAlexander Motin } 8055458a1c8SAlexander Motin if (detach_opt.nsid != NONE) 8065458a1c8SAlexander Motin nsid = detach_opt.nsid; 8075dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 8085dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 809ba405bc8SAlexander Motin 810ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 811ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 812ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 8135dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 814ba405bc8SAlexander Motin 815f634b4c1SWarner Losh if (detach_opt.ctrlrid == NONE) { 816ba405bc8SAlexander Motin /* Get list of controllers this namespace attached to. */ 817ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 8189544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 8195458a1c8SAlexander Motin pt.cmd.nsid = htole32(nsid); 820ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 821ba405bc8SAlexander Motin pt.buf = clist; 822ba405bc8SAlexander Motin pt.len = sizeof(clist); 823ba405bc8SAlexander Motin pt.is_read = 1; 824ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 8255dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 826ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 8275dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 828ba405bc8SAlexander Motin if (clist[0] == 0) { 829f634b4c1SWarner Losh detach_opt.ctrlrid = cd.ctrlr_id; 830ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 831ba405bc8SAlexander Motin clist[0] = htole16(1); 832f634b4c1SWarner Losh clist[1] = htole16(detach_opt.ctrlrid); 833ba405bc8SAlexander Motin } 834ba405bc8SAlexander Motin } else { 835ba405bc8SAlexander Motin /* By default detach from this controller. */ 836f634b4c1SWarner Losh if (detach_opt.ctrlrid == NONE - 1) 837f634b4c1SWarner Losh detach_opt.ctrlrid = cd.ctrlr_id; 838ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 839ba405bc8SAlexander Motin clist[0] = htole16(1); 840f634b4c1SWarner Losh clist[1] = htole16(detach_opt.ctrlrid); 841ba405bc8SAlexander Motin } 842ba405bc8SAlexander Motin 843ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 8449544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 8453b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(1); /* detach */ 8465458a1c8SAlexander Motin pt.cmd.nsid = nsid; 847ba405bc8SAlexander Motin pt.buf = &clist; 848ba405bc8SAlexander Motin pt.len = sizeof(clist); 849ba405bc8SAlexander Motin 850ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 8515dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", detach_opt.dev, result); 852ba405bc8SAlexander Motin 853ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 8545dc463f9SAlexander Motin errx(EX_IOERR, "namespace detach failed: %s", 855ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 856ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 857ba405bc8SAlexander Motin } 8585458a1c8SAlexander Motin printf("namespace %d detached\n", nsid); 859ba405bc8SAlexander Motin exit(0); 860ba405bc8SAlexander Motin } 861ba405bc8SAlexander Motin 862a13a291aSWarner Losh static void 8633b3dd3f7SAlexander Motin nsattached(const struct cmd *f, int argc, char *argv[]) 8643b3dd3f7SAlexander Motin { 8653b3dd3f7SAlexander Motin struct nvme_pt_command pt; 8663b3dd3f7SAlexander Motin struct nvme_controller_data cd; 8673b3dd3f7SAlexander Motin int fd, i, n; 8685458a1c8SAlexander Motin char *path; 8695458a1c8SAlexander Motin uint32_t nsid; 8703b3dd3f7SAlexander Motin uint16_t clist[2048]; 8713b3dd3f7SAlexander Motin 8723b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 8733b3dd3f7SAlexander Motin return; 8745458a1c8SAlexander Motin open_dev(attached_opt.dev, &fd, 0, 1); 8755458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 8765458a1c8SAlexander Motin if (nsid != 0) { 8775458a1c8SAlexander Motin close(fd); 8785458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 8795458a1c8SAlexander Motin } else if (attached_opt.nsid == NONE) { 8805458a1c8SAlexander Motin close(fd); 8815458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 8823b3dd3f7SAlexander Motin arg_help(argc, argv, f); 8833b3dd3f7SAlexander Motin } 8845458a1c8SAlexander Motin if (attached_opt.nsid != NONE) 8855458a1c8SAlexander Motin nsid = attached_opt.nsid; 8865dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 8875dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 8883b3dd3f7SAlexander Motin 8893b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 8903b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 8913b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 8925dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 8933b3dd3f7SAlexander Motin 8943b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 8953b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 8965458a1c8SAlexander Motin pt.cmd.nsid = htole32(nsid); 8973b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 8983b3dd3f7SAlexander Motin pt.buf = clist; 8993b3dd3f7SAlexander Motin pt.len = sizeof(clist); 9003b3dd3f7SAlexander Motin pt.is_read = 1; 9013b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 9025dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 9033b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 9045dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 9053b3dd3f7SAlexander Motin 9063b3dd3f7SAlexander Motin n = le16toh(clist[0]); 9073b3dd3f7SAlexander Motin printf("Attached %d controller(s):\n", n); 9083b3dd3f7SAlexander Motin for (i = 0; i < n; i++) 9093b3dd3f7SAlexander Motin printf(" 0x%04x\n", le16toh(clist[i + 1])); 9103b3dd3f7SAlexander Motin 9113b3dd3f7SAlexander Motin exit(0); 9123b3dd3f7SAlexander Motin } 9133b3dd3f7SAlexander Motin 9143b3dd3f7SAlexander Motin static void 9153b3dd3f7SAlexander Motin nsidentify(const struct cmd *f, int argc, char *argv[]) 9163b3dd3f7SAlexander Motin { 9173b3dd3f7SAlexander Motin struct nvme_pt_command pt; 9183b3dd3f7SAlexander Motin struct nvme_controller_data cd; 9193b3dd3f7SAlexander Motin struct nvme_namespace_data nsdata; 9203b3dd3f7SAlexander Motin uint8_t *data; 9213b3dd3f7SAlexander Motin int fd; 9225458a1c8SAlexander Motin char *path; 9235458a1c8SAlexander Motin uint32_t nsid; 9243b3dd3f7SAlexander Motin u_int i; 9253b3dd3f7SAlexander Motin 9263b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 9273b3dd3f7SAlexander Motin return; 9285458a1c8SAlexander Motin open_dev(identify_opt.dev, &fd, 0, 1); 9295458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 9305458a1c8SAlexander Motin if (nsid != 0) { 9315458a1c8SAlexander Motin close(fd); 9325458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 933d1a0eab9SAlexander Motin } else if (identify_opt.nsid == NONE) { 9345458a1c8SAlexander Motin close(fd); 9355458a1c8SAlexander Motin fprintf(stderr, "No NSID specified"); 9363b3dd3f7SAlexander Motin arg_help(argc, argv, f); 9373b3dd3f7SAlexander Motin } 938d1a0eab9SAlexander Motin if (identify_opt.nsid != NONE) 9395458a1c8SAlexander Motin nsid = identify_opt.nsid; 9405dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 9415dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 9423b3dd3f7SAlexander Motin 9433b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 9443b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 9453b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 9465dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 9473b3dd3f7SAlexander Motin 9483b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 9493b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 9505458a1c8SAlexander Motin pt.cmd.nsid = htole32(nsid); 9513b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x11); 9523b3dd3f7SAlexander Motin pt.buf = &nsdata; 9533b3dd3f7SAlexander Motin pt.len = sizeof(nsdata); 9543b3dd3f7SAlexander Motin pt.is_read = 1; 9553b3dd3f7SAlexander Motin 9563b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 9575dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 9583b3dd3f7SAlexander Motin 9593b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 9605dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 9613b3dd3f7SAlexander Motin 9623b3dd3f7SAlexander Motin close(fd); 9633b3dd3f7SAlexander Motin 9643b3dd3f7SAlexander Motin data = (uint8_t *)&nsdata; 9653b3dd3f7SAlexander Motin for (i = 0; i < sizeof(nsdata); i++) { 9663b3dd3f7SAlexander Motin if (data[i] != 0) 9673b3dd3f7SAlexander Motin break; 9683b3dd3f7SAlexander Motin } 9693b3dd3f7SAlexander Motin if (i == sizeof(nsdata)) 9705dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "namespace %d is not allocated", nsid); 9713b3dd3f7SAlexander Motin 9723b3dd3f7SAlexander Motin /* Convert data to host endian */ 9733b3dd3f7SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 9743b3dd3f7SAlexander Motin 9753b3dd3f7SAlexander Motin if (identify_opt.hex) { 9763b3dd3f7SAlexander Motin i = sizeof(struct nvme_namespace_data); 9773b3dd3f7SAlexander Motin if (!identify_opt.verbose) { 9783b3dd3f7SAlexander Motin for (; i > 384; i--) { 9793b3dd3f7SAlexander Motin if (data[i - 1] != 0) 9803b3dd3f7SAlexander Motin break; 9813b3dd3f7SAlexander Motin } 9823b3dd3f7SAlexander Motin } 9833b3dd3f7SAlexander Motin print_hex(&nsdata, i); 9843b3dd3f7SAlexander Motin exit(0); 9853b3dd3f7SAlexander Motin } 9863b3dd3f7SAlexander Motin 9873b3dd3f7SAlexander Motin print_namespace(&nsdata); 9883b3dd3f7SAlexander Motin exit(0); 9893b3dd3f7SAlexander Motin } 9903b3dd3f7SAlexander Motin 9913b3dd3f7SAlexander Motin static void 992f634b4c1SWarner Losh ns(const struct cmd *nf __unused, int argc, char *argv[]) 993ba405bc8SAlexander Motin { 994ba405bc8SAlexander Motin 995f634b4c1SWarner Losh cmd_dispatch(argc, argv, &ns_cmd); 996ba405bc8SAlexander Motin } 997