1ba405bc8SAlexander Motin /*- 24d846d26SWarner 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/param.h> 30ba405bc8SAlexander Motin #include <sys/ioccom.h> 31ba405bc8SAlexander Motin 32ba405bc8SAlexander Motin #include <err.h> 33ba405bc8SAlexander Motin #include <fcntl.h> 343b3dd3f7SAlexander Motin #include <stdbool.h> 353b3dd3f7SAlexander Motin #include <stddef.h> 36ba405bc8SAlexander Motin #include <stdio.h> 37ba405bc8SAlexander Motin #include <stdlib.h> 38ba405bc8SAlexander Motin #include <string.h> 395dc463f9SAlexander Motin #include <sysexits.h> 40ba405bc8SAlexander Motin #include <unistd.h> 41ba405bc8SAlexander Motin 42ba405bc8SAlexander Motin #include "nvmecontrol.h" 43ba405bc8SAlexander Motin 44f634b4c1SWarner Losh /* Tables for command line parsing */ 45f634b4c1SWarner Losh 46f634b4c1SWarner Losh static cmd_fn_t ns; 473b3dd3f7SAlexander Motin static cmd_fn_t nsactive; 483b3dd3f7SAlexander Motin static cmd_fn_t nsallocated; 493b3dd3f7SAlexander Motin static cmd_fn_t nscontrollers; 50f634b4c1SWarner Losh static cmd_fn_t nscreate; 51f634b4c1SWarner Losh static cmd_fn_t nsdelete; 52f634b4c1SWarner Losh static cmd_fn_t nsattach; 53f634b4c1SWarner Losh static cmd_fn_t nsdetach; 543b3dd3f7SAlexander Motin static cmd_fn_t nsattached; 553b3dd3f7SAlexander Motin static cmd_fn_t nsidentify; 56f634b4c1SWarner Losh 57f634b4c1SWarner Losh #define NONE 0xffffffffu 58f634b4c1SWarner Losh #define NONE64 0xffffffffffffffffull 59f634b4c1SWarner Losh #define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc } 60f634b4c1SWarner Losh #define OPT_END { NULL, 0, arg_none, NULL, NULL } 61f634b4c1SWarner Losh 62f634b4c1SWarner Losh static struct cmd ns_cmd = { 633b3dd3f7SAlexander Motin .name = "ns", 643b3dd3f7SAlexander Motin .fn = ns, 653b3dd3f7SAlexander Motin .descr = "Namespace management commands", 663b3dd3f7SAlexander Motin .ctx_size = 0, 673b3dd3f7SAlexander Motin .opts = NULL, 683b3dd3f7SAlexander Motin .args = NULL, 69f634b4c1SWarner Losh }; 70f634b4c1SWarner Losh 71f634b4c1SWarner Losh CMD_COMMAND(ns_cmd); 72f634b4c1SWarner Losh 733b3dd3f7SAlexander Motin static struct active_options { 743b3dd3f7SAlexander Motin const char *dev; 753b3dd3f7SAlexander Motin } active_opt = { 763b3dd3f7SAlexander Motin .dev = NULL, 773b3dd3f7SAlexander Motin }; 783b3dd3f7SAlexander Motin 793b3dd3f7SAlexander Motin static const struct args active_args[] = { 805458a1c8SAlexander Motin { arg_string, &active_opt.dev, "controller-id|namespace-id" }, 813b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 823b3dd3f7SAlexander Motin }; 833b3dd3f7SAlexander Motin 843b3dd3f7SAlexander Motin static struct cmd active_cmd = { 853b3dd3f7SAlexander Motin .name = "active", 863b3dd3f7SAlexander Motin .fn = nsactive, 873b3dd3f7SAlexander Motin .descr = "List active (attached) namespaces", 883b3dd3f7SAlexander Motin .ctx_size = sizeof(active_opt), 893b3dd3f7SAlexander Motin .opts = NULL, 903b3dd3f7SAlexander Motin .args = active_args, 913b3dd3f7SAlexander Motin }; 923b3dd3f7SAlexander Motin 933b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, active_cmd); 943b3dd3f7SAlexander Motin 953b3dd3f7SAlexander Motin static struct cmd allocated_cmd = { 963b3dd3f7SAlexander Motin .name = "allocated", 973b3dd3f7SAlexander Motin .fn = nsallocated, 983b3dd3f7SAlexander Motin .descr = "List allocated (created) namespaces", 993b3dd3f7SAlexander Motin .ctx_size = sizeof(active_opt), 1003b3dd3f7SAlexander Motin .opts = NULL, 1013b3dd3f7SAlexander Motin .args = active_args, 1023b3dd3f7SAlexander Motin }; 1033b3dd3f7SAlexander Motin 1043b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, allocated_cmd); 1053b3dd3f7SAlexander Motin 1063b3dd3f7SAlexander Motin static struct controllers_options { 1073b3dd3f7SAlexander Motin const char *dev; 1083b3dd3f7SAlexander Motin } controllers_opt = { 1093b3dd3f7SAlexander Motin .dev = NULL, 1103b3dd3f7SAlexander Motin }; 1113b3dd3f7SAlexander Motin 1123b3dd3f7SAlexander Motin static const struct args controllers_args[] = { 1135458a1c8SAlexander Motin { arg_string, &controllers_opt.dev, "controller-id|namespace-id" }, 1143b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 1153b3dd3f7SAlexander Motin }; 1163b3dd3f7SAlexander Motin 1173b3dd3f7SAlexander Motin static struct cmd controllers_cmd = { 1183b3dd3f7SAlexander Motin .name = "controllers", 1193b3dd3f7SAlexander Motin .fn = nscontrollers, 1203b3dd3f7SAlexander Motin .descr = "List all controllers in NVM subsystem", 1213b3dd3f7SAlexander Motin .ctx_size = sizeof(controllers_opt), 1223b3dd3f7SAlexander Motin .opts = NULL, 1233b3dd3f7SAlexander Motin .args = controllers_args, 1243b3dd3f7SAlexander Motin }; 1253b3dd3f7SAlexander Motin 1263b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, controllers_cmd); 1273b3dd3f7SAlexander Motin 128f634b4c1SWarner Losh static struct create_options { 129f634b4c1SWarner Losh uint64_t nsze; 130f634b4c1SWarner Losh uint64_t cap; 131f634b4c1SWarner Losh uint32_t lbaf; 132f634b4c1SWarner Losh uint32_t mset; 133f634b4c1SWarner Losh uint32_t nmic; 134f634b4c1SWarner Losh uint32_t pi; 135f634b4c1SWarner Losh uint32_t pil; 136f634b4c1SWarner Losh uint32_t flbas; 137f634b4c1SWarner Losh uint32_t dps; 138f634b4c1SWarner Losh // uint32_t block_size; 139f634b4c1SWarner Losh const char *dev; 140f634b4c1SWarner Losh } create_opt = { 141f634b4c1SWarner Losh .nsze = NONE64, 142f634b4c1SWarner Losh .cap = NONE64, 143f634b4c1SWarner Losh .lbaf = NONE, 144f634b4c1SWarner Losh .mset = NONE, 145f634b4c1SWarner Losh .nmic = NONE, 146f634b4c1SWarner Losh .pi = NONE, 147f634b4c1SWarner Losh .pil = NONE, 148f634b4c1SWarner Losh .flbas = NONE, 149f634b4c1SWarner Losh .dps = NONE, 150f634b4c1SWarner Losh .dev = NULL, 151f634b4c1SWarner Losh // .block_size = NONE, 152f634b4c1SWarner Losh }; 153f634b4c1SWarner Losh 154f634b4c1SWarner Losh static const struct opts create_opts[] = { 155f634b4c1SWarner Losh OPT("nsze", 's', arg_uint64, create_opt, nsze, 156f634b4c1SWarner Losh "The namespace size"), 157f634b4c1SWarner Losh OPT("ncap", 'c', arg_uint64, create_opt, cap, 158f634b4c1SWarner Losh "The capacity of the namespace (<= ns size)"), 159f634b4c1SWarner Losh OPT("lbaf", 'f', arg_uint32, create_opt, lbaf, 160f634b4c1SWarner Losh "The FMT field of the FLBAS"), 161f634b4c1SWarner Losh OPT("mset", 'm', arg_uint32, create_opt, mset, 162f634b4c1SWarner Losh "The MSET field of the FLBAS"), 163f634b4c1SWarner Losh OPT("nmic", 'n', arg_uint32, create_opt, nmic, 164f634b4c1SWarner Losh "Namespace multipath and sharing capabilities"), 165f634b4c1SWarner Losh OPT("pi", 'p', arg_uint32, create_opt, pi, 166f634b4c1SWarner Losh "PI field of FLBAS"), 167f634b4c1SWarner Losh OPT("pil", 'l', arg_uint32, create_opt, pil, 168f634b4c1SWarner Losh "PIL field of FLBAS"), 1693b3dd3f7SAlexander Motin OPT("flbas", 'L', arg_uint32, create_opt, flbas, 170f634b4c1SWarner Losh "Namespace formatted logical block size setting"), 171f634b4c1SWarner Losh OPT("dps", 'd', arg_uint32, create_opt, dps, 172f634b4c1SWarner Losh "Data protection settings"), 173f634b4c1SWarner Losh // OPT("block-size", 'b', arg_uint32, create_opt, block_size, 174f634b4c1SWarner Losh // "Blocksize of the namespace"), 175f634b4c1SWarner Losh OPT_END 176f634b4c1SWarner Losh }; 177f634b4c1SWarner Losh 178f634b4c1SWarner Losh static const struct args create_args[] = { 1795458a1c8SAlexander Motin { arg_string, &create_opt.dev, "controller-id|namespace-id" }, 180f634b4c1SWarner Losh { arg_none, NULL, NULL }, 181f634b4c1SWarner Losh }; 182f634b4c1SWarner Losh 183f634b4c1SWarner Losh static struct cmd create_cmd = { 184f634b4c1SWarner Losh .name = "create", 185f634b4c1SWarner Losh .fn = nscreate, 1863b3dd3f7SAlexander Motin .descr = "Create a namespace", 187f634b4c1SWarner Losh .ctx_size = sizeof(create_opt), 188f634b4c1SWarner Losh .opts = create_opts, 189f634b4c1SWarner Losh .args = create_args, 190f634b4c1SWarner Losh }; 191f634b4c1SWarner Losh 192f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, create_cmd); 193f634b4c1SWarner Losh 194f634b4c1SWarner Losh static struct delete_options { 195f634b4c1SWarner Losh uint32_t nsid; 196f634b4c1SWarner Losh const char *dev; 197f634b4c1SWarner Losh } delete_opt = { 198dbf1dce8SAlexander Motin .nsid = NONE - 1, 199f634b4c1SWarner Losh .dev = NULL, 200f634b4c1SWarner Losh }; 201f634b4c1SWarner Losh 202f634b4c1SWarner Losh static const struct opts delete_opts[] = { 203f634b4c1SWarner Losh OPT("namespace-id", 'n', arg_uint32, delete_opt, nsid, 204f634b4c1SWarner Losh "The namespace ID to delete"), 205f634b4c1SWarner Losh OPT_END 206f634b4c1SWarner Losh }; 207f634b4c1SWarner Losh 208f634b4c1SWarner Losh static const struct args delete_args[] = { 2095458a1c8SAlexander Motin { arg_string, &delete_opt.dev, "controller-id|namespace-id" }, 210f634b4c1SWarner Losh { arg_none, NULL, NULL }, 211f634b4c1SWarner Losh }; 212f634b4c1SWarner Losh 213f634b4c1SWarner Losh static struct cmd delete_cmd = { 214f634b4c1SWarner Losh .name = "delete", 215f634b4c1SWarner Losh .fn = nsdelete, 2163b3dd3f7SAlexander Motin .descr = "Delete a namespace", 217f634b4c1SWarner Losh .ctx_size = sizeof(delete_opt), 218f634b4c1SWarner Losh .opts = delete_opts, 219f634b4c1SWarner Losh .args = delete_args, 220f634b4c1SWarner Losh }; 221f634b4c1SWarner Losh 222f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, delete_cmd); 223f634b4c1SWarner Losh 224f634b4c1SWarner Losh static struct attach_options { 225f634b4c1SWarner Losh uint32_t nsid; 226f634b4c1SWarner Losh uint32_t ctrlrid; 227f634b4c1SWarner Losh const char *dev; 228f634b4c1SWarner Losh } attach_opt = { 229f634b4c1SWarner Losh .nsid = NONE, 230f634b4c1SWarner Losh .ctrlrid = NONE - 1, 231f634b4c1SWarner Losh .dev = NULL, 232f634b4c1SWarner Losh }; 233f634b4c1SWarner Losh 234f634b4c1SWarner Losh static const struct opts attach_opts[] = { 235f634b4c1SWarner Losh OPT("namespace-id", 'n', arg_uint32, attach_opt, nsid, 236f634b4c1SWarner Losh "The namespace ID to attach"), 2373b3dd3f7SAlexander Motin OPT("controller", 'c', arg_uint32, attach_opt, ctrlrid, 238f634b4c1SWarner Losh "The controller ID to attach"), 239f634b4c1SWarner Losh OPT_END 240f634b4c1SWarner Losh }; 241f634b4c1SWarner Losh 242f634b4c1SWarner Losh static const struct args attach_args[] = { 2435458a1c8SAlexander Motin { arg_string, &attach_opt.dev, "controller-id|namespace-id" }, 244f634b4c1SWarner Losh { arg_none, NULL, NULL }, 245f634b4c1SWarner Losh }; 246f634b4c1SWarner Losh 247f634b4c1SWarner Losh static struct cmd attach_cmd = { 248f634b4c1SWarner Losh .name = "attach", 249f634b4c1SWarner Losh .fn = nsattach, 2503b3dd3f7SAlexander Motin .descr = "Attach a controller to a namespace", 251f634b4c1SWarner Losh .ctx_size = sizeof(attach_opt), 252f634b4c1SWarner Losh .opts = attach_opts, 253f634b4c1SWarner Losh .args = attach_args, 254f634b4c1SWarner Losh }; 255f634b4c1SWarner Losh 256f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, attach_cmd); 257f634b4c1SWarner Losh 2583b3dd3f7SAlexander Motin static struct attached_options { 2593b3dd3f7SAlexander Motin uint32_t nsid; 2603b3dd3f7SAlexander Motin const char *dev; 2613b3dd3f7SAlexander Motin } attached_opt = { 2623b3dd3f7SAlexander Motin .nsid = NONE, 2633b3dd3f7SAlexander Motin .dev = NULL, 2643b3dd3f7SAlexander Motin }; 2653b3dd3f7SAlexander Motin 2663b3dd3f7SAlexander Motin static const struct opts attached_opts[] = { 2673b3dd3f7SAlexander Motin OPT("namespace-id", 'n', arg_uint32, attached_opt, nsid, 2683b3dd3f7SAlexander Motin "The namespace ID to request attached controllers"), 2693b3dd3f7SAlexander Motin OPT_END 2703b3dd3f7SAlexander Motin }; 2713b3dd3f7SAlexander Motin 2723b3dd3f7SAlexander Motin static const struct args attached_args[] = { 2735458a1c8SAlexander Motin { arg_string, &attached_opt.dev, "controller-id|namespace-id" }, 2743b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 2753b3dd3f7SAlexander Motin }; 2763b3dd3f7SAlexander Motin 2773b3dd3f7SAlexander Motin static struct cmd attached_cmd = { 2783b3dd3f7SAlexander Motin .name = "attached", 2793b3dd3f7SAlexander Motin .fn = nsattached, 2803b3dd3f7SAlexander Motin .descr = "List controllers attached to a namespace", 2813b3dd3f7SAlexander Motin .ctx_size = sizeof(attached_opt), 2823b3dd3f7SAlexander Motin .opts = attached_opts, 2833b3dd3f7SAlexander Motin .args = attached_args, 2843b3dd3f7SAlexander Motin }; 2853b3dd3f7SAlexander Motin 2863b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, attached_cmd); 2873b3dd3f7SAlexander Motin 288f634b4c1SWarner Losh static struct detach_options { 289f634b4c1SWarner Losh uint32_t nsid; 290f634b4c1SWarner Losh uint32_t ctrlrid; 291f634b4c1SWarner Losh const char *dev; 292f634b4c1SWarner Losh } detach_opt = { 293f634b4c1SWarner Losh .nsid = NONE, 294f634b4c1SWarner Losh .ctrlrid = NONE - 1, 295f634b4c1SWarner Losh .dev = NULL, 296f634b4c1SWarner Losh }; 297f634b4c1SWarner Losh 298f634b4c1SWarner Losh static const struct opts detach_opts[] = { 299f634b4c1SWarner Losh OPT("namespace-id", 'n', arg_uint32, detach_opt, nsid, 300f634b4c1SWarner Losh "The namespace ID to detach"), 3013b3dd3f7SAlexander Motin OPT("controller", 'c', arg_uint32, detach_opt, ctrlrid, 302f634b4c1SWarner Losh "The controller ID to detach"), 303f634b4c1SWarner Losh OPT_END 304f634b4c1SWarner Losh }; 305f634b4c1SWarner Losh 306f634b4c1SWarner Losh static const struct args detach_args[] = { 3075458a1c8SAlexander Motin { arg_string, &detach_opt.dev, "controller-id|namespace-id" }, 308f634b4c1SWarner Losh { arg_none, NULL, NULL }, 309f634b4c1SWarner Losh }; 310f634b4c1SWarner Losh 311f634b4c1SWarner Losh static struct cmd detach_cmd = { 312f634b4c1SWarner Losh .name = "detach", 313f634b4c1SWarner Losh .fn = nsdetach, 3143b3dd3f7SAlexander Motin .descr = "Detach a controller from a namespace", 315f634b4c1SWarner Losh .ctx_size = sizeof(detach_opt), 316f634b4c1SWarner Losh .opts = detach_opts, 317f634b4c1SWarner Losh .args = detach_args, 318f634b4c1SWarner Losh }; 319f634b4c1SWarner Losh 320f634b4c1SWarner Losh CMD_SUBCOMMAND(ns_cmd, detach_cmd); 321a13a291aSWarner Losh 3223b3dd3f7SAlexander Motin static struct identify_options { 3233b3dd3f7SAlexander Motin bool hex; 3243b3dd3f7SAlexander Motin bool verbose; 3253b3dd3f7SAlexander Motin const char *dev; 3263b3dd3f7SAlexander Motin uint32_t nsid; 3273b3dd3f7SAlexander Motin } identify_opt = { 3283b3dd3f7SAlexander Motin .hex = false, 3293b3dd3f7SAlexander Motin .verbose = false, 3303b3dd3f7SAlexander Motin .dev = NULL, 331d1a0eab9SAlexander Motin .nsid = NONE, 3323b3dd3f7SAlexander Motin }; 3333b3dd3f7SAlexander Motin 3343b3dd3f7SAlexander Motin static const struct opts identify_opts[] = { 3353b3dd3f7SAlexander Motin OPT("hex", 'x', arg_none, identify_opt, hex, 3363b3dd3f7SAlexander Motin "Print identiy information in hex"), 3373b3dd3f7SAlexander Motin OPT("verbose", 'v', arg_none, identify_opt, verbose, 3383b3dd3f7SAlexander Motin "More verbosity: print entire identify table"), 3393b3dd3f7SAlexander Motin OPT("nsid", 'n', arg_uint32, identify_opt, nsid, 3403b3dd3f7SAlexander Motin "The namespace ID to print IDENTIFY for"), 3413b3dd3f7SAlexander Motin { NULL, 0, arg_none, NULL, NULL } 3423b3dd3f7SAlexander Motin }; 3433b3dd3f7SAlexander Motin 3443b3dd3f7SAlexander Motin static const struct args identify_args[] = { 3455458a1c8SAlexander Motin { arg_string, &identify_opt.dev, "controller-id|namespace-id" }, 3463b3dd3f7SAlexander Motin { arg_none, NULL, NULL }, 3473b3dd3f7SAlexander Motin }; 3483b3dd3f7SAlexander Motin 3493b3dd3f7SAlexander Motin static struct cmd identify_cmd = { 3503b3dd3f7SAlexander Motin .name = "identify", 3513b3dd3f7SAlexander Motin .fn = nsidentify, 3523b3dd3f7SAlexander Motin .descr = "Print IDENTIFY for allocated namespace", 3533b3dd3f7SAlexander Motin .ctx_size = sizeof(identify_opt), 3543b3dd3f7SAlexander Motin .opts = identify_opts, 3553b3dd3f7SAlexander Motin .args = identify_args, 3563b3dd3f7SAlexander Motin }; 3573b3dd3f7SAlexander Motin 3583b3dd3f7SAlexander Motin CMD_SUBCOMMAND(ns_cmd, identify_cmd); 359a13a291aSWarner Losh 360ba405bc8SAlexander Motin /* handles NVME_OPC_NAMESPACE_MANAGEMENT and ATTACHMENT admin cmds */ 361ba405bc8SAlexander Motin 362ba405bc8SAlexander Motin struct ns_result_str { 363ba405bc8SAlexander Motin uint16_t res; 364ba405bc8SAlexander Motin const char * str; 365ba405bc8SAlexander Motin }; 366ba405bc8SAlexander Motin 367ba405bc8SAlexander Motin static struct ns_result_str ns_result[] = { 368ba405bc8SAlexander Motin { 0x2, "Invalid Field"}, 369ba405bc8SAlexander Motin { 0xa, "Invalid Format"}, 370ba405bc8SAlexander Motin { 0xb, "Invalid Namespace or format"}, 371e2dfabb5SGordon Bergling { 0x15, "Namespace insufficient capacity"}, 3725d7c65ffSJens Schweikhardt { 0x16, "Namespace ID unavailable"}, 373ba405bc8SAlexander Motin { 0x18, "Namespace already attached"}, 374ba405bc8SAlexander Motin { 0x19, "Namespace is private"}, 375ba405bc8SAlexander Motin { 0x1a, "Namespace is not attached"}, 376ba405bc8SAlexander Motin { 0x1b, "Thin provisioning not supported"}, 377ba405bc8SAlexander Motin { 0x1c, "Controller list invalid"}, 3783b3dd3f7SAlexander Motin { 0x24, "ANA Group Identifier Invalid"}, 3793b3dd3f7SAlexander Motin { 0x25, "ANA Attach Failed"}, 380ba405bc8SAlexander Motin { 0xFFFF, "Unknown"} 381ba405bc8SAlexander Motin }; 382ba405bc8SAlexander Motin 383ba405bc8SAlexander Motin static const char * 384ba405bc8SAlexander Motin get_res_str(uint16_t res) 385ba405bc8SAlexander Motin { 386ba405bc8SAlexander Motin struct ns_result_str *t = ns_result; 387ba405bc8SAlexander Motin 388ba405bc8SAlexander Motin while (t->res != 0xFFFF) { 389ba405bc8SAlexander Motin if (t->res == res) 390ba405bc8SAlexander Motin return (t->str); 391ba405bc8SAlexander Motin t++; 392ba405bc8SAlexander Motin } 393ba405bc8SAlexander Motin return t->str; 394ba405bc8SAlexander Motin } 395ba405bc8SAlexander Motin 3963b3dd3f7SAlexander Motin static void 3973b3dd3f7SAlexander Motin nsactive(const struct cmd *f, int argc, char *argv[]) 3983b3dd3f7SAlexander Motin { 3993b3dd3f7SAlexander Motin struct nvme_pt_command pt; 4005458a1c8SAlexander Motin struct nvme_controller_data cd; 4013b3dd3f7SAlexander Motin int fd, i; 4025458a1c8SAlexander Motin char *path; 4035458a1c8SAlexander Motin uint32_t nsid; 4043b3dd3f7SAlexander Motin uint32_t list[1024]; 4053b3dd3f7SAlexander Motin 4063b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 4073b3dd3f7SAlexander Motin return; 4081f15d49eSAlexander Motin open_dev(active_opt.dev, &fd, 0, 1); 4095458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 4105458a1c8SAlexander Motin if (nsid != 0) { 4115458a1c8SAlexander Motin close(fd); 4125458a1c8SAlexander Motin open_dev(path, &fd, 0, 1); 4135458a1c8SAlexander Motin } 4145458a1c8SAlexander Motin free(path); 4155dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 4165dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 4175458a1c8SAlexander Motin 4185458a1c8SAlexander Motin /* Check that controller can execute this command. */ 419fba73a40SJohn Baldwin if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0) 4205dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 4213b3dd3f7SAlexander Motin 4223b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 4233b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 4243b3dd3f7SAlexander Motin pt.cmd.nsid = htole32(0); 4253b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x02); 4263b3dd3f7SAlexander Motin pt.buf = list; 4273b3dd3f7SAlexander Motin pt.len = sizeof(list); 4283b3dd3f7SAlexander Motin pt.is_read = 1; 4293b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 4305dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 4313b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 4325dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 4333b3dd3f7SAlexander Motin 4343b3dd3f7SAlexander Motin printf("Active namespaces:\n"); 4353b3dd3f7SAlexander Motin for (i = 0; list[i] != 0; i++) 4363b3dd3f7SAlexander Motin printf("%10d\n", le32toh(list[i])); 4373b3dd3f7SAlexander Motin 4383b3dd3f7SAlexander Motin exit(0); 4393b3dd3f7SAlexander Motin } 4403b3dd3f7SAlexander Motin 4413b3dd3f7SAlexander Motin static void 4423b3dd3f7SAlexander Motin nsallocated(const struct cmd *f, int argc, char *argv[]) 4433b3dd3f7SAlexander Motin { 4443b3dd3f7SAlexander Motin struct nvme_pt_command pt; 4453b3dd3f7SAlexander Motin struct nvme_controller_data cd; 4463b3dd3f7SAlexander Motin int fd, i; 4475458a1c8SAlexander Motin char *path; 4485458a1c8SAlexander Motin uint32_t nsid; 4493b3dd3f7SAlexander Motin uint32_t list[1024]; 4503b3dd3f7SAlexander Motin 4513b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 4523b3dd3f7SAlexander Motin return; 4531f15d49eSAlexander Motin open_dev(active_opt.dev, &fd, 0, 1); 4545458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 4555458a1c8SAlexander Motin if (nsid != 0) { 4565458a1c8SAlexander Motin close(fd); 4575458a1c8SAlexander Motin open_dev(path, &fd, 0, 1); 4585458a1c8SAlexander Motin } 4595458a1c8SAlexander Motin free(path); 4605dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 4615dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 4623b3dd3f7SAlexander Motin 4633b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 464fba73a40SJohn Baldwin if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0) 4655dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 4663b3dd3f7SAlexander Motin 4673b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 4683b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 4693b3dd3f7SAlexander Motin pt.cmd.nsid = htole32(0); 4703b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x10); 4713b3dd3f7SAlexander Motin pt.buf = list; 4723b3dd3f7SAlexander Motin pt.len = sizeof(list); 4733b3dd3f7SAlexander Motin pt.is_read = 1; 4743b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 4755dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 4763b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 4775dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 4783b3dd3f7SAlexander Motin 4793b3dd3f7SAlexander Motin printf("Allocated namespaces:\n"); 4803b3dd3f7SAlexander Motin for (i = 0; list[i] != 0; i++) 4813b3dd3f7SAlexander Motin printf("%10d\n", le32toh(list[i])); 4823b3dd3f7SAlexander Motin 4833b3dd3f7SAlexander Motin exit(0); 4843b3dd3f7SAlexander Motin } 4853b3dd3f7SAlexander Motin 4863b3dd3f7SAlexander Motin static void 4873b3dd3f7SAlexander Motin nscontrollers(const struct cmd *f, int argc, char *argv[]) 4883b3dd3f7SAlexander Motin { 4893b3dd3f7SAlexander Motin struct nvme_pt_command pt; 4903b3dd3f7SAlexander Motin struct nvme_controller_data cd; 4913b3dd3f7SAlexander Motin int fd, i, n; 4925458a1c8SAlexander Motin char *path; 4935458a1c8SAlexander Motin uint32_t nsid; 4943b3dd3f7SAlexander Motin uint16_t clist[2048]; 4953b3dd3f7SAlexander Motin 4963b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 4973b3dd3f7SAlexander Motin return; 4981f15d49eSAlexander Motin open_dev(controllers_opt.dev, &fd, 0, 1); 4995458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 5005458a1c8SAlexander Motin if (nsid != 0) { 5015458a1c8SAlexander Motin close(fd); 5025458a1c8SAlexander Motin open_dev(path, &fd, 0, 1); 5035458a1c8SAlexander Motin } 5045458a1c8SAlexander Motin free(path); 5055dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 5065dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 5073b3dd3f7SAlexander Motin 5083b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 509fba73a40SJohn Baldwin if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0) 5105dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 5113b3dd3f7SAlexander Motin 5123b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 5133b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 5143b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x13); 5153b3dd3f7SAlexander Motin pt.buf = clist; 5163b3dd3f7SAlexander Motin pt.len = sizeof(clist); 5173b3dd3f7SAlexander Motin pt.is_read = 1; 5183b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 5195dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 5203b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 5215dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 5223b3dd3f7SAlexander Motin 5233b3dd3f7SAlexander Motin n = le16toh(clist[0]); 5243b3dd3f7SAlexander Motin printf("NVM subsystem includes %d controller(s):\n", n); 5253b3dd3f7SAlexander Motin for (i = 0; i < n; i++) 5263b3dd3f7SAlexander Motin printf(" 0x%04x\n", le16toh(clist[i + 1])); 5273b3dd3f7SAlexander Motin 5283b3dd3f7SAlexander Motin exit(0); 5293b3dd3f7SAlexander Motin } 5303b3dd3f7SAlexander Motin 531ba405bc8SAlexander Motin /* 532ba405bc8SAlexander Motin * NS MGMT Command specific status values: 533ba405bc8SAlexander Motin * 0xa = Invalid Format 53469f9c5a5SYu-Sheng Ma * 0x15 = Namespace Insufficient capacity 535ba405bc8SAlexander Motin * 0x16 = Namespace ID unavailable (number namespaces exceeded) 536ba405bc8SAlexander Motin * 0xb = Thin Provisioning Not supported 537ba405bc8SAlexander Motin */ 5380d095c23SWarner Losh static void 539f634b4c1SWarner Losh nscreate(const struct cmd *f, int argc, char *argv[]) 540ba405bc8SAlexander Motin { 541ba405bc8SAlexander Motin struct nvme_pt_command pt; 542ba405bc8SAlexander Motin struct nvme_controller_data cd; 543ba405bc8SAlexander Motin struct nvme_namespace_data nsdata; 544f634b4c1SWarner Losh int fd, result; 5455458a1c8SAlexander Motin char *path; 5465458a1c8SAlexander Motin uint32_t nsid; 547ba405bc8SAlexander Motin 548f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 549f634b4c1SWarner Losh return; 550ba405bc8SAlexander Motin 551f634b4c1SWarner Losh if (create_opt.cap == NONE64) 552f634b4c1SWarner Losh create_opt.cap = create_opt.nsze; 553f634b4c1SWarner Losh if (create_opt.nsze == NONE64) { 554f634b4c1SWarner Losh fprintf(stderr, 555f634b4c1SWarner Losh "Size not specified\n"); 556f634b4c1SWarner Losh arg_help(argc, argv, f); 557ba405bc8SAlexander Motin } 558ba405bc8SAlexander Motin 559f634b4c1SWarner Losh open_dev(create_opt.dev, &fd, 1, 1); 5605458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 5615458a1c8SAlexander Motin if (nsid != 0) { 5625458a1c8SAlexander Motin close(fd); 5635458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 5645458a1c8SAlexander Motin } 5655458a1c8SAlexander Motin free(path); 5665dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 5675dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 568ba405bc8SAlexander Motin 569ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 570fba73a40SJohn Baldwin if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0) 5715dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 572ba405bc8SAlexander Motin 573ba405bc8SAlexander Motin memset(&nsdata, 0, sizeof(nsdata)); 574f634b4c1SWarner Losh nsdata.nsze = create_opt.nsze; 575f634b4c1SWarner Losh nsdata.ncap = create_opt.cap; 57620dc2c4dSAlexander Motin if (create_opt.flbas != NONE) { 577f634b4c1SWarner Losh nsdata.flbas = create_opt.flbas; 57820dc2c4dSAlexander Motin } else { 57920dc2c4dSAlexander Motin /* Default to the first format, whatever it is. */ 58020dc2c4dSAlexander Motin nsdata.flbas = 0; 58120dc2c4dSAlexander Motin if (create_opt.lbaf != NONE) { 582c68ec278SJohn Baldwin nsdata.flbas |= NVMEF(NVME_NS_DATA_FLBAS_FORMAT, 583c68ec278SJohn Baldwin create_opt.lbaf); 58420dc2c4dSAlexander Motin } 58520dc2c4dSAlexander Motin if (create_opt.mset != NONE) { 586c68ec278SJohn Baldwin nsdata.flbas |= NVMEF(NVME_NS_DATA_FLBAS_EXTENDED, 587c68ec278SJohn Baldwin create_opt.mset); 58820dc2c4dSAlexander Motin } 58920dc2c4dSAlexander Motin } 59020dc2c4dSAlexander Motin if (create_opt.dps != NONE) { 591f634b4c1SWarner Losh nsdata.dps = create_opt.dps; 59220dc2c4dSAlexander Motin } else { 59320dc2c4dSAlexander Motin /* Default to protection disabled. */ 59420dc2c4dSAlexander Motin nsdata.dps = 0; 59520dc2c4dSAlexander Motin if (create_opt.pi != NONE) { 596c68ec278SJohn Baldwin nsdata.dps |= NVMEF(NVME_NS_DATA_DPS_MD_START, 597c68ec278SJohn Baldwin create_opt.pi); 59820dc2c4dSAlexander Motin } 59920dc2c4dSAlexander Motin if (create_opt.pil != NONE) { 600c68ec278SJohn Baldwin nsdata.dps |= NVMEF(NVME_NS_DATA_DPS_PIT, 601c68ec278SJohn Baldwin create_opt.pil); 60220dc2c4dSAlexander Motin } 60320dc2c4dSAlexander Motin } 60420dc2c4dSAlexander Motin if (create_opt.nmic != NONE) { 605f634b4c1SWarner Losh nsdata.nmic = create_opt.nmic; 60620dc2c4dSAlexander Motin } else { 60720dc2c4dSAlexander Motin /* Allow namespaces sharing if Multi-Path I/O is supported. */ 608c68ec278SJohn Baldwin nsdata.nmic = NVMEF(NVME_NS_DATA_NMIC_MAY_BE_SHARED, !!cd.mic); 60920dc2c4dSAlexander Motin } 610ba405bc8SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 611ba405bc8SAlexander Motin 612ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 6139544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 6143b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0); /* create */ 615ba405bc8SAlexander Motin pt.buf = &nsdata; 616ba405bc8SAlexander Motin pt.len = sizeof(struct nvme_namespace_data); 617ba405bc8SAlexander Motin pt.is_read = 0; /* passthrough writes data to ctrlr */ 618ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 6195dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", create_opt.dev, result); 620ba405bc8SAlexander Motin 621ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 6225dc463f9SAlexander Motin errx(EX_IOERR, "namespace creation failed: %s", 623fba73a40SJohn Baldwin get_res_str(NVMEV(NVME_STATUS_SC, pt.cpl.status))); 624ba405bc8SAlexander Motin } 625ba405bc8SAlexander Motin printf("namespace %d created\n", pt.cpl.cdw0); 626ba405bc8SAlexander Motin exit(0); 627ba405bc8SAlexander Motin } 628ba405bc8SAlexander Motin 6290d095c23SWarner Losh static void 630f634b4c1SWarner Losh nsdelete(const struct cmd *f, int argc, char *argv[]) 631ba405bc8SAlexander Motin { 632ba405bc8SAlexander Motin struct nvme_pt_command pt; 633ba405bc8SAlexander Motin struct nvme_controller_data cd; 634f634b4c1SWarner Losh int fd, result; 6355458a1c8SAlexander Motin char *path; 6365458a1c8SAlexander Motin uint32_t nsid; 637ba405bc8SAlexander Motin char buf[2]; 638ba405bc8SAlexander Motin 639f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 640f634b4c1SWarner Losh return; 641ba405bc8SAlexander Motin 642f634b4c1SWarner Losh open_dev(delete_opt.dev, &fd, 1, 1); 6435458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 6445458a1c8SAlexander Motin if (nsid != 0) { 6455458a1c8SAlexander Motin close(fd); 6465458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 647dbf1dce8SAlexander Motin } else if (delete_opt.nsid == NONE - 1) { 6485458a1c8SAlexander Motin close(fd); 649*e3987382SWarner Losh fprintf(stderr, "No NSID specified\n"); 6505458a1c8SAlexander Motin arg_help(argc, argv, f); 6515458a1c8SAlexander Motin } 652dbf1dce8SAlexander Motin if (delete_opt.nsid != NONE - 1) 6535458a1c8SAlexander Motin nsid = delete_opt.nsid; 6545458a1c8SAlexander Motin free(path); 6555dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 6565dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 657ba405bc8SAlexander Motin 658ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 659fba73a40SJohn Baldwin if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0) 6605dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 661ba405bc8SAlexander Motin 662ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 6639544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_MANAGEMENT; 6643b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(1); /* delete */ 665ba405bc8SAlexander Motin pt.buf = buf; 666ba405bc8SAlexander Motin pt.len = sizeof(buf); 667ba405bc8SAlexander Motin pt.is_read = 1; 6685458a1c8SAlexander Motin pt.cmd.nsid = nsid; 669ba405bc8SAlexander Motin 670ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 6715dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", delete_opt.dev, result); 672ba405bc8SAlexander Motin 673ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 6745dc463f9SAlexander Motin errx(EX_IOERR, "namespace deletion failed: %s", 675fba73a40SJohn Baldwin get_res_str(NVMEV(NVME_STATUS_SC, pt.cpl.status))); 676ba405bc8SAlexander Motin } 6775458a1c8SAlexander Motin printf("namespace %d deleted\n", nsid); 678ba405bc8SAlexander Motin exit(0); 679ba405bc8SAlexander Motin } 680ba405bc8SAlexander Motin 681ba405bc8SAlexander Motin /* 682ba405bc8SAlexander Motin * Attach and Detach use Dword 10, and a controller list (section 4.9) 683ba405bc8SAlexander Motin * This struct is 4096 bytes in size. 684ba405bc8SAlexander Motin * 0h = attach 685ba405bc8SAlexander Motin * 1h = detach 686ba405bc8SAlexander Motin * 687ba405bc8SAlexander Motin * Result values for both attach/detach: 688ba405bc8SAlexander Motin * 689ba405bc8SAlexander Motin * Completion 18h = Already attached 690ba405bc8SAlexander Motin * 19h = NS is private and already attached to a controller 691ba405bc8SAlexander Motin * 1Ah = Not attached, request could not be completed 692ba405bc8SAlexander Motin * 1Ch = Controller list invalid. 693ba405bc8SAlexander Motin * 694ba405bc8SAlexander Motin * 0x2 Invalid Field can occur if ctrlrid d.n.e in system. 695ba405bc8SAlexander Motin */ 6960d095c23SWarner Losh static void 697f634b4c1SWarner Losh nsattach(const struct cmd *f, int argc, char *argv[]) 698ba405bc8SAlexander Motin { 699ba405bc8SAlexander Motin struct nvme_pt_command pt; 700ba405bc8SAlexander Motin struct nvme_controller_data cd; 701f634b4c1SWarner Losh int fd, result; 7025458a1c8SAlexander Motin char *path; 7035458a1c8SAlexander Motin uint32_t nsid; 704ba405bc8SAlexander Motin uint16_t clist[2048]; 705ba405bc8SAlexander Motin 706f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 707f634b4c1SWarner Losh return; 7085458a1c8SAlexander Motin open_dev(attach_opt.dev, &fd, 1, 1); 7095458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 7105458a1c8SAlexander Motin if (nsid != 0) { 7115458a1c8SAlexander Motin close(fd); 7125458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 7135458a1c8SAlexander Motin } else if (attach_opt.nsid == NONE) { 7145458a1c8SAlexander Motin close(fd); 715*e3987382SWarner Losh fprintf(stderr, "No NSID specified\n"); 716f634b4c1SWarner Losh arg_help(argc, argv, f); 717ba405bc8SAlexander Motin } 7185458a1c8SAlexander Motin if (attach_opt.nsid != NONE) 7195458a1c8SAlexander Motin nsid = attach_opt.nsid; 7205dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 7215dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 722ba405bc8SAlexander Motin 723ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 724fba73a40SJohn Baldwin if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0) 7255dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 726ba405bc8SAlexander Motin 727f634b4c1SWarner Losh if (attach_opt.ctrlrid == NONE) { 728ba405bc8SAlexander Motin /* Get full list of controllers to attach to. */ 729ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 7309544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 731ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x13); 732ba405bc8SAlexander Motin pt.buf = clist; 733ba405bc8SAlexander Motin pt.len = sizeof(clist); 734ba405bc8SAlexander Motin pt.is_read = 1; 735ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 7365dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 737ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 7385dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 739ba405bc8SAlexander Motin } else { 740ba405bc8SAlexander Motin /* By default attach to this controller. */ 741f634b4c1SWarner Losh if (attach_opt.ctrlrid == NONE - 1) 742f634b4c1SWarner Losh attach_opt.ctrlrid = cd.ctrlr_id; 743ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 744ba405bc8SAlexander Motin clist[0] = htole16(1); 745f634b4c1SWarner Losh clist[1] = htole16(attach_opt.ctrlrid); 746ba405bc8SAlexander Motin } 747ba405bc8SAlexander Motin 748ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 7499544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 7503b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0); /* attach */ 7515458a1c8SAlexander Motin pt.cmd.nsid = nsid; 752ba405bc8SAlexander Motin pt.buf = &clist; 753ba405bc8SAlexander Motin pt.len = sizeof(clist); 754ba405bc8SAlexander Motin 755ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 7565dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", attach_opt.dev, result); 757ba405bc8SAlexander Motin 758ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 7595dc463f9SAlexander Motin errx(EX_IOERR, "namespace attach failed: %s", 760fba73a40SJohn Baldwin get_res_str(NVMEV(NVME_STATUS_SC, pt.cpl.status))); 761ba405bc8SAlexander Motin } 7625458a1c8SAlexander Motin printf("namespace %d attached\n", nsid); 763ba405bc8SAlexander Motin exit(0); 764ba405bc8SAlexander Motin } 765ba405bc8SAlexander Motin 7660d095c23SWarner Losh static void 767f634b4c1SWarner Losh nsdetach(const struct cmd *f, int argc, char *argv[]) 768ba405bc8SAlexander Motin { 769ba405bc8SAlexander Motin struct nvme_pt_command pt; 770ba405bc8SAlexander Motin struct nvme_controller_data cd; 771f634b4c1SWarner Losh int fd, result; 7725458a1c8SAlexander Motin char *path; 7735458a1c8SAlexander Motin uint32_t nsid; 774ba405bc8SAlexander Motin uint16_t clist[2048]; 775ba405bc8SAlexander Motin 776f634b4c1SWarner Losh if (arg_parse(argc, argv, f)) 777f634b4c1SWarner Losh return; 7785458a1c8SAlexander Motin open_dev(detach_opt.dev, &fd, 1, 1); 7795458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 7805458a1c8SAlexander Motin if (nsid != 0) { 7815458a1c8SAlexander Motin close(fd); 7825458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 7835458a1c8SAlexander Motin } else if (detach_opt.nsid == NONE) { 7845458a1c8SAlexander Motin close(fd); 785*e3987382SWarner Losh fprintf(stderr, "No NSID specified\n"); 786f634b4c1SWarner Losh arg_help(argc, argv, f); 787ba405bc8SAlexander Motin } 7885458a1c8SAlexander Motin if (detach_opt.nsid != NONE) 7895458a1c8SAlexander Motin nsid = detach_opt.nsid; 7905dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 7915dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 792ba405bc8SAlexander Motin 793ba405bc8SAlexander Motin /* Check that controller can execute this command. */ 794fba73a40SJohn Baldwin if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0) 7955dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 796ba405bc8SAlexander Motin 797f634b4c1SWarner Losh if (detach_opt.ctrlrid == NONE) { 798ba405bc8SAlexander Motin /* Get list of controllers this namespace attached to. */ 799ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 8009544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_IDENTIFY; 8015458a1c8SAlexander Motin pt.cmd.nsid = htole32(nsid); 802ba405bc8SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 803ba405bc8SAlexander Motin pt.buf = clist; 804ba405bc8SAlexander Motin pt.len = sizeof(clist); 805ba405bc8SAlexander Motin pt.is_read = 1; 806ba405bc8SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 8075dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 808ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 8095dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 810ba405bc8SAlexander Motin if (clist[0] == 0) { 811f634b4c1SWarner Losh detach_opt.ctrlrid = cd.ctrlr_id; 812ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 813ba405bc8SAlexander Motin clist[0] = htole16(1); 814f634b4c1SWarner Losh clist[1] = htole16(detach_opt.ctrlrid); 815ba405bc8SAlexander Motin } 816ba405bc8SAlexander Motin } else { 817ba405bc8SAlexander Motin /* By default detach from this controller. */ 818f634b4c1SWarner Losh if (detach_opt.ctrlrid == NONE - 1) 819f634b4c1SWarner Losh detach_opt.ctrlrid = cd.ctrlr_id; 820ba405bc8SAlexander Motin memset(&clist, 0, sizeof(clist)); 821ba405bc8SAlexander Motin clist[0] = htole16(1); 822f634b4c1SWarner Losh clist[1] = htole16(detach_opt.ctrlrid); 823ba405bc8SAlexander Motin } 824ba405bc8SAlexander Motin 825ba405bc8SAlexander Motin memset(&pt, 0, sizeof(pt)); 8269544e6dcSChuck Tuffli pt.cmd.opc = NVME_OPC_NAMESPACE_ATTACHMENT; 8273b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(1); /* detach */ 8285458a1c8SAlexander Motin pt.cmd.nsid = nsid; 829ba405bc8SAlexander Motin pt.buf = &clist; 830ba405bc8SAlexander Motin pt.len = sizeof(clist); 831ba405bc8SAlexander Motin 832ba405bc8SAlexander Motin if ((result = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt)) < 0) 8335dc463f9SAlexander Motin errx(EX_IOERR, "ioctl request to %s failed: %d", detach_opt.dev, result); 834ba405bc8SAlexander Motin 835ba405bc8SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) { 8365dc463f9SAlexander Motin errx(EX_IOERR, "namespace detach failed: %s", 837fba73a40SJohn Baldwin get_res_str(NVMEV(NVME_STATUS_SC, pt.cpl.status))); 838ba405bc8SAlexander Motin } 8395458a1c8SAlexander Motin printf("namespace %d detached\n", nsid); 840ba405bc8SAlexander Motin exit(0); 841ba405bc8SAlexander Motin } 842ba405bc8SAlexander Motin 843a13a291aSWarner Losh static void 8443b3dd3f7SAlexander Motin nsattached(const struct cmd *f, int argc, char *argv[]) 8453b3dd3f7SAlexander Motin { 8463b3dd3f7SAlexander Motin struct nvme_pt_command pt; 8473b3dd3f7SAlexander Motin struct nvme_controller_data cd; 8483b3dd3f7SAlexander Motin int fd, i, n; 8495458a1c8SAlexander Motin char *path; 8505458a1c8SAlexander Motin uint32_t nsid; 8513b3dd3f7SAlexander Motin uint16_t clist[2048]; 8523b3dd3f7SAlexander Motin 8533b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 8543b3dd3f7SAlexander Motin return; 8555458a1c8SAlexander Motin open_dev(attached_opt.dev, &fd, 0, 1); 8565458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 8575458a1c8SAlexander Motin if (nsid != 0) { 8585458a1c8SAlexander Motin close(fd); 8595458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 8605458a1c8SAlexander Motin } else if (attached_opt.nsid == NONE) { 8615458a1c8SAlexander Motin close(fd); 862*e3987382SWarner Losh fprintf(stderr, "No NSID specified\n"); 8633b3dd3f7SAlexander Motin arg_help(argc, argv, f); 8643b3dd3f7SAlexander Motin } 8655458a1c8SAlexander Motin if (attached_opt.nsid != NONE) 8665458a1c8SAlexander Motin nsid = attached_opt.nsid; 8675dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 8685dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 8693b3dd3f7SAlexander Motin 8703b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 871fba73a40SJohn Baldwin if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0) 8725dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 8733b3dd3f7SAlexander Motin 8743b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 8753b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 8765458a1c8SAlexander Motin pt.cmd.nsid = htole32(nsid); 8773b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x12); 8783b3dd3f7SAlexander Motin pt.buf = clist; 8793b3dd3f7SAlexander Motin pt.len = sizeof(clist); 8803b3dd3f7SAlexander Motin pt.is_read = 1; 8813b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 8825dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 8833b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 8845dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 8853b3dd3f7SAlexander Motin 8863b3dd3f7SAlexander Motin n = le16toh(clist[0]); 8873b3dd3f7SAlexander Motin printf("Attached %d controller(s):\n", n); 8883b3dd3f7SAlexander Motin for (i = 0; i < n; i++) 8893b3dd3f7SAlexander Motin printf(" 0x%04x\n", le16toh(clist[i + 1])); 8903b3dd3f7SAlexander Motin 8913b3dd3f7SAlexander Motin exit(0); 8923b3dd3f7SAlexander Motin } 8933b3dd3f7SAlexander Motin 8943b3dd3f7SAlexander Motin static void 8953b3dd3f7SAlexander Motin nsidentify(const struct cmd *f, int argc, char *argv[]) 8963b3dd3f7SAlexander Motin { 8973b3dd3f7SAlexander Motin struct nvme_pt_command pt; 8983b3dd3f7SAlexander Motin struct nvme_controller_data cd; 8993b3dd3f7SAlexander Motin struct nvme_namespace_data nsdata; 9003b3dd3f7SAlexander Motin uint8_t *data; 9013b3dd3f7SAlexander Motin int fd; 9025458a1c8SAlexander Motin char *path; 9035458a1c8SAlexander Motin uint32_t nsid; 9043b3dd3f7SAlexander Motin u_int i; 9053b3dd3f7SAlexander Motin 9063b3dd3f7SAlexander Motin if (arg_parse(argc, argv, f)) 9073b3dd3f7SAlexander Motin return; 9085458a1c8SAlexander Motin open_dev(identify_opt.dev, &fd, 0, 1); 9095458a1c8SAlexander Motin get_nsid(fd, &path, &nsid); 9105458a1c8SAlexander Motin if (nsid != 0) { 9115458a1c8SAlexander Motin close(fd); 9125458a1c8SAlexander Motin open_dev(path, &fd, 1, 1); 913d1a0eab9SAlexander Motin } else if (identify_opt.nsid == NONE) { 9145458a1c8SAlexander Motin close(fd); 915*e3987382SWarner Losh fprintf(stderr, "No NSID specified\n"); 9163b3dd3f7SAlexander Motin arg_help(argc, argv, f); 9173b3dd3f7SAlexander Motin } 918d1a0eab9SAlexander Motin if (identify_opt.nsid != NONE) 9195458a1c8SAlexander Motin nsid = identify_opt.nsid; 9205dc463f9SAlexander Motin if (read_controller_data(fd, &cd)) 9215dc463f9SAlexander Motin errx(EX_IOERR, "Identify request failed"); 9223b3dd3f7SAlexander Motin 9233b3dd3f7SAlexander Motin /* Check that controller can execute this command. */ 924fba73a40SJohn Baldwin if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0) 9255dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "controller does not support namespace management"); 9263b3dd3f7SAlexander Motin 9273b3dd3f7SAlexander Motin memset(&pt, 0, sizeof(pt)); 9283b3dd3f7SAlexander Motin pt.cmd.opc = NVME_OPC_IDENTIFY; 9295458a1c8SAlexander Motin pt.cmd.nsid = htole32(nsid); 9303b3dd3f7SAlexander Motin pt.cmd.cdw10 = htole32(0x11); 9313b3dd3f7SAlexander Motin pt.buf = &nsdata; 9323b3dd3f7SAlexander Motin pt.len = sizeof(nsdata); 9333b3dd3f7SAlexander Motin pt.is_read = 1; 9343b3dd3f7SAlexander Motin 9353b3dd3f7SAlexander Motin if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0) 9365dc463f9SAlexander Motin err(EX_IOERR, "identify request failed"); 9373b3dd3f7SAlexander Motin 9383b3dd3f7SAlexander Motin if (nvme_completion_is_error(&pt.cpl)) 9395dc463f9SAlexander Motin errx(EX_IOERR, "identify request returned error"); 9403b3dd3f7SAlexander Motin 9413b3dd3f7SAlexander Motin close(fd); 9423b3dd3f7SAlexander Motin 9433b3dd3f7SAlexander Motin data = (uint8_t *)&nsdata; 9443b3dd3f7SAlexander Motin for (i = 0; i < sizeof(nsdata); i++) { 9453b3dd3f7SAlexander Motin if (data[i] != 0) 9463b3dd3f7SAlexander Motin break; 9473b3dd3f7SAlexander Motin } 9483b3dd3f7SAlexander Motin if (i == sizeof(nsdata)) 9495dc463f9SAlexander Motin errx(EX_UNAVAILABLE, "namespace %d is not allocated", nsid); 9503b3dd3f7SAlexander Motin 9513b3dd3f7SAlexander Motin /* Convert data to host endian */ 9523b3dd3f7SAlexander Motin nvme_namespace_data_swapbytes(&nsdata); 9533b3dd3f7SAlexander Motin 9543b3dd3f7SAlexander Motin if (identify_opt.hex) { 9553b3dd3f7SAlexander Motin i = sizeof(struct nvme_namespace_data); 9563b3dd3f7SAlexander Motin if (!identify_opt.verbose) { 9573b3dd3f7SAlexander Motin for (; i > 384; i--) { 9583b3dd3f7SAlexander Motin if (data[i - 1] != 0) 9593b3dd3f7SAlexander Motin break; 9603b3dd3f7SAlexander Motin } 9613b3dd3f7SAlexander Motin } 9623b3dd3f7SAlexander Motin print_hex(&nsdata, i); 9633b3dd3f7SAlexander Motin exit(0); 9643b3dd3f7SAlexander Motin } 9653b3dd3f7SAlexander Motin 9663b3dd3f7SAlexander Motin print_namespace(&nsdata); 9673b3dd3f7SAlexander Motin exit(0); 9683b3dd3f7SAlexander Motin } 9693b3dd3f7SAlexander Motin 9703b3dd3f7SAlexander Motin static void 971f634b4c1SWarner Losh ns(const struct cmd *nf __unused, int argc, char *argv[]) 972ba405bc8SAlexander Motin { 973ba405bc8SAlexander Motin 974f634b4c1SWarner Losh cmd_dispatch(argc, argv, &ns_cmd); 975ba405bc8SAlexander Motin } 976