1ba405bc8SAlexander Motin /*- 2ba405bc8SAlexander Motin * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3ba405bc8SAlexander Motin * 452467047SWarner Losh * Copyright (c) 2017 Netflix, Inc. 5*a7bf63beSAlexander 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> 42ba405bc8SAlexander Motin #include <unistd.h> 43ba405bc8SAlexander Motin 44ba405bc8SAlexander Motin #include "nvmecontrol.h" 45ba405bc8SAlexander Motin 46f634b4c1SWarner Losh /* Tables for command line parsing */ 47f634b4c1SWarner Losh 48f634b4c1SWarner Losh static cmd_fn_t ns; 493b3dd3f7SAlexander Motin static cmd_fn_t nsactive; 503b3dd3f7SAlexander Motin static cmd_fn_t nsallocated; 513b3dd3f7SAlexander Motin static cmd_fn_t nscontrollers; 52f634b4c1SWarner Losh static cmd_fn_t nscreate; 53f634b4c1SWarner Losh static cmd_fn_t nsdelete; 54f634b4c1SWarner Losh static cmd_fn_t nsattach; 55f634b4c1SWarner Losh static cmd_fn_t nsdetach; 563b3dd3f7SAlexander Motin static cmd_fn_t nsattached; 573b3dd3f7SAlexander Motin static cmd_fn_t nsidentify; 58f634b4c1SWarner Losh 59f634b4c1SWarner Losh #define NONE 0xffffffffu 60f634b4c1SWarner Losh #define NONE64 0xffffffffffffffffull 61f634b4c1SWarner Losh #define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc } 62f634b4c1SWarner Losh #define OPT_END { NULL, 0, arg_none, NULL, NULL } 63f634b4c1SWarner Losh 64f634b4c1SWarner Losh static struct cmd ns_cmd = { 653b3dd3f7SAlexander Motin .name = "ns", 663b3dd3f7SAlexander Motin .fn = ns, 673b3dd3f7SAlexander Motin .descr = "Namespace management commands", 683b3dd3f7SAlexander Motin .ctx_size = 0, 693b3dd3f7SAlexander Motin .opts = NULL, 703b3dd3f7SAlexander Motin .args = NULL, 71f634b4c1SWarner Losh }; 72f634b4c1SWarner Losh 73f634b4c1SWarner Losh CMD_COMMAND(ns_cmd); 74f634b4c1SWarner Losh 753b3dd3f7SAlexander Motin static struct active_options { 763b3dd3f7SAlexander Motin const char *dev; 773b3dd3f7SAlexander Motin } active_opt = { 783b3dd3f7SAlexander Motin .dev = NULL, 793b3dd3f7SAlexander Motin }; 803b3dd3f7SAlexander Motin 813b3dd3f7SAlexander Motin static const struct args active_args[] = { 823b3dd3f7SAlexander Motin { arg_string, &active_opt.dev, "controller-id" }, 833b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 843b3dd3f7SAlexander Motin }; 853b3dd3f7SAlexander Motin 863b3dd3f7SAlexander Motin static struct cmd active_cmd = { 873b3dd3f7SAlexander Motin .name = "active", 883b3dd3f7SAlexander Motin .fn = nsactive, 893b3dd3f7SAlexander Motin .descr = "List active (attached) namespaces", 903b3dd3f7SAlexander Motin .ctx_size = sizeof(active_opt), 913b3dd3f7SAlexander Motin .opts = NULL, 923b3dd3f7SAlexander Motin .args = active_args, 933b3dd3f7SAlexander Motin }; 943b3dd3f7SAlexander Motin 953b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, active_cmd); 963b3dd3f7SAlexander Motin 973b3dd3f7SAlexander Motin static struct cmd allocated_cmd = { 983b3dd3f7SAlexander Motin .name = "allocated", 993b3dd3f7SAlexander Motin .fn = nsallocated, 1003b3dd3f7SAlexander Motin .descr = "List allocated (created) namespaces", 1013b3dd3f7SAlexander Motin .ctx_size = sizeof(active_opt), 1023b3dd3f7SAlexander Motin .opts = NULL, 1033b3dd3f7SAlexander Motin .args = active_args, 1043b3dd3f7SAlexander Motin }; 1053b3dd3f7SAlexander Motin 1063b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, allocated_cmd); 1073b3dd3f7SAlexander Motin 1083b3dd3f7SAlexander Motin static struct controllers_options { 1093b3dd3f7SAlexander Motin const char *dev; 1103b3dd3f7SAlexander Motin } controllers_opt = { 1113b3dd3f7SAlexander Motin .dev = NULL, 1123b3dd3f7SAlexander Motin }; 1133b3dd3f7SAlexander Motin 1143b3dd3f7SAlexander Motin static const struct args controllers_args[] = { 1153b3dd3f7SAlexander Motin { arg_string, &controllers_opt.dev, "controller-id" }, 1163b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 1173b3dd3f7SAlexander Motin }; 1183b3dd3f7SAlexander Motin 1193b3dd3f7SAlexander Motin static struct cmd controllers_cmd = { 1203b3dd3f7SAlexander Motin .name = "controllers", 1213b3dd3f7SAlexander Motin .fn = nscontrollers, 1223b3dd3f7SAlexander Motin .descr = "List all controllers in NVM subsystem", 1233b3dd3f7SAlexander Motin .ctx_size = sizeof(controllers_opt), 1243b3dd3f7SAlexander Motin .opts = NULL, 1253b3dd3f7SAlexander Motin .args = controllers_args, 1263b3dd3f7SAlexander Motin }; 1273b3dd3f7SAlexander Motin 1283b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, controllers_cmd); 1293b3dd3f7SAlexander Motin 130f634b4c1SWarner Losh static struct create_options { 131f634b4c1SWarner Losh uint64_t nsze; 132f634b4c1SWarner Losh uint64_t cap; 133f634b4c1SWarner Losh uint32_t lbaf; 134f634b4c1SWarner Losh uint32_t mset; 135f634b4c1SWarner Losh uint32_t nmic; 136f634b4c1SWarner Losh uint32_t pi; 137f634b4c1SWarner Losh uint32_t pil; 138f634b4c1SWarner Losh uint32_t flbas; 139f634b4c1SWarner Losh uint32_t dps; 140f634b4c1SWarner Losh // uint32_t block_size; 141f634b4c1SWarner Losh const char *dev; 142f634b4c1SWarner Losh } create_opt = { 143f634b4c1SWarner Losh .nsze = NONE64, 144f634b4c1SWarner Losh .cap = NONE64, 145f634b4c1SWarner Losh .lbaf = NONE, 146f634b4c1SWarner Losh .mset = NONE, 147f634b4c1SWarner Losh .nmic = NONE, 148f634b4c1SWarner Losh .pi = NONE, 149f634b4c1SWarner Losh .pil = NONE, 150f634b4c1SWarner Losh .flbas = NONE, 151f634b4c1SWarner Losh .dps = NONE, 152f634b4c1SWarner Losh .dev = NULL, 153f634b4c1SWarner Losh // .block_size = NONE, 154f634b4c1SWarner Losh }; 155f634b4c1SWarner Losh 156f634b4c1SWarner Losh static const struct opts create_opts[] = { 157f634b4c1SWarner Losh OPT("nsze", 's', arg_uint64, create_opt, nsze, 158f634b4c1SWarner Losh "The namespace size"), 159f634b4c1SWarner Losh OPT("ncap", 'c', arg_uint64, create_opt, cap, 160f634b4c1SWarner Losh "The capacity of the namespace (<= ns size)"), 161f634b4c1SWarner Losh OPT("lbaf", 'f', arg_uint32, create_opt, lbaf, 162f634b4c1SWarner Losh "The FMT field of the FLBAS"), 163f634b4c1SWarner Losh OPT("mset", 'm', arg_uint32, create_opt, mset, 164f634b4c1SWarner Losh "The MSET field of the FLBAS"), 165f634b4c1SWarner Losh OPT("nmic", 'n', arg_uint32, create_opt, nmic, 166f634b4c1SWarner Losh "Namespace multipath and sharing capabilities"), 167f634b4c1SWarner Losh OPT("pi", 'p', arg_uint32, create_opt, pi, 168f634b4c1SWarner Losh "PI field of FLBAS"), 169f634b4c1SWarner Losh OPT("pil", 'l', arg_uint32, create_opt, pil, 170f634b4c1SWarner Losh "PIL field of FLBAS"), 1713b3dd3f7SAlexander Motin OPT("flbas", 'L', arg_uint32, create_opt, flbas, 172f634b4c1SWarner Losh "Namespace formatted logical block size setting"), 173f634b4c1SWarner Losh OPT("dps", 'd', arg_uint32, create_opt, dps, 174f634b4c1SWarner Losh "Data protection settings"), 175f634b4c1SWarner Losh // OPT("block-size", 'b', arg_uint32, create_opt, block_size, 176f634b4c1SWarner Losh // "Blocksize of the namespace"), 177f634b4c1SWarner Losh OPT_END 178f634b4c1SWarner Losh }; 179f634b4c1SWarner Losh 180f634b4c1SWarner Losh static const struct args create_args[] = { 181f634b4c1SWarner Losh { arg_string, &create_opt.dev, "controller-id" }, 182f634b4c1SWarner Losh { arg_none, NULL, NULL }, 183f634b4c1SWarner Losh }; 184f634b4c1SWarner Losh 185f634b4c1SWarner Losh static struct cmd create_cmd = { 186f634b4c1SWarner Losh .name = "create", 187f634b4c1SWarner Losh .fn = nscreate, 1883b3dd3f7SAlexander Motin .descr = "Create a namespace", 189f634b4c1SWarner Losh .ctx_size = sizeof(create_opt), 190f634b4c1SWarner Losh .opts = create_opts, 191f634b4c1SWarner Losh .args = create_args, 192f634b4c1SWarner Losh }; 193f634b4c1SWarner Losh 194f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, create_cmd); 195f634b4c1SWarner Losh 196f634b4c1SWarner Losh static struct delete_options { 197f634b4c1SWarner Losh uint32_t nsid; 198f634b4c1SWarner Losh const char *dev; 199f634b4c1SWarner Losh } delete_opt = { 200f634b4c1SWarner Losh .nsid = NONE, 201f634b4c1SWarner Losh .dev = NULL, 202f634b4c1SWarner Losh }; 203f634b4c1SWarner Losh 204f634b4c1SWarner Losh static const struct opts delete_opts[] = { 205f634b4c1SWarner Losh OPT("namespace-id", 'n', arg_uint32, delete_opt, nsid, 206f634b4c1SWarner Losh "The namespace ID to delete"), 207f634b4c1SWarner Losh OPT_END 208f634b4c1SWarner Losh }; 209f634b4c1SWarner Losh 210f634b4c1SWarner Losh static const struct args delete_args[] = { 211f634b4c1SWarner Losh { arg_string, &delete_opt.dev, "controller-id" }, 212f634b4c1SWarner Losh { arg_none, NULL, NULL }, 213f634b4c1SWarner Losh }; 214f634b4c1SWarner Losh 215f634b4c1SWarner Losh static struct cmd delete_cmd = { 216f634b4c1SWarner Losh .name = "delete", 217f634b4c1SWarner Losh .fn = nsdelete, 2183b3dd3f7SAlexander Motin .descr = "Delete a namespace", 219f634b4c1SWarner Losh .ctx_size = sizeof(delete_opt), 220f634b4c1SWarner Losh .opts = delete_opts, 221f634b4c1SWarner Losh .args = delete_args, 222f634b4c1SWarner Losh }; 223f634b4c1SWarner Losh 224f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, delete_cmd); 225f634b4c1SWarner Losh 226f634b4c1SWarner Losh static struct attach_options { 227f634b4c1SWarner Losh uint32_t nsid; 228f634b4c1SWarner Losh uint32_t ctrlrid; 229f634b4c1SWarner Losh const char *dev; 230f634b4c1SWarner Losh } attach_opt = { 231f634b4c1SWarner Losh .nsid = NONE, 232f634b4c1SWarner Losh .ctrlrid = NONE - 1, 233f634b4c1SWarner Losh .dev = NULL, 234f634b4c1SWarner Losh }; 235f634b4c1SWarner Losh 236f634b4c1SWarner Losh static const struct opts attach_opts[] = { 237f634b4c1SWarner Losh OPT("namespace-id", 'n', arg_uint32, attach_opt, nsid, 238f634b4c1SWarner Losh "The namespace ID to attach"), 2393b3dd3f7SAlexander Motin OPT("controller", 'c', arg_uint32, attach_opt, ctrlrid, 240f634b4c1SWarner Losh "The controller ID to attach"), 241f634b4c1SWarner Losh OPT_END 242f634b4c1SWarner Losh }; 243f634b4c1SWarner Losh 244f634b4c1SWarner Losh static const struct args attach_args[] = { 245f634b4c1SWarner Losh { arg_string, &attach_opt.dev, "controller-id" }, 246f634b4c1SWarner Losh { arg_none, NULL, NULL }, 247f634b4c1SWarner Losh }; 248f634b4c1SWarner Losh 249f634b4c1SWarner Losh static struct cmd attach_cmd = { 250f634b4c1SWarner Losh .name = "attach", 251f634b4c1SWarner Losh .fn = nsattach, 2523b3dd3f7SAlexander Motin .descr = "Attach a controller to a namespace", 253f634b4c1SWarner Losh .ctx_size = sizeof(attach_opt), 254f634b4c1SWarner Losh .opts = attach_opts, 255f634b4c1SWarner Losh .args = attach_args, 256f634b4c1SWarner Losh }; 257f634b4c1SWarner Losh 258f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, attach_cmd); 259f634b4c1SWarner Losh 2603b3dd3f7SAlexander Motin static struct attached_options { 2613b3dd3f7SAlexander Motin uint32_t nsid; 2623b3dd3f7SAlexander Motin const char *dev; 2633b3dd3f7SAlexander Motin } attached_opt = { 2643b3dd3f7SAlexander Motin .nsid = NONE, 2653b3dd3f7SAlexander Motin .dev = NULL, 2663b3dd3f7SAlexander Motin }; 2673b3dd3f7SAlexander Motin 2683b3dd3f7SAlexander Motin static const struct opts attached_opts[] = { 2693b3dd3f7SAlexander Motin OPT("namespace-id", 'n', arg_uint32, attached_opt, nsid, 2703b3dd3f7SAlexander Motin "The namespace ID to request attached controllers"), 2713b3dd3f7SAlexander Motin OPT_END 2723b3dd3f7SAlexander Motin }; 2733b3dd3f7SAlexander Motin 2743b3dd3f7SAlexander Motin static const struct args attached_args[] = { 2753b3dd3f7SAlexander Motin { arg_string, &attached_opt.dev, "controller-id" }, 2763b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 2773b3dd3f7SAlexander Motin }; 2783b3dd3f7SAlexander Motin 2793b3dd3f7SAlexander Motin static struct cmd attached_cmd = { 2803b3dd3f7SAlexander Motin .name = "attached", 2813b3dd3f7SAlexander Motin .fn = nsattached, 2823b3dd3f7SAlexander Motin .descr = "List controllers attached to a namespace", 2833b3dd3f7SAlexander Motin .ctx_size = sizeof(attached_opt), 2843b3dd3f7SAlexander Motin .opts = attached_opts, 2853b3dd3f7SAlexander Motin .args = attached_args, 2863b3dd3f7SAlexander Motin }; 2873b3dd3f7SAlexander Motin 2883b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, attached_cmd); 2893b3dd3f7SAlexander Motin 290f634b4c1SWarner Losh static struct detach_options { 291f634b4c1SWarner Losh uint32_t nsid; 292f634b4c1SWarner Losh uint32_t ctrlrid; 293f634b4c1SWarner Losh const char *dev; 294f634b4c1SWarner Losh } detach_opt = { 295f634b4c1SWarner Losh .nsid = NONE, 296f634b4c1SWarner Losh .ctrlrid = NONE - 1, 297f634b4c1SWarner Losh .dev = NULL, 298f634b4c1SWarner Losh }; 299f634b4c1SWarner Losh 300f634b4c1SWarner Losh static const struct opts detach_opts[] = { 301f634b4c1SWarner Losh OPT("namespace-id", 'n', arg_uint32, detach_opt, nsid, 302f634b4c1SWarner Losh "The namespace ID to detach"), 3033b3dd3f7SAlexander Motin OPT("controller", 'c', arg_uint32, detach_opt, ctrlrid, 304f634b4c1SWarner Losh "The controller ID to detach"), 305f634b4c1SWarner Losh OPT_END 306f634b4c1SWarner Losh }; 307f634b4c1SWarner Losh 308f634b4c1SWarner Losh static const struct args detach_args[] = { 309f634b4c1SWarner Losh { arg_string, &detach_opt.dev, "controller-id" }, 310f634b4c1SWarner Losh { arg_none, NULL, NULL }, 311f634b4c1SWarner Losh }; 312f634b4c1SWarner Losh 313f634b4c1SWarner Losh static struct cmd detach_cmd = { 314f634b4c1SWarner Losh .name = "detach", 315f634b4c1SWarner Losh .fn = nsdetach, 3163b3dd3f7SAlexander Motin .descr = "Detach a controller from a namespace", 317f634b4c1SWarner Losh .ctx_size = sizeof(detach_opt), 318f634b4c1SWarner Losh .opts = detach_opts, 319f634b4c1SWarner Losh .args = detach_args, 320f634b4c1SWarner Losh }; 321f634b4c1SWarner Losh 322f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, detach_cmd); 323a13a291aSWarner Losh 3243b3dd3f7SAlexander Motin static struct identify_options { 3253b3dd3f7SAlexander Motin bool hex; 3263b3dd3f7SAlexander Motin bool verbose; 3273b3dd3f7SAlexander Motin const char *dev; 3283b3dd3f7SAlexander Motin uint32_t nsid; 3293b3dd3f7SAlexander Motin } identify_opt = { 3303b3dd3f7SAlexander Motin .hex = false, 3313b3dd3f7SAlexander Motin .verbose = false, 3323b3dd3f7SAlexander Motin .dev = NULL, 3333b3dd3f7SAlexander Motin .nsid = NONE, 3343b3dd3f7SAlexander Motin }; 3353b3dd3f7SAlexander Motin 3363b3dd3f7SAlexander Motin static const struct opts identify_opts[] = { 3373b3dd3f7SAlexander Motin OPT("hex", 'x', arg_none, identify_opt, hex, 3383b3dd3f7SAlexander Motin "Print identiy information in hex"), 3393b3dd3f7SAlexander Motin OPT("verbose", 'v', arg_none, identify_opt, verbose, 3403b3dd3f7SAlexander Motin "More verbosity: print entire identify table"), 3413b3dd3f7SAlexander Motin OPT("nsid", 'n', arg_uint32, identify_opt, nsid, 3423b3dd3f7SAlexander Motin "The namespace ID to print IDENTIFY for"), 3433b3dd3f7SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 3443b3dd3f7SAlexander Motin }; 3453b3dd3f7SAlexander Motin 3463b3dd3f7SAlexander Motin static const struct args identify_args[] = { 3473b3dd3f7SAlexander Motin { arg_string, &identify_opt.dev, "controller-id" }, 3483b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 3493b3dd3f7SAlexander Motin }; 3503b3dd3f7SAlexander Motin 3513b3dd3f7SAlexander Motin static struct cmd identify_cmd = { 3523b3dd3f7SAlexander Motin .name = "identify", 3533b3dd3f7SAlexander Motin .fn = nsidentify, 3543b3dd3f7SAlexander Motin .descr = "Print IDENTIFY for allocated namespace", 3553b3dd3f7SAlexander Motin .ctx_size = sizeof(identify_opt), 3563b3dd3f7SAlexander Motin .opts = identify_opts, 3573b3dd3f7SAlexander Motin .args = identify_args, 3583b3dd3f7SAlexander Motin }; 3593b3dd3f7SAlexander Motin 3603b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, identify_cmd); 361a13a291aSWarner Losh 362ba405bc8SAlexander Motin /* handles NVME_OPC_NAMESPACE_MANAGEMENT and ATTACHMENT admin cmds */ 363ba405bc8SAlexander Motin 364ba405bc8SAlexander Motin struct ns_result_str { 365ba405bc8SAlexander Motin uint16_t res; 366ba405bc8SAlexander Motin const char * str; 367ba405bc8SAlexander Motin }; 368ba405bc8SAlexander Motin 369ba405bc8SAlexander Motin static struct ns_result_str ns_result[] = { 370ba405bc8SAlexander Motin { 0x2, "Invalid Field"}, 371ba405bc8SAlexander Motin { 0xa, "Invalid Format"}, 372ba405bc8SAlexander Motin { 0xb, "Invalid Namespace or format"}, 373ba405bc8SAlexander Motin { 0x15, "Namespace insufficent capacity"}, 374ba405bc8SAlexander Motin { 0x16, "Namespace ID unavaliable"}, 375ba405bc8SAlexander Motin { 0x18, "Namespace already attached"}, 376ba405bc8SAlexander Motin { 0x19, "Namespace is private"}, 377ba405bc8SAlexander Motin { 0x1a, "Namespace is not attached"}, 378ba405bc8SAlexander Motin { 0x1b, "Thin provisioning not supported"}, 379ba405bc8SAlexander Motin { 0x1c, "Controller list invalid"}, 3803b3dd3f7SAlexander Motin { 0x24, "ANA Group Identifier Invalid"}, 3813b3dd3f7SAlexander Motin { 0x25, "ANA Attach Failed"}, 382ba405bc8SAlexander Motin { 0xFFFF, "Unknown"} 383ba405bc8SAlexander Motin }; 384ba405bc8SAlexander Motin 385ba405bc8SAlexander Motin static const char * 386ba405bc8SAlexander Motin get_res_str(uint16_t res) 387ba405bc8SAlexander Motin { 388ba405bc8SAlexander Motin struct ns_result_str *t = ns_result; 389ba405bc8SAlexander Motin 390ba405bc8SAlexander Motin while (t->res != 0xFFFF) { 391ba405bc8SAlexander Motin if (t->res == res) 392ba405bc8SAlexander Motin return (t->str); 393ba405bc8SAlexander Motin t++; 394ba405bc8SAlexander Motin } 395ba405bc8SAlexander Motin return t->str; 396ba405bc8SAlexander Motin } 397ba405bc8SAlexander Motin 3983b3dd3f7SAlexander Motin static void 3993b3dd3f7SAlexander Motin nsactive(const struct cmd *f, int argc, char *argv[]) 4003b3dd3f7SAlexander Motin { 4013b3dd3f7SAlexander Motin struct nvme_pt_command pt; 4023b3dd3f7SAlexander Motin int fd, i; 4033b3dd3f7SAlexander Motin uint32_t list[1024]; 4043b3dd3f7SAlexander Motin 4053b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 4063b3dd3f7SAlexander Motin return; 4073b3dd3f7SAlexander Motin open_dev(active_opt.dev, &fd, 1, 1); 4083b3dd3f7SAlexander Motin 4093b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 4103b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 4113b3dd3f7SAlexander Motin pt.cmd.nsid = htole32(0); 4123b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x02); 4133b3dd3f7SAlexander Motin pt.buf = list; 4143b3dd3f7SAlexander Motin pt.len = sizeof(list); 4153b3dd3f7SAlexander Motin pt.is_read = 1; 4163b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 4173b3dd3f7SAlexander Motin err(1, "identify request failed"); 4183b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 4193b3dd3f7SAlexander Motin errx(1, "identify request returned error"); 4203b3dd3f7SAlexander Motin 4213b3dd3f7SAlexander Motin printf("Active namespaces:\n"); 4223b3dd3f7SAlexander Motin for (i = 0; list[i] != 0; i++) 4233b3dd3f7SAlexander Motin printf("%10d\n", le32toh(list[i])); 4243b3dd3f7SAlexander Motin 4253b3dd3f7SAlexander Motin exit(0); 4263b3dd3f7SAlexander Motin } 4273b3dd3f7SAlexander Motin 4283b3dd3f7SAlexander Motin static void 4293b3dd3f7SAlexander Motin nsallocated(const struct cmd *f, int argc, char *argv[]) 4303b3dd3f7SAlexander Motin { 4313b3dd3f7SAlexander Motin struct nvme_pt_command pt; 4323b3dd3f7SAlexander Motin struct nvme_controller_data cd; 4333b3dd3f7SAlexander Motin int fd, i; 4343b3dd3f7SAlexander Motin uint32_t list[1024]; 4353b3dd3f7SAlexander Motin 4363b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 4373b3dd3f7SAlexander Motin return; 4383b3dd3f7SAlexander Motin open_dev(active_opt.dev, &fd, 1, 1); 4393b3dd3f7SAlexander Motin read_controller_data(fd, &cd); 4403b3dd3f7SAlexander Motin 4413b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 4423b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 4433b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 4443b3dd3f7SAlexander Motin errx(1, "controller does not support namespace management"); 4453b3dd3f7SAlexander Motin 4463b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 4473b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 4483b3dd3f7SAlexander Motin pt.cmd.nsid = htole32(0); 4493b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x10); 4503b3dd3f7SAlexander Motin pt.buf = list; 4513b3dd3f7SAlexander Motin pt.len = sizeof(list); 4523b3dd3f7SAlexander Motin pt.is_read = 1; 4533b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 4543b3dd3f7SAlexander Motin err(1, "identify request failed"); 4553b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 4563b3dd3f7SAlexander Motin errx(1, "identify request returned error"); 4573b3dd3f7SAlexander Motin 4583b3dd3f7SAlexander Motin printf("Allocated namespaces:\n"); 4593b3dd3f7SAlexander Motin for (i = 0; list[i] != 0; i++) 4603b3dd3f7SAlexander Motin printf("%10d\n", le32toh(list[i])); 4613b3dd3f7SAlexander Motin 4623b3dd3f7SAlexander Motin exit(0); 4633b3dd3f7SAlexander Motin } 4643b3dd3f7SAlexander Motin 4653b3dd3f7SAlexander Motin static void 4663b3dd3f7SAlexander Motin nscontrollers(const struct cmd *f, int argc, char *argv[]) 4673b3dd3f7SAlexander Motin { 4683b3dd3f7SAlexander Motin struct nvme_pt_command pt; 4693b3dd3f7SAlexander Motin struct nvme_controller_data cd; 4703b3dd3f7SAlexander Motin int fd, i, n; 4713b3dd3f7SAlexander Motin uint16_t clist[2048]; 4723b3dd3f7SAlexander Motin 4733b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 4743b3dd3f7SAlexander Motin return; 4753b3dd3f7SAlexander Motin open_dev(controllers_opt.dev, &fd, 1, 1); 4763b3dd3f7SAlexander Motin read_controller_data(fd, &cd); 4773b3dd3f7SAlexander Motin 4783b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 4793b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 4803b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 4813b3dd3f7SAlexander Motin errx(1, "controller does not support namespace management"); 4823b3dd3f7SAlexander Motin 4833b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 4843b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 4853b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x13); 4863b3dd3f7SAlexander Motin pt.buf = clist; 4873b3dd3f7SAlexander Motin pt.len = sizeof(clist); 4883b3dd3f7SAlexander Motin pt.is_read = 1; 4893b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 4903b3dd3f7SAlexander Motin err(1, "identify request failed"); 4913b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 4923b3dd3f7SAlexander Motin errx(1, "identify request returned error"); 4933b3dd3f7SAlexander Motin 4943b3dd3f7SAlexander Motin n = le16toh(clist[0]); 4953b3dd3f7SAlexander Motin printf("NVM subsystem includes %d controller(s):\n", n); 4963b3dd3f7SAlexander Motin for (i = 0; i < n; i++) 4973b3dd3f7SAlexander Motin printf(" 0x%04x\n", le16toh(clist[i + 1])); 4983b3dd3f7SAlexander Motin 4993b3dd3f7SAlexander Motin exit(0); 5003b3dd3f7SAlexander Motin } 5013b3dd3f7SAlexander Motin 502ba405bc8SAlexander Motin /* 503ba405bc8SAlexander Motin * NS MGMT Command specific status values: 504ba405bc8SAlexander Motin * 0xa = Invalid Format 505ba405bc8SAlexander Motin * 0x15 = Namespace Insuffience capacity 506ba405bc8SAlexander Motin * 0x16 = Namespace ID unavailable (number namespaces exceeded) 507ba405bc8SAlexander Motin * 0xb = Thin Provisioning Not supported 508ba405bc8SAlexander Motin */ 5090d095c23SWarner Losh static void 510f634b4c1SWarner Losh nscreate(const struct cmd *f, int argc, char *argv[]) 511ba405bc8SAlexander Motin { 512ba405bc8SAlexander Motin struct nvme_pt_command pt; 513ba405bc8SAlexander Motin struct nvme_controller_data cd; 514ba405bc8SAlexander Motin struct nvme_namespace_data nsdata; 515f634b4c1SWarner Losh int fd, result; 516ba405bc8SAlexander Motin 517f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 518f634b4c1SWarner Losh return; 519ba405bc8SAlexander Motin 520f634b4c1SWarner Losh if (create_opt.cap == NONE64) 521f634b4c1SWarner Losh create_opt.cap = create_opt.nsze; 522f634b4c1SWarner Losh if (create_opt.nsze == NONE64) { 523f634b4c1SWarner Losh fprintf(stderr, 524f634b4c1SWarner Losh "Size not specified\n"); 525f634b4c1SWarner Losh arg_help(argc, argv, f); 526ba405bc8SAlexander Motin } 527ba405bc8SAlexander Motin 528f634b4c1SWarner Losh open_dev(create_opt.dev, &fd, 1, 1); 529ba405bc8SAlexander Motin read_controller_data(fd, &cd); 530ba405bc8SAlexander Motin 531ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 532ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 533ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 534ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 535ba405bc8SAlexander Motin 536ba405bc8SAlexander Motin /* Allow namespaces sharing if Multi-Path I/O is supported. */ 537f634b4c1SWarner Losh if (create_opt.nmic == NONE) { 538f634b4c1SWarner Losh create_opt.nmic = cd.mic ? (NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK << 539ba405bc8SAlexander Motin NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) : 0; 540ba405bc8SAlexander Motin } 541ba405bc8SAlexander Motin 542ba405bc8SAlexander Motin memset(&nsdata, 0, sizeof(nsdata)); 543f634b4c1SWarner Losh nsdata.nsze = create_opt.nsze; 544f634b4c1SWarner Losh nsdata.ncap = create_opt.cap; 545f634b4c1SWarner Losh if (create_opt.flbas == NONE) 546f634b4c1SWarner Losh nsdata.flbas = ((create_opt.lbaf & NVME_NS_DATA_FLBAS_FORMAT_MASK) 547ba405bc8SAlexander Motin << NVME_NS_DATA_FLBAS_FORMAT_SHIFT) | 548f634b4c1SWarner Losh ((create_opt.mset & NVME_NS_DATA_FLBAS_EXTENDED_MASK) 549ba405bc8SAlexander Motin << NVME_NS_DATA_FLBAS_EXTENDED_SHIFT); 550f634b4c1SWarner Losh else 551f634b4c1SWarner Losh nsdata.flbas = create_opt.flbas; 552f634b4c1SWarner Losh if (create_opt.dps == NONE) 553f634b4c1SWarner Losh nsdata.dps = ((create_opt.pi & NVME_NS_DATA_DPS_MD_START_MASK) 554ba405bc8SAlexander Motin << NVME_NS_DATA_DPS_MD_START_SHIFT) | 555f634b4c1SWarner Losh ((create_opt.pil & NVME_NS_DATA_DPS_PIT_MASK) 556ba405bc8SAlexander Motin << NVME_NS_DATA_DPS_PIT_SHIFT); 557f634b4c1SWarner Losh else 558f634b4c1SWarner Losh nsdata.dps = create_opt.dps; 559f634b4c1SWarner Losh nsdata.nmic = create_opt.nmic; 560ba405bc8SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 561ba405bc8SAlexander Motin 562ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 5639544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 5643b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0); /* create */ 565ba405bc8SAlexander Motin pt.buf = &nsdata; 566ba405bc8SAlexander Motin pt.len = sizeof(struct nvme_namespace_data); 567ba405bc8SAlexander Motin pt.is_read = 0; /* passthrough writes data to ctrlr */ 568ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 569ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 570ba405bc8SAlexander Motin 571ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 572ba405bc8SAlexander Motin errx(1, "namespace creation failed: %s", 573ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 574ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 575ba405bc8SAlexander Motin } 576ba405bc8SAlexander Motin printf("namespace %d created\n", pt.cpl.cdw0); 577ba405bc8SAlexander Motin exit(0); 578ba405bc8SAlexander Motin } 579ba405bc8SAlexander Motin 5800d095c23SWarner Losh static void 581f634b4c1SWarner Losh nsdelete(const struct cmd *f, int argc, char *argv[]) 582ba405bc8SAlexander Motin { 583ba405bc8SAlexander Motin struct nvme_pt_command pt; 584ba405bc8SAlexander Motin struct nvme_controller_data cd; 585f634b4c1SWarner Losh int fd, result; 586ba405bc8SAlexander Motin char buf[2]; 587ba405bc8SAlexander Motin 588f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 589f634b4c1SWarner Losh return; 590f634b4c1SWarner Losh if (delete_opt.nsid == NONE) { 591f634b4c1SWarner Losh fprintf(stderr, 592f634b4c1SWarner Losh "No NSID specified"); 593f634b4c1SWarner Losh arg_help(argc, argv, f); 594ba405bc8SAlexander Motin } 595ba405bc8SAlexander Motin 596f634b4c1SWarner Losh open_dev(delete_opt.dev, &fd, 1, 1); 597ba405bc8SAlexander Motin read_controller_data(fd, &cd); 598ba405bc8SAlexander Motin 599ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 600ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 601ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 602ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 603ba405bc8SAlexander Motin 604ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 6059544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 6063b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(1); /* delete */ 607ba405bc8SAlexander Motin pt.buf = buf; 608ba405bc8SAlexander Motin pt.len = sizeof(buf); 609ba405bc8SAlexander Motin pt.is_read = 1; 610f634b4c1SWarner Losh pt.cmd.nsid = delete_opt.nsid; 611ba405bc8SAlexander Motin 612ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 613f634b4c1SWarner Losh errx(1, "ioctl request to %s failed: %d", delete_opt.dev, result); 614ba405bc8SAlexander Motin 615ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 616ba405bc8SAlexander Motin errx(1, "namespace deletion failed: %s", 617ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 618ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 619ba405bc8SAlexander Motin } 620f634b4c1SWarner Losh printf("namespace %d deleted\n", delete_opt.nsid); 621ba405bc8SAlexander Motin exit(0); 622ba405bc8SAlexander Motin } 623ba405bc8SAlexander Motin 624ba405bc8SAlexander Motin /* 625ba405bc8SAlexander Motin * Attach and Detach use Dword 10, and a controller list (section 4.9) 626ba405bc8SAlexander Motin * This struct is 4096 bytes in size. 627ba405bc8SAlexander Motin * 0h = attach 628ba405bc8SAlexander Motin * 1h = detach 629ba405bc8SAlexander Motin * 630ba405bc8SAlexander Motin * Result values for both attach/detach: 631ba405bc8SAlexander Motin * 632ba405bc8SAlexander Motin * Completion 18h = Already attached 633ba405bc8SAlexander Motin * 19h = NS is private and already attached to a controller 634ba405bc8SAlexander Motin * 1Ah = Not attached, request could not be completed 635ba405bc8SAlexander Motin * 1Ch = Controller list invalid. 636ba405bc8SAlexander Motin * 637ba405bc8SAlexander Motin * 0x2 Invalid Field can occur if ctrlrid d.n.e in system. 638ba405bc8SAlexander Motin */ 6390d095c23SWarner Losh static void 640f634b4c1SWarner Losh nsattach(const struct cmd *f, int argc, char *argv[]) 641ba405bc8SAlexander Motin { 642ba405bc8SAlexander Motin struct nvme_pt_command pt; 643ba405bc8SAlexander Motin struct nvme_controller_data cd; 644f634b4c1SWarner Losh int fd, result; 645ba405bc8SAlexander Motin uint16_t clist[2048]; 646ba405bc8SAlexander Motin 647f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 648f634b4c1SWarner Losh return; 649f634b4c1SWarner Losh if (attach_opt.nsid == NONE) { 650f634b4c1SWarner Losh fprintf(stderr, "No valid NSID specified\n"); 651f634b4c1SWarner Losh arg_help(argc, argv, f); 652ba405bc8SAlexander Motin } 653f634b4c1SWarner Losh open_dev(attach_opt.dev, &fd, 1, 1); 654ba405bc8SAlexander Motin read_controller_data(fd, &cd); 655ba405bc8SAlexander Motin 656ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 657ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 658ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 659ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 660ba405bc8SAlexander Motin 661f634b4c1SWarner Losh if (attach_opt.ctrlrid == NONE) { 662ba405bc8SAlexander Motin /* Get full list of controllers to attach to. */ 663ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 6649544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 665ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x13); 666ba405bc8SAlexander Motin pt.buf = clist; 667ba405bc8SAlexander Motin pt.len = sizeof(clist); 668ba405bc8SAlexander Motin pt.is_read = 1; 669ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 670ba405bc8SAlexander Motin err(1, "identify request failed"); 671ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 672ba405bc8SAlexander Motin errx(1, "identify request returned error"); 673ba405bc8SAlexander Motin } else { 674ba405bc8SAlexander Motin /* By default attach to this controller. */ 675f634b4c1SWarner Losh if (attach_opt.ctrlrid == NONE - 1) 676f634b4c1SWarner Losh attach_opt.ctrlrid = cd.ctrlr_id; 677ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 678ba405bc8SAlexander Motin clist[0] = htole16(1); 679f634b4c1SWarner Losh clist[1] = htole16(attach_opt.ctrlrid); 680ba405bc8SAlexander Motin } 681ba405bc8SAlexander Motin 682ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 6839544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 6843b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0); /* attach */ 685f634b4c1SWarner Losh pt.cmd.nsid = attach_opt.nsid; 686ba405bc8SAlexander Motin pt.buf = &clist; 687ba405bc8SAlexander Motin pt.len = sizeof(clist); 688ba405bc8SAlexander Motin 689ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 690f634b4c1SWarner Losh errx(1, "ioctl request to %s failed: %d", attach_opt.dev, result); 691ba405bc8SAlexander Motin 692ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 693ba405bc8SAlexander Motin errx(1, "namespace attach failed: %s", 694ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 695ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 696ba405bc8SAlexander Motin } 697f634b4c1SWarner Losh printf("namespace %d attached\n", attach_opt.nsid); 698ba405bc8SAlexander Motin exit(0); 699ba405bc8SAlexander Motin } 700ba405bc8SAlexander Motin 7010d095c23SWarner Losh static void 702f634b4c1SWarner Losh nsdetach(const struct cmd *f, int argc, char *argv[]) 703ba405bc8SAlexander Motin { 704ba405bc8SAlexander Motin struct nvme_pt_command pt; 705ba405bc8SAlexander Motin struct nvme_controller_data cd; 706f634b4c1SWarner Losh int fd, result; 707ba405bc8SAlexander Motin uint16_t clist[2048]; 708ba405bc8SAlexander Motin 709f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 710f634b4c1SWarner Losh return; 7113b3dd3f7SAlexander Motin if (detach_opt.nsid == NONE) { 712f634b4c1SWarner Losh fprintf(stderr, "No valid NSID specified\n"); 713f634b4c1SWarner Losh arg_help(argc, argv, f); 714ba405bc8SAlexander Motin } 7153b3dd3f7SAlexander Motin open_dev(detach_opt.dev, &fd, 1, 1); 716ba405bc8SAlexander Motin read_controller_data(fd, &cd); 717ba405bc8SAlexander Motin 718ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 719ba405bc8SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 720ba405bc8SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 721ba405bc8SAlexander Motin errx(1, "controller does not support namespace management"); 722ba405bc8SAlexander Motin 723f634b4c1SWarner Losh if (detach_opt.ctrlrid == NONE) { 724ba405bc8SAlexander Motin /* Get list of controllers this namespace attached to. */ 725ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 7269544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 727f634b4c1SWarner Losh pt.cmd.nsid = htole32(detach_opt.nsid); 728ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 729ba405bc8SAlexander Motin pt.buf = clist; 730ba405bc8SAlexander Motin pt.len = sizeof(clist); 731ba405bc8SAlexander Motin pt.is_read = 1; 732ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 733ba405bc8SAlexander Motin err(1, "identify request failed"); 734ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 735ba405bc8SAlexander Motin errx(1, "identify request returned error"); 736ba405bc8SAlexander Motin if (clist[0] == 0) { 737f634b4c1SWarner Losh detach_opt.ctrlrid = cd.ctrlr_id; 738ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 739ba405bc8SAlexander Motin clist[0] = htole16(1); 740f634b4c1SWarner Losh clist[1] = htole16(detach_opt.ctrlrid); 741ba405bc8SAlexander Motin } 742ba405bc8SAlexander Motin } else { 743ba405bc8SAlexander Motin /* By default detach from this controller. */ 744f634b4c1SWarner Losh if (detach_opt.ctrlrid == NONE - 1) 745f634b4c1SWarner Losh detach_opt.ctrlrid = cd.ctrlr_id; 746ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 747ba405bc8SAlexander Motin clist[0] = htole16(1); 748f634b4c1SWarner Losh clist[1] = htole16(detach_opt.ctrlrid); 749ba405bc8SAlexander Motin } 750ba405bc8SAlexander Motin 751ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 7529544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 7533b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(1); /* detach */ 754f634b4c1SWarner Losh pt.cmd.nsid = detach_opt.nsid; 755ba405bc8SAlexander Motin pt.buf = &clist; 756ba405bc8SAlexander Motin pt.len = sizeof(clist); 757ba405bc8SAlexander Motin 758ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 759ba405bc8SAlexander Motin errx(1, "ioctl request to %s failed: %d", argv[optind], result); 760ba405bc8SAlexander Motin 761ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 762ba405bc8SAlexander Motin errx(1, "namespace detach failed: %s", 763ba405bc8SAlexander Motin get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) & 764ba405bc8SAlexander Motin NVME_STATUS_SC_MASK)); 765ba405bc8SAlexander Motin } 766f634b4c1SWarner Losh printf("namespace %d detached\n", detach_opt.nsid); 767ba405bc8SAlexander Motin exit(0); 768ba405bc8SAlexander Motin } 769ba405bc8SAlexander Motin 770a13a291aSWarner Losh static void 7713b3dd3f7SAlexander Motin nsattached(const struct cmd *f, int argc, char *argv[]) 7723b3dd3f7SAlexander Motin { 7733b3dd3f7SAlexander Motin struct nvme_pt_command pt; 7743b3dd3f7SAlexander Motin struct nvme_controller_data cd; 7753b3dd3f7SAlexander Motin int fd, i, n; 7763b3dd3f7SAlexander Motin uint16_t clist[2048]; 7773b3dd3f7SAlexander Motin 7783b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 7793b3dd3f7SAlexander Motin return; 7803b3dd3f7SAlexander Motin if (attached_opt.nsid == NONE) { 7813b3dd3f7SAlexander Motin fprintf(stderr, "No valid NSID specified\n"); 7823b3dd3f7SAlexander Motin arg_help(argc, argv, f); 7833b3dd3f7SAlexander Motin } 7843b3dd3f7SAlexander Motin open_dev(attached_opt.dev, &fd, 1, 1); 7853b3dd3f7SAlexander Motin read_controller_data(fd, &cd); 7863b3dd3f7SAlexander Motin 7873b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 7883b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 7893b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 7903b3dd3f7SAlexander Motin errx(1, "controller does not support namespace management"); 7913b3dd3f7SAlexander Motin 7923b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 7933b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 7943b3dd3f7SAlexander Motin pt.cmd.nsid = htole32(attached_opt.nsid); 7953b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 7963b3dd3f7SAlexander Motin pt.buf = clist; 7973b3dd3f7SAlexander Motin pt.len = sizeof(clist); 7983b3dd3f7SAlexander Motin pt.is_read = 1; 7993b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 8003b3dd3f7SAlexander Motin err(1, "identify request failed"); 8013b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 8023b3dd3f7SAlexander Motin errx(1, "identify request returned error"); 8033b3dd3f7SAlexander Motin 8043b3dd3f7SAlexander Motin n = le16toh(clist[0]); 8053b3dd3f7SAlexander Motin printf("Attached %d controller(s):\n", n); 8063b3dd3f7SAlexander Motin for (i = 0; i < n; i++) 8073b3dd3f7SAlexander Motin printf(" 0x%04x\n", le16toh(clist[i + 1])); 8083b3dd3f7SAlexander Motin 8093b3dd3f7SAlexander Motin exit(0); 8103b3dd3f7SAlexander Motin } 8113b3dd3f7SAlexander Motin 8123b3dd3f7SAlexander Motin static void 8133b3dd3f7SAlexander Motin nsidentify(const struct cmd *f, int argc, char *argv[]) 8143b3dd3f7SAlexander Motin { 8153b3dd3f7SAlexander Motin struct nvme_pt_command pt; 8163b3dd3f7SAlexander Motin struct nvme_controller_data cd; 8173b3dd3f7SAlexander Motin struct nvme_namespace_data nsdata; 8183b3dd3f7SAlexander Motin uint8_t *data; 8193b3dd3f7SAlexander Motin int fd; 8203b3dd3f7SAlexander Motin u_int i; 8213b3dd3f7SAlexander Motin 8223b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 8233b3dd3f7SAlexander Motin return; 8243b3dd3f7SAlexander Motin if (identify_opt.nsid == NONE) { 8253b3dd3f7SAlexander Motin fprintf(stderr, "No valid NSID specified\n"); 8263b3dd3f7SAlexander Motin arg_help(argc, argv, f); 8273b3dd3f7SAlexander Motin } 8283b3dd3f7SAlexander Motin open_dev(identify_opt.dev, &fd, 1, 1); 8293b3dd3f7SAlexander Motin read_controller_data(fd, &cd); 8303b3dd3f7SAlexander Motin 8313b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 8323b3dd3f7SAlexander Motin if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) & 8333b3dd3f7SAlexander Motin NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0) 8343b3dd3f7SAlexander Motin errx(1, "controller does not support namespace management"); 8353b3dd3f7SAlexander Motin 8363b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 8373b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 8383b3dd3f7SAlexander Motin pt.cmd.nsid = htole32(identify_opt.nsid); 8393b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x11); 8403b3dd3f7SAlexander Motin pt.buf = &nsdata; 8413b3dd3f7SAlexander Motin pt.len = sizeof(nsdata); 8423b3dd3f7SAlexander Motin pt.is_read = 1; 8433b3dd3f7SAlexander Motin 8443b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 8453b3dd3f7SAlexander Motin err(1, "identify request failed"); 8463b3dd3f7SAlexander Motin 8473b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 8483b3dd3f7SAlexander Motin errx(1, "identify request returned error"); 8493b3dd3f7SAlexander Motin 8503b3dd3f7SAlexander Motin close(fd); 8513b3dd3f7SAlexander Motin 8523b3dd3f7SAlexander Motin data = (uint8_t *)&nsdata; 8533b3dd3f7SAlexander Motin for (i = 0; i < sizeof(nsdata); i++) { 8543b3dd3f7SAlexander Motin if (data[i] != 0) 8553b3dd3f7SAlexander Motin break; 8563b3dd3f7SAlexander Motin } 8573b3dd3f7SAlexander Motin if (i == sizeof(nsdata)) 8583b3dd3f7SAlexander Motin errx(1, "namespace %d is not allocated", identify_opt.nsid); 8593b3dd3f7SAlexander Motin 8603b3dd3f7SAlexander Motin /* Convert data to host endian */ 8613b3dd3f7SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 8623b3dd3f7SAlexander Motin 8633b3dd3f7SAlexander Motin if (identify_opt.hex) { 8643b3dd3f7SAlexander Motin i = sizeof(struct nvme_namespace_data); 8653b3dd3f7SAlexander Motin if (!identify_opt.verbose) { 8663b3dd3f7SAlexander Motin for (; i > 384; i--) { 8673b3dd3f7SAlexander Motin if (data[i - 1] != 0) 8683b3dd3f7SAlexander Motin break; 8693b3dd3f7SAlexander Motin } 8703b3dd3f7SAlexander Motin } 8713b3dd3f7SAlexander Motin print_hex(&nsdata, i); 8723b3dd3f7SAlexander Motin exit(0); 8733b3dd3f7SAlexander Motin } 8743b3dd3f7SAlexander Motin 8753b3dd3f7SAlexander Motin print_namespace(&nsdata); 8763b3dd3f7SAlexander Motin exit(0); 8773b3dd3f7SAlexander Motin } 8783b3dd3f7SAlexander Motin 8793b3dd3f7SAlexander Motin static void 880f634b4c1SWarner Losh ns(const struct cmd *nf __unused, int argc, char *argv[]) 881ba405bc8SAlexander Motin { 882ba405bc8SAlexander Motin 883f634b4c1SWarner Losh cmd_dispatch(argc, argv, &ns_cmd); 884ba405bc8SAlexander Motin } 885