xref: /freebsd/sbin/nvmecontrol/ns.c (revision e39873820da7ddfddb59823efc3421125b92c17a)
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