1*f5f0964cSRobert Mustacchi /*
2*f5f0964cSRobert Mustacchi * This file and its contents are supplied under the terms of the
3*f5f0964cSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*f5f0964cSRobert Mustacchi * You may only use this file in accordance with the terms of version
5*f5f0964cSRobert Mustacchi * 1.0 of the CDDL.
6*f5f0964cSRobert Mustacchi *
7*f5f0964cSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*f5f0964cSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*f5f0964cSRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*f5f0964cSRobert Mustacchi */
11*f5f0964cSRobert Mustacchi
12*f5f0964cSRobert Mustacchi /*
13*f5f0964cSRobert Mustacchi * Copyright 2025 Oxide Computer Company
14*f5f0964cSRobert Mustacchi */
15*f5f0964cSRobert Mustacchi
16*f5f0964cSRobert Mustacchi /*
17*f5f0964cSRobert Mustacchi * This implements support for Namespace Management and Namespace Attach
18*f5f0964cSRobert Mustacchi * commands.
19*f5f0964cSRobert Mustacchi */
20*f5f0964cSRobert Mustacchi
21*f5f0964cSRobert Mustacchi #include <string.h>
22*f5f0964cSRobert Mustacchi #include <unistd.h>
23*f5f0964cSRobert Mustacchi
24*f5f0964cSRobert Mustacchi #include "libnvme_impl.h"
25*f5f0964cSRobert Mustacchi
26*f5f0964cSRobert Mustacchi void
nvme_ns_attach_req_fini(nvme_ns_attach_req_t * req)27*f5f0964cSRobert Mustacchi nvme_ns_attach_req_fini(nvme_ns_attach_req_t *req)
28*f5f0964cSRobert Mustacchi {
29*f5f0964cSRobert Mustacchi free(req);
30*f5f0964cSRobert Mustacchi }
31*f5f0964cSRobert Mustacchi
32*f5f0964cSRobert Mustacchi static void
nvme_ns_attach_req_clear_need(nvme_ns_attach_req_t * req,nvme_ns_attach_req_field_t field)33*f5f0964cSRobert Mustacchi nvme_ns_attach_req_clear_need(nvme_ns_attach_req_t *req,
34*f5f0964cSRobert Mustacchi nvme_ns_attach_req_field_t field)
35*f5f0964cSRobert Mustacchi {
36*f5f0964cSRobert Mustacchi req->nar_need &= ~(1 << field);
37*f5f0964cSRobert Mustacchi }
38*f5f0964cSRobert Mustacchi
39*f5f0964cSRobert Mustacchi bool
nvme_ns_attach_req_init_by_sel(nvme_ctrl_t * ctrl,uint32_t sel,nvme_ns_attach_req_t ** reqp)40*f5f0964cSRobert Mustacchi nvme_ns_attach_req_init_by_sel(nvme_ctrl_t *ctrl, uint32_t sel,
41*f5f0964cSRobert Mustacchi nvme_ns_attach_req_t **reqp)
42*f5f0964cSRobert Mustacchi {
43*f5f0964cSRobert Mustacchi nvme_ns_attach_req_t *req;
44*f5f0964cSRobert Mustacchi nvme_valid_ctrl_data_t ctrl_data;
45*f5f0964cSRobert Mustacchi
46*f5f0964cSRobert Mustacchi if (reqp == NULL) {
47*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_BAD_PTR, 0,
48*f5f0964cSRobert Mustacchi "encountered invalid nvme_ns_attach_req_t output pointer: "
49*f5f0964cSRobert Mustacchi "%p", reqp));
50*f5f0964cSRobert Mustacchi }
51*f5f0964cSRobert Mustacchi
52*f5f0964cSRobert Mustacchi ctrl_data.vcd_vers = &ctrl->nc_vers;
53*f5f0964cSRobert Mustacchi ctrl_data.vcd_id = &ctrl->nc_info;
54*f5f0964cSRobert Mustacchi
55*f5f0964cSRobert Mustacchi if (!nvme_nsmgmt_cmds_supported(&ctrl_data)) {
56*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_NS_MGMT_UNSUP_BY_DEV, 0,
57*f5f0964cSRobert Mustacchi "controller does not support namespace management"));
58*f5f0964cSRobert Mustacchi }
59*f5f0964cSRobert Mustacchi
60*f5f0964cSRobert Mustacchi /*
61*f5f0964cSRobert Mustacchi * See discussion in nvme_ns_create_req_init_by_csi() down below for
62*f5f0964cSRobert Mustacchi * rationale around the single error here.
63*f5f0964cSRobert Mustacchi */
64*f5f0964cSRobert Mustacchi if (sel != NVME_NS_ATTACH_CTRL_ATTACH &&
65*f5f0964cSRobert Mustacchi sel != NVME_NS_ATTACH_CTRL_DETACH) {
66*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_NS_ATTACH_BAD_SEL, 0,
67*f5f0964cSRobert Mustacchi "the system (and possibly device) does not support "
68*f5f0964cSRobert Mustacchi "attaching namespaces with selector 0x%x", sel));
69*f5f0964cSRobert Mustacchi }
70*f5f0964cSRobert Mustacchi
71*f5f0964cSRobert Mustacchi req = calloc(1, sizeof (nvme_ns_attach_req_t));
72*f5f0964cSRobert Mustacchi if (req == NULL) {
73*f5f0964cSRobert Mustacchi int e = errno;
74*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_NO_MEM, e, "failed to "
75*f5f0964cSRobert Mustacchi "allocate memory for a new nvme_ns_attach_req_t: %s",
76*f5f0964cSRobert Mustacchi strerror(e)));
77*f5f0964cSRobert Mustacchi }
78*f5f0964cSRobert Mustacchi
79*f5f0964cSRobert Mustacchi req->nar_ctrl = ctrl;
80*f5f0964cSRobert Mustacchi req->nar_sel = sel;
81*f5f0964cSRobert Mustacchi for (size_t i = 0; i < nvme_ns_attach_nfields; i++) {
82*f5f0964cSRobert Mustacchi if (nvme_ns_attach_fields[i].nlfi_def_req) {
83*f5f0964cSRobert Mustacchi req->nar_need |= 1 << i;
84*f5f0964cSRobert Mustacchi }
85*f5f0964cSRobert Mustacchi }
86*f5f0964cSRobert Mustacchi nvme_ns_attach_req_clear_need(req, NVME_NS_ATTACH_REQ_FIELD_SEL);
87*f5f0964cSRobert Mustacchi
88*f5f0964cSRobert Mustacchi *reqp = req;
89*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(ctrl));
90*f5f0964cSRobert Mustacchi }
91*f5f0964cSRobert Mustacchi
92*f5f0964cSRobert Mustacchi static const nvme_field_check_t nvme_ns_attach_check_nsid = {
93*f5f0964cSRobert Mustacchi nvme_ns_attach_fields, NVME_NS_ATTACH_REQ_FIELD_NSID,
94*f5f0964cSRobert Mustacchi NVME_ERR_NS_RANGE, 0, 0
95*f5f0964cSRobert Mustacchi };
96*f5f0964cSRobert Mustacchi
97*f5f0964cSRobert Mustacchi bool
nvme_ns_attach_req_set_nsid(nvme_ns_attach_req_t * req,uint32_t nsid)98*f5f0964cSRobert Mustacchi nvme_ns_attach_req_set_nsid(nvme_ns_attach_req_t *req, uint32_t nsid)
99*f5f0964cSRobert Mustacchi {
100*f5f0964cSRobert Mustacchi if (!nvme_field_check_one(req->nar_ctrl, nsid, "namespace attach",
101*f5f0964cSRobert Mustacchi &nvme_ns_attach_check_nsid, 0)) {
102*f5f0964cSRobert Mustacchi return (false);
103*f5f0964cSRobert Mustacchi }
104*f5f0964cSRobert Mustacchi
105*f5f0964cSRobert Mustacchi req->nar_nsid = nsid;
106*f5f0964cSRobert Mustacchi nvme_ns_attach_req_clear_need(req, NVME_NS_ATTACH_REQ_FIELD_NSID);
107*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(req->nar_ctrl));
108*f5f0964cSRobert Mustacchi }
109*f5f0964cSRobert Mustacchi
110*f5f0964cSRobert Mustacchi /*
111*f5f0964cSRobert Mustacchi * Right now we don't support setting an explicit controller list in the kernel
112*f5f0964cSRobert Mustacchi * so this is a short-hand for saying just do it for my current controller
113*f5f0964cSRobert Mustacchi * without requiring us to actually set anything here, we just need to clear
114*f5f0964cSRobert Mustacchi * that this has been explicitly set that way the target is not implicit.
115*f5f0964cSRobert Mustacchi */
116*f5f0964cSRobert Mustacchi bool
nvme_ns_attach_req_set_ctrlid_self(nvme_ns_attach_req_t * req)117*f5f0964cSRobert Mustacchi nvme_ns_attach_req_set_ctrlid_self(nvme_ns_attach_req_t *req)
118*f5f0964cSRobert Mustacchi {
119*f5f0964cSRobert Mustacchi nvme_ns_attach_req_clear_need(req, NVME_NS_ATTACH_REQ_FIELD_DPTR);
120*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(req->nar_ctrl));
121*f5f0964cSRobert Mustacchi }
122*f5f0964cSRobert Mustacchi
123*f5f0964cSRobert Mustacchi bool
nvme_ns_attach_req_exec(nvme_ns_attach_req_t * req)124*f5f0964cSRobert Mustacchi nvme_ns_attach_req_exec(nvme_ns_attach_req_t *req)
125*f5f0964cSRobert Mustacchi {
126*f5f0964cSRobert Mustacchi nvme_ctrl_t *ctrl = req->nar_ctrl;
127*f5f0964cSRobert Mustacchi nvme_ioctl_common_t common;
128*f5f0964cSRobert Mustacchi int code;
129*f5f0964cSRobert Mustacchi
130*f5f0964cSRobert Mustacchi if (req->nar_need != 0) {
131*f5f0964cSRobert Mustacchi return (nvme_field_miss_err(ctrl, nvme_ns_attach_fields,
132*f5f0964cSRobert Mustacchi nvme_ns_attach_nfields,
133*f5f0964cSRobert Mustacchi NVME_ERR_NS_ATTACH_REQ_MISSING_FIELDS, "namespace attach",
134*f5f0964cSRobert Mustacchi req->nar_need));
135*f5f0964cSRobert Mustacchi }
136*f5f0964cSRobert Mustacchi
137*f5f0964cSRobert Mustacchi (void) memset(&common, 0, sizeof (common));
138*f5f0964cSRobert Mustacchi common.nioc_nsid = req->nar_nsid;
139*f5f0964cSRobert Mustacchi
140*f5f0964cSRobert Mustacchi code = req->nar_sel == NVME_NS_ATTACH_CTRL_ATTACH ?
141*f5f0964cSRobert Mustacchi NVME_IOC_CTRL_ATTACH : NVME_IOC_CTRL_DETACH;
142*f5f0964cSRobert Mustacchi if (ioctl(ctrl->nc_fd, code, &common) != 0) {
143*f5f0964cSRobert Mustacchi int e = errno;
144*f5f0964cSRobert Mustacchi return (nvme_ioctl_syserror(ctrl, e, "namespace attach"));
145*f5f0964cSRobert Mustacchi }
146*f5f0964cSRobert Mustacchi
147*f5f0964cSRobert Mustacchi if (common.nioc_drv_err != NVME_IOCTL_E_OK) {
148*f5f0964cSRobert Mustacchi return (nvme_ioctl_error(ctrl, &common, "namespace attach"));
149*f5f0964cSRobert Mustacchi }
150*f5f0964cSRobert Mustacchi
151*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(ctrl));
152*f5f0964cSRobert Mustacchi }
153*f5f0964cSRobert Mustacchi
154*f5f0964cSRobert Mustacchi void
nvme_ns_delete_req_fini(nvme_ns_delete_req_t * req)155*f5f0964cSRobert Mustacchi nvme_ns_delete_req_fini(nvme_ns_delete_req_t *req)
156*f5f0964cSRobert Mustacchi {
157*f5f0964cSRobert Mustacchi free(req);
158*f5f0964cSRobert Mustacchi }
159*f5f0964cSRobert Mustacchi
160*f5f0964cSRobert Mustacchi bool
nvme_ns_delete_req_init(nvme_ctrl_t * ctrl,nvme_ns_delete_req_t ** reqp)161*f5f0964cSRobert Mustacchi nvme_ns_delete_req_init(nvme_ctrl_t *ctrl, nvme_ns_delete_req_t **reqp)
162*f5f0964cSRobert Mustacchi {
163*f5f0964cSRobert Mustacchi nvme_ns_delete_req_t *req;
164*f5f0964cSRobert Mustacchi nvme_valid_ctrl_data_t ctrl_data;
165*f5f0964cSRobert Mustacchi
166*f5f0964cSRobert Mustacchi if (reqp == NULL) {
167*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_BAD_PTR, 0,
168*f5f0964cSRobert Mustacchi "encountered invalid nvme_ns_delete_req_t output pointer: "
169*f5f0964cSRobert Mustacchi "%p", reqp));
170*f5f0964cSRobert Mustacchi }
171*f5f0964cSRobert Mustacchi
172*f5f0964cSRobert Mustacchi ctrl_data.vcd_vers = &ctrl->nc_vers;
173*f5f0964cSRobert Mustacchi ctrl_data.vcd_id = &ctrl->nc_info;
174*f5f0964cSRobert Mustacchi
175*f5f0964cSRobert Mustacchi if (!nvme_nsmgmt_cmds_supported(&ctrl_data)) {
176*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_NS_MGMT_UNSUP_BY_DEV, 0,
177*f5f0964cSRobert Mustacchi "controller does not support namespace management"));
178*f5f0964cSRobert Mustacchi }
179*f5f0964cSRobert Mustacchi
180*f5f0964cSRobert Mustacchi req = calloc(1, sizeof (nvme_ns_delete_req_t));
181*f5f0964cSRobert Mustacchi if (req == NULL) {
182*f5f0964cSRobert Mustacchi int e = errno;
183*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_NO_MEM, e, "failed to "
184*f5f0964cSRobert Mustacchi "allocate memory for a new nvme_ns_delete_req_t: %s",
185*f5f0964cSRobert Mustacchi strerror(e)));
186*f5f0964cSRobert Mustacchi }
187*f5f0964cSRobert Mustacchi
188*f5f0964cSRobert Mustacchi req->ndr_ctrl = ctrl;
189*f5f0964cSRobert Mustacchi for (size_t i = 0; i < nvme_ns_delete_nfields; i++) {
190*f5f0964cSRobert Mustacchi if (nvme_ns_delete_fields[i].nlfi_def_req) {
191*f5f0964cSRobert Mustacchi req->ndr_need |= 1 << i;
192*f5f0964cSRobert Mustacchi }
193*f5f0964cSRobert Mustacchi }
194*f5f0964cSRobert Mustacchi
195*f5f0964cSRobert Mustacchi *reqp = req;
196*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(ctrl));
197*f5f0964cSRobert Mustacchi }
198*f5f0964cSRobert Mustacchi
199*f5f0964cSRobert Mustacchi static void
nvme_ns_delete_req_clear_need(nvme_ns_delete_req_t * req,nvme_ns_delete_req_field_t field)200*f5f0964cSRobert Mustacchi nvme_ns_delete_req_clear_need(nvme_ns_delete_req_t *req,
201*f5f0964cSRobert Mustacchi nvme_ns_delete_req_field_t field)
202*f5f0964cSRobert Mustacchi {
203*f5f0964cSRobert Mustacchi req->ndr_need &= ~(1 << field);
204*f5f0964cSRobert Mustacchi }
205*f5f0964cSRobert Mustacchi
206*f5f0964cSRobert Mustacchi static const nvme_field_check_t nvme_ns_delete_check_nsid = {
207*f5f0964cSRobert Mustacchi nvme_ns_delete_fields, NVME_NS_DELETE_REQ_FIELD_NSID,
208*f5f0964cSRobert Mustacchi NVME_ERR_NS_RANGE, 0, 0
209*f5f0964cSRobert Mustacchi };
210*f5f0964cSRobert Mustacchi
211*f5f0964cSRobert Mustacchi bool
nvme_ns_delete_req_set_nsid(nvme_ns_delete_req_t * req,uint32_t nsid)212*f5f0964cSRobert Mustacchi nvme_ns_delete_req_set_nsid(nvme_ns_delete_req_t *req, uint32_t nsid)
213*f5f0964cSRobert Mustacchi {
214*f5f0964cSRobert Mustacchi if (!nvme_field_check_one(req->ndr_ctrl, nsid, "namespace delete",
215*f5f0964cSRobert Mustacchi &nvme_ns_delete_check_nsid, 0)) {
216*f5f0964cSRobert Mustacchi return (false);
217*f5f0964cSRobert Mustacchi }
218*f5f0964cSRobert Mustacchi
219*f5f0964cSRobert Mustacchi req->ndr_nsid = nsid;
220*f5f0964cSRobert Mustacchi nvme_ns_delete_req_clear_need(req, NVME_NS_DELETE_REQ_FIELD_NSID);
221*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(req->ndr_ctrl));
222*f5f0964cSRobert Mustacchi }
223*f5f0964cSRobert Mustacchi
224*f5f0964cSRobert Mustacchi bool
nvme_ns_delete_req_exec(nvme_ns_delete_req_t * req)225*f5f0964cSRobert Mustacchi nvme_ns_delete_req_exec(nvme_ns_delete_req_t *req)
226*f5f0964cSRobert Mustacchi {
227*f5f0964cSRobert Mustacchi nvme_ctrl_t *ctrl = req->ndr_ctrl;
228*f5f0964cSRobert Mustacchi nvme_ioctl_common_t common;
229*f5f0964cSRobert Mustacchi
230*f5f0964cSRobert Mustacchi if (req->ndr_need != 0) {
231*f5f0964cSRobert Mustacchi return (nvme_field_miss_err(ctrl, nvme_ns_delete_fields,
232*f5f0964cSRobert Mustacchi nvme_ns_delete_nfields,
233*f5f0964cSRobert Mustacchi NVME_ERR_NS_DELETE_REQ_MISSING_FIELDS, "namespace delete",
234*f5f0964cSRobert Mustacchi req->ndr_need));
235*f5f0964cSRobert Mustacchi }
236*f5f0964cSRobert Mustacchi
237*f5f0964cSRobert Mustacchi (void) memset(&common, 0, sizeof (common));
238*f5f0964cSRobert Mustacchi common.nioc_nsid = req->ndr_nsid;
239*f5f0964cSRobert Mustacchi
240*f5f0964cSRobert Mustacchi if (ioctl(ctrl->nc_fd, NVME_IOC_NS_DELETE, &common) != 0) {
241*f5f0964cSRobert Mustacchi int e = errno;
242*f5f0964cSRobert Mustacchi return (nvme_ioctl_syserror(ctrl, e, "namespace delete"));
243*f5f0964cSRobert Mustacchi }
244*f5f0964cSRobert Mustacchi
245*f5f0964cSRobert Mustacchi if (common.nioc_drv_err != NVME_IOCTL_E_OK) {
246*f5f0964cSRobert Mustacchi return (nvme_ioctl_error(ctrl, &common, "namespace delete"));
247*f5f0964cSRobert Mustacchi }
248*f5f0964cSRobert Mustacchi
249*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(ctrl));
250*f5f0964cSRobert Mustacchi }
251*f5f0964cSRobert Mustacchi
252*f5f0964cSRobert Mustacchi void
nvme_ns_create_req_fini(nvme_ns_create_req_t * req)253*f5f0964cSRobert Mustacchi nvme_ns_create_req_fini(nvme_ns_create_req_t *req)
254*f5f0964cSRobert Mustacchi {
255*f5f0964cSRobert Mustacchi free(req);
256*f5f0964cSRobert Mustacchi }
257*f5f0964cSRobert Mustacchi
258*f5f0964cSRobert Mustacchi bool
nvme_ns_create_req_init_by_csi(nvme_ctrl_t * ctrl,nvme_csi_t csi,nvme_ns_create_req_t ** reqp)259*f5f0964cSRobert Mustacchi nvme_ns_create_req_init_by_csi(nvme_ctrl_t *ctrl, nvme_csi_t csi,
260*f5f0964cSRobert Mustacchi nvme_ns_create_req_t **reqp)
261*f5f0964cSRobert Mustacchi {
262*f5f0964cSRobert Mustacchi nvme_ns_create_req_t *req;
263*f5f0964cSRobert Mustacchi nvme_valid_ctrl_data_t ctrl_data;
264*f5f0964cSRobert Mustacchi
265*f5f0964cSRobert Mustacchi if (reqp == NULL) {
266*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_BAD_PTR, 0,
267*f5f0964cSRobert Mustacchi "encountered invalid nvme_ns_create_req_t output pointer: "
268*f5f0964cSRobert Mustacchi "%p", reqp));
269*f5f0964cSRobert Mustacchi }
270*f5f0964cSRobert Mustacchi
271*f5f0964cSRobert Mustacchi ctrl_data.vcd_vers = &ctrl->nc_vers;
272*f5f0964cSRobert Mustacchi ctrl_data.vcd_id = &ctrl->nc_info;
273*f5f0964cSRobert Mustacchi
274*f5f0964cSRobert Mustacchi if (!nvme_nsmgmt_cmds_supported(&ctrl_data)) {
275*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_NS_MGMT_UNSUP_BY_DEV, 0,
276*f5f0964cSRobert Mustacchi "controller does not support namespace management"));
277*f5f0964cSRobert Mustacchi }
278*f5f0964cSRobert Mustacchi
279*f5f0964cSRobert Mustacchi /*
280*f5f0964cSRobert Mustacchi * The CSI determines what fields are supported and required. Not all
281*f5f0964cSRobert Mustacchi * CSIs support namespace creation and in addition, we only support the
282*f5f0964cSRobert Mustacchi * NVM CSI. The notion of CSIs was added in NVMe 2.0. There are several
283*f5f0964cSRobert Mustacchi * things that could go wrong here:
284*f5f0964cSRobert Mustacchi *
285*f5f0964cSRobert Mustacchi * - We could have an NVMe controller that is pre-2.0 and therefore
286*f5f0964cSRobert Mustacchi * anything other than the NVM CSI is invalid (it's implicit pre-2.0).
287*f5f0964cSRobert Mustacchi * - We could have a CSI that's just not defined by any version of the
288*f5f0964cSRobert Mustacchi * spec.
289*f5f0964cSRobert Mustacchi * - We could have a CSI that's defined by a spec that's newer than the
290*f5f0964cSRobert Mustacchi * device.
291*f5f0964cSRobert Mustacchi * - The CSI may not support namespace creation. The device may not even
292*f5f0964cSRobert Mustacchi * support the CSI!
293*f5f0964cSRobert Mustacchi *
294*f5f0964cSRobert Mustacchi * In addition, the kernel doesn't support anything other than the NVM
295*f5f0964cSRobert Mustacchi * CSI today. Rather than break these all apart, we give a generic error
296*f5f0964cSRobert Mustacchi * message about this. We can make this higher fidelity in the future.
297*f5f0964cSRobert Mustacchi */
298*f5f0964cSRobert Mustacchi if (csi != NVME_CSI_NVM) {
299*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_NS_CREATE_BAD_CSI, 0,
300*f5f0964cSRobert Mustacchi "the system (and possibly device) does not support "
301*f5f0964cSRobert Mustacchi "creating namespaces with CSI 0x%x", csi));
302*f5f0964cSRobert Mustacchi }
303*f5f0964cSRobert Mustacchi
304*f5f0964cSRobert Mustacchi req = calloc(1, sizeof (nvme_ns_create_req_t));
305*f5f0964cSRobert Mustacchi if (req == NULL) {
306*f5f0964cSRobert Mustacchi int e = errno;
307*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(ctrl, NVME_ERR_NO_MEM, e, "failed to "
308*f5f0964cSRobert Mustacchi "allocate memory for a new nvme_ns_create_req_t: %s",
309*f5f0964cSRobert Mustacchi strerror(e)));
310*f5f0964cSRobert Mustacchi }
311*f5f0964cSRobert Mustacchi
312*f5f0964cSRobert Mustacchi for (size_t i = 0; i < nvme_ns_create_fields_nvm_nreq; i++) {
313*f5f0964cSRobert Mustacchi req->ncr_need |= 1 << nvme_ns_create_fields_nvm_req[i];
314*f5f0964cSRobert Mustacchi }
315*f5f0964cSRobert Mustacchi
316*f5f0964cSRobert Mustacchi for (size_t i = 0; i < nvme_ns_create_fields_nvm_nallow; i++) {
317*f5f0964cSRobert Mustacchi req->ncr_allow |= 1 << nvme_ns_create_fields_nvm_allow[i];
318*f5f0964cSRobert Mustacchi }
319*f5f0964cSRobert Mustacchi
320*f5f0964cSRobert Mustacchi req->ncr_ctrl = ctrl;
321*f5f0964cSRobert Mustacchi req->ncr_csi = csi;
322*f5f0964cSRobert Mustacchi
323*f5f0964cSRobert Mustacchi *reqp = req;
324*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(ctrl));
325*f5f0964cSRobert Mustacchi }
326*f5f0964cSRobert Mustacchi
327*f5f0964cSRobert Mustacchi static void
nvme_ns_create_req_clear_need(nvme_ns_create_req_t * req,nvme_ns_create_req_field_t field)328*f5f0964cSRobert Mustacchi nvme_ns_create_req_clear_need(nvme_ns_create_req_t *req,
329*f5f0964cSRobert Mustacchi nvme_ns_create_req_field_t field)
330*f5f0964cSRobert Mustacchi {
331*f5f0964cSRobert Mustacchi req->ncr_need &= ~(1 << field);
332*f5f0964cSRobert Mustacchi }
333*f5f0964cSRobert Mustacchi
334*f5f0964cSRobert Mustacchi static const nvme_field_check_t nvme_ns_create_check_flbas = {
335*f5f0964cSRobert Mustacchi nvme_ns_create_fields, NVME_NS_CREATE_REQ_FIELD_FLBAS,
336*f5f0964cSRobert Mustacchi NVME_ERR_NS_CREATE_FLBAS_RANGE, 0, 0
337*f5f0964cSRobert Mustacchi };
338*f5f0964cSRobert Mustacchi
339*f5f0964cSRobert Mustacchi bool
nvme_ns_create_req_set_flbas(nvme_ns_create_req_t * req,uint32_t flbas)340*f5f0964cSRobert Mustacchi nvme_ns_create_req_set_flbas(nvme_ns_create_req_t *req, uint32_t flbas)
341*f5f0964cSRobert Mustacchi {
342*f5f0964cSRobert Mustacchi if (!nvme_field_check_one(req->ncr_ctrl, flbas, "namespace create",
343*f5f0964cSRobert Mustacchi &nvme_ns_create_check_flbas, req->ncr_allow)) {
344*f5f0964cSRobert Mustacchi return (false);
345*f5f0964cSRobert Mustacchi }
346*f5f0964cSRobert Mustacchi
347*f5f0964cSRobert Mustacchi req->ncr_flbas = flbas;
348*f5f0964cSRobert Mustacchi nvme_ns_create_req_clear_need(req, NVME_NS_CREATE_REQ_FIELD_FLBAS);
349*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(req->ncr_ctrl));
350*f5f0964cSRobert Mustacchi }
351*f5f0964cSRobert Mustacchi
352*f5f0964cSRobert Mustacchi static const nvme_field_check_t nvme_ns_create_check_nsze = {
353*f5f0964cSRobert Mustacchi nvme_ns_create_fields, NVME_NS_CREATE_REQ_FIELD_NSZE,
354*f5f0964cSRobert Mustacchi NVME_ERR_NS_CREATE_NSZE_RANGE, 0, 0
355*f5f0964cSRobert Mustacchi };
356*f5f0964cSRobert Mustacchi
357*f5f0964cSRobert Mustacchi bool
nvme_ns_create_req_set_nsze(nvme_ns_create_req_t * req,uint64_t nsze)358*f5f0964cSRobert Mustacchi nvme_ns_create_req_set_nsze(nvme_ns_create_req_t *req, uint64_t nsze)
359*f5f0964cSRobert Mustacchi {
360*f5f0964cSRobert Mustacchi if (!nvme_field_check_one(req->ncr_ctrl, nsze, "namespace create",
361*f5f0964cSRobert Mustacchi &nvme_ns_create_check_nsze, req->ncr_allow)) {
362*f5f0964cSRobert Mustacchi return (false);
363*f5f0964cSRobert Mustacchi }
364*f5f0964cSRobert Mustacchi
365*f5f0964cSRobert Mustacchi req->ncr_nsze = nsze;
366*f5f0964cSRobert Mustacchi nvme_ns_create_req_clear_need(req, NVME_NS_CREATE_REQ_FIELD_NSZE);
367*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(req->ncr_ctrl));
368*f5f0964cSRobert Mustacchi }
369*f5f0964cSRobert Mustacchi
370*f5f0964cSRobert Mustacchi static const nvme_field_check_t nvme_ns_create_check_ncap = {
371*f5f0964cSRobert Mustacchi nvme_ns_create_fields, NVME_NS_CREATE_REQ_FIELD_NCAP,
372*f5f0964cSRobert Mustacchi NVME_ERR_NS_CREATE_NCAP_RANGE, 0, 0
373*f5f0964cSRobert Mustacchi };
374*f5f0964cSRobert Mustacchi
375*f5f0964cSRobert Mustacchi bool
nvme_ns_create_req_set_ncap(nvme_ns_create_req_t * req,uint64_t ncap)376*f5f0964cSRobert Mustacchi nvme_ns_create_req_set_ncap(nvme_ns_create_req_t *req, uint64_t ncap)
377*f5f0964cSRobert Mustacchi {
378*f5f0964cSRobert Mustacchi if (!nvme_field_check_one(req->ncr_ctrl, ncap, "namespace create",
379*f5f0964cSRobert Mustacchi &nvme_ns_create_check_ncap, req->ncr_allow)) {
380*f5f0964cSRobert Mustacchi return (false);
381*f5f0964cSRobert Mustacchi }
382*f5f0964cSRobert Mustacchi
383*f5f0964cSRobert Mustacchi req->ncr_ncap = ncap;
384*f5f0964cSRobert Mustacchi nvme_ns_create_req_clear_need(req, NVME_NS_CREATE_REQ_FIELD_NCAP);
385*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(req->ncr_ctrl));
386*f5f0964cSRobert Mustacchi }
387*f5f0964cSRobert Mustacchi
388*f5f0964cSRobert Mustacchi static const nvme_field_check_t nvme_ns_create_check_nmic = {
389*f5f0964cSRobert Mustacchi nvme_ns_create_fields, NVME_NS_CREATE_REQ_FIELD_NMIC,
390*f5f0964cSRobert Mustacchi NVME_ERR_NS_CREATE_NMIC_RANGE, 0, 0
391*f5f0964cSRobert Mustacchi };
392*f5f0964cSRobert Mustacchi
393*f5f0964cSRobert Mustacchi bool
nvme_ns_create_req_set_nmic(nvme_ns_create_req_t * req,uint32_t nmic)394*f5f0964cSRobert Mustacchi nvme_ns_create_req_set_nmic(nvme_ns_create_req_t *req, uint32_t nmic)
395*f5f0964cSRobert Mustacchi {
396*f5f0964cSRobert Mustacchi if (!nvme_field_check_one(req->ncr_ctrl, nmic, "namespace create",
397*f5f0964cSRobert Mustacchi &nvme_ns_create_check_nmic, req->ncr_allow)) {
398*f5f0964cSRobert Mustacchi return (false);
399*f5f0964cSRobert Mustacchi }
400*f5f0964cSRobert Mustacchi
401*f5f0964cSRobert Mustacchi req->ncr_nmic = nmic;
402*f5f0964cSRobert Mustacchi nvme_ns_create_req_clear_need(req, NVME_NS_CREATE_REQ_FIELD_NMIC);
403*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(req->ncr_ctrl));
404*f5f0964cSRobert Mustacchi }
405*f5f0964cSRobert Mustacchi
406*f5f0964cSRobert Mustacchi bool
nvme_ns_create_req_get_nsid(nvme_ns_create_req_t * req,uint32_t * nsid)407*f5f0964cSRobert Mustacchi nvme_ns_create_req_get_nsid(nvme_ns_create_req_t *req, uint32_t *nsid)
408*f5f0964cSRobert Mustacchi {
409*f5f0964cSRobert Mustacchi if (nsid == NULL) {
410*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(req->ncr_ctrl, NVME_ERR_BAD_PTR, 0,
411*f5f0964cSRobert Mustacchi "encountered invalid nsid output pointer: %p", nsid));
412*f5f0964cSRobert Mustacchi }
413*f5f0964cSRobert Mustacchi
414*f5f0964cSRobert Mustacchi if (!req->ncr_results_valid) {
415*f5f0964cSRobert Mustacchi return (nvme_ctrl_error(req->ncr_ctrl,
416*f5f0964cSRobert Mustacchi NVME_ERR_NS_CREATE_NO_RESULTS, 0, "namespace create "
417*f5f0964cSRobert Mustacchi "results are not currently valid and cannot be returned"));
418*f5f0964cSRobert Mustacchi }
419*f5f0964cSRobert Mustacchi
420*f5f0964cSRobert Mustacchi *nsid = req->ncr_nsid;
421*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(req->ncr_ctrl));
422*f5f0964cSRobert Mustacchi }
423*f5f0964cSRobert Mustacchi
424*f5f0964cSRobert Mustacchi bool
nvme_ns_create_req_exec(nvme_ns_create_req_t * req)425*f5f0964cSRobert Mustacchi nvme_ns_create_req_exec(nvme_ns_create_req_t *req)
426*f5f0964cSRobert Mustacchi {
427*f5f0964cSRobert Mustacchi nvme_ctrl_t *ctrl = req->ncr_ctrl;
428*f5f0964cSRobert Mustacchi nvme_ioctl_ns_create_t create;
429*f5f0964cSRobert Mustacchi
430*f5f0964cSRobert Mustacchi /*
431*f5f0964cSRobert Mustacchi * Immediately invalidate our results if someone calls this again.
432*f5f0964cSRobert Mustacchi */
433*f5f0964cSRobert Mustacchi req->ncr_results_valid = false;
434*f5f0964cSRobert Mustacchi req->ncr_nsid = 0;
435*f5f0964cSRobert Mustacchi
436*f5f0964cSRobert Mustacchi if (req->ncr_need != 0) {
437*f5f0964cSRobert Mustacchi return (nvme_field_miss_err(ctrl, nvme_ns_create_fields,
438*f5f0964cSRobert Mustacchi nvme_ns_create_nfields,
439*f5f0964cSRobert Mustacchi NVME_ERR_NS_CREATE_REQ_MISSING_FIELDS, "namespace create",
440*f5f0964cSRobert Mustacchi req->ncr_need));
441*f5f0964cSRobert Mustacchi }
442*f5f0964cSRobert Mustacchi
443*f5f0964cSRobert Mustacchi (void) memset(&create, 0, sizeof (create));
444*f5f0964cSRobert Mustacchi create.nnc_nsze = req->ncr_nsze;
445*f5f0964cSRobert Mustacchi create.nnc_ncap = req->ncr_ncap;
446*f5f0964cSRobert Mustacchi create.nnc_csi = req->ncr_csi;
447*f5f0964cSRobert Mustacchi create.nnc_flbas = req->ncr_flbas;
448*f5f0964cSRobert Mustacchi create.nnc_nmic = req->ncr_nmic;
449*f5f0964cSRobert Mustacchi
450*f5f0964cSRobert Mustacchi if (ioctl(ctrl->nc_fd, NVME_IOC_NS_CREATE, &create) != 0) {
451*f5f0964cSRobert Mustacchi int e = errno;
452*f5f0964cSRobert Mustacchi return (nvme_ioctl_syserror(ctrl, e, "namespace create"));
453*f5f0964cSRobert Mustacchi }
454*f5f0964cSRobert Mustacchi
455*f5f0964cSRobert Mustacchi if (create.nnc_common.nioc_drv_err != NVME_IOCTL_E_OK) {
456*f5f0964cSRobert Mustacchi return (nvme_ioctl_error(ctrl, &create.nnc_common,
457*f5f0964cSRobert Mustacchi "namespace create"));
458*f5f0964cSRobert Mustacchi }
459*f5f0964cSRobert Mustacchi
460*f5f0964cSRobert Mustacchi req->ncr_results_valid = true;
461*f5f0964cSRobert Mustacchi req->ncr_nsid = create.nnc_nsid;
462*f5f0964cSRobert Mustacchi return (nvme_ctrl_success(ctrl));
463*f5f0964cSRobert Mustacchi }
464