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