xref: /illumos-gate/usr/src/lib/libnvme/common/libnvme_error.c (revision f5f0964ce91892f7482efc86903b0ec7c7b6ba66)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2025 Oxide Computer Company
14  */
15 
16 /*
17  * libnvme error manipulation and translation. This maintains the error objects
18  * that we have on handles and provides translations between the kernel's errors
19  * and those that we might generate ourselves. Information errors are instead
20  * contained in the corresponding files that own controller and namespace
21  * information libnvme_ctrl_info.c and libnvme_ns_info.c respectively.
22  */
23 
24 #include <string.h>
25 #include <stdarg.h>
26 #include <sys/debug.h>
27 #include <sys/sysmacros.h>
28 #include <upanic.h>
29 
30 #include "libnvme_impl.h"
31 
32 /*
33  * The following sets of functions provide translations of error types. Note,
34  * the kernel headers need to be updated for newer NVMe specs at which point
35  * these should be updated.
36  */
37 const char *
nvme_scttostr(nvme_ctrl_t * ctrl __unused,uint32_t sc)38 nvme_scttostr(nvme_ctrl_t *ctrl __unused, uint32_t sc)
39 {
40 	switch (sc) {
41 	case NVME_CQE_SCT_GENERIC:
42 		return ("generic command status");
43 	case NVME_CQE_SCT_SPECIFIC:
44 		return ("command specific status");
45 	case NVME_CQE_SCT_INTEGRITY:
46 		return ("media and data integrity errors");
47 	case NVME_CQE_SCT_VENDOR:
48 		return ("vendor specific");
49 	default:
50 		return ("unknown status type");
51 	}
52 }
53 
54 static const char *
nvme_sctostr_gen_gen(uint32_t sct)55 nvme_sctostr_gen_gen(uint32_t sct)
56 {
57 	switch (sct) {
58 	case NVME_CQE_SC_GEN_SUCCESS:
59 		return ("successful completion");
60 	case NVME_CQE_SC_GEN_INV_OPC:
61 		return ("invalid command opcode");
62 	case NVME_CQE_SC_GEN_INV_FLD:
63 		return ("invalid field in command");
64 	case NVME_CQE_SC_GEN_ID_CNFL:
65 		return ("command id conflict");
66 	case NVME_CQE_SC_GEN_DATA_XFR_ERR:
67 		return ("data transfer error");
68 	case NVME_CQE_SC_GEN_ABORT_PWRLOSS:
69 		return ("commands aborted due to power loss notification");
70 	case NVME_CQE_SC_GEN_INTERNAL_ERR:
71 		return ("internal error");
72 	case NVME_CQE_SC_GEN_ABORT_REQUEST:
73 		return ("command abort requested");
74 	case NVME_CQE_SC_GEN_ABORT_SQ_DEL:
75 		return ("command aborted due to sq deletion");
76 	case NVME_CQE_SC_GEN_ABORT_FUSE_FAIL:
77 		return ("command aborted due to failed fused command");
78 	case NVME_CQE_SC_GEN_ABORT_FUSE_MISS:
79 		return ("command aborted due to missing fused command");
80 	case NVME_CQE_SC_GEN_INV_NS:
81 		return ("invalid namespace or format");
82 	case NVME_CQE_SC_GEN_CMD_SEQ_ERR:
83 		return ("command sequence error");
84 	case NVME_CQE_SC_GEN_INV_SGL_LAST:
85 		return ("invalid sgl last segment descriptor");
86 	case NVME_CQE_SC_GEN_INV_SGL_NUM:
87 		return ("invalid number of sgl descriptors");
88 	case NVME_CQE_SC_GEN_INV_DSGL_LEN:
89 		return ("data sgl length invalid");
90 	case NVME_CQE_SC_GEN_INV_MSGL_LEN:
91 		return ("metadata sgl length invalid");
92 	case NVME_CQE_SC_GEN_INV_SGL_DESC:
93 		return ("sgl descriptor type invalid");
94 	case NVME_CQE_SC_GEN_INV_USE_CMB:
95 		return ("invalid use of controller memory buffer");
96 	case NVME_CQE_SC_GEN_INV_PRP_OFF:
97 		return ("prp offset invalid");
98 	case NVME_CQE_SC_GEN_AWU_EXCEEDED:
99 		return ("atomic write unit exceeded");
100 	case NVME_CQE_SC_GEN_OP_DENIED:
101 		return ("operation denied");
102 	case NVME_CQE_SC_GEN_INV_SGL_OFF:
103 		return ("sgl offset invalid");
104 	case NVME_CQE_SC_GEN_INV_SGL_ST:
105 		return ("sgl sub type invalid");
106 	case NVME_CQE_SC_GEN_INCON_HOSTID:
107 		return ("host identifier inconsistent format");
108 	case NVME_CQE_SC_GEN_KA_EXP:
109 		return ("keep alive timer expired");
110 	case NVME_CQE_SC_GEN_INV_KA_TO:
111 		return ("keep alive timeout invalid");
112 	case NVME_CQE_SC_GEN_ABORT_PREEMPT:
113 		return ("command aborted due to preempt and abort");
114 	case NVME_CQE_SC_GEN_SANITIZE_FAIL:
115 		return ("sanitize failed");
116 	case NVME_CQE_SC_GEN_SANITIZING:
117 		return ("sanitize in progress");
118 	case NVME_CQE_SC_GEN_INV_SGL_GRAN:
119 		return ("sgl data block granularity invalid");
120 	case NVME_CQE_SC_GEN_NO_CMD_Q_CMD:
121 		return ("command not supported for queue in cmb");
122 	case NVME_CQE_SC_GEN_NS_RDONLY:
123 		return ("namespace is write protected");
124 	case NVME_CQE_SC_GEN_CMD_INTR:
125 		return ("command interrupted");
126 	case NVME_CQE_SC_GEN_TRANSIENT:
127 		return ("transient transport error");
128 	case NVME_CQE_SC_GEN_CMD_LOCK:
129 		return ("command prohibited by command and feature lockdown");
130 	case NVME_CQE_SC_ADM_MEDIA_NR:
131 		return ("admin command media not ready");
132 	default:
133 		return ("unknown status code");
134 	}
135 }
136 
137 static const char *
nvme_sctostr_gen_csi(nvme_csi_t csi,uint32_t sct)138 nvme_sctostr_gen_csi(nvme_csi_t csi, uint32_t sct)
139 {
140 	/*
141 	 * These errors are allowed for all command sets.
142 	 */
143 	switch (sct) {
144 	case NVME_CQE_SC_GEN_NVM_CAP_EXC:
145 		return ("capacity exceeded");
146 	case NVME_CQE_SC_GEN_NVM_NS_NOTRDY:
147 		return ("namespace not ready");
148 	case NVME_CQE_SC_GEN_NVM_RSV_CNFLCT:
149 		return ("reservation conflict");
150 	default:
151 		break;
152 	}
153 
154 	switch (csi) {
155 	case NVME_CSI_NVM:
156 	case NVME_CSI_ZNS:
157 		switch (sct) {
158 		case NVME_CQE_SC_GEN_NVM_LBA_RANGE:
159 			return ("lba out of range");
160 		case NVME_CQE_SC_GEN_NVM_FORMATTING:
161 			return ("format in progress");
162 		default:
163 			break;
164 		}
165 		break;
166 	case NVME_CSI_KV:
167 		switch (sct) {
168 		case NVME_CQE_SC_GEN_KEY_INV_VAL:
169 			return ("invalid value size");
170 		case NVME_CQE_SC_GEN_KEY_INV_KEY:
171 			return ("invalid key size");
172 		case NVME_CQE_SC_GEN_KEY_ENOENT:
173 			return ("kv key does not exist");
174 		case NVME_CQE_SC_GEN_KEY_UNRECOV:
175 			return ("unrecovered error");
176 		case NVME_CQE_SC_GEN_KEY_EXISTS:
177 			return ("key exists");
178 		default:
179 			break;
180 		}
181 		break;
182 	default:
183 		break;
184 	}
185 
186 	return ("unknown command set specific general status code");
187 }
188 
189 static const char *
nvme_sctostr_cmd_gen(uint32_t sct)190 nvme_sctostr_cmd_gen(uint32_t sct)
191 {
192 	switch (sct) {
193 	case NVME_CQE_SC_SPC_INV_CQ	:
194 		return ("completion queue invalid");
195 	case NVME_CQE_SC_SPC_INV_QID	:
196 		return ("invalid queue identifier");
197 	case NVME_CQE_SC_SPC_MAX_QSZ_EXC:
198 		return ("max queue size exceeded");
199 	case NVME_CQE_SC_SPC_ABRT_CMD_EXC:
200 		return ("abort command limit exceeded");
201 	case NVME_CQE_SC_SPC_ASYNC_EVREQ_EXC:
202 		return ("asynchronous event request limit");
203 	case NVME_CQE_SC_SPC_INV_FW_SLOT:
204 		return ("invalid firmware slot");
205 	case NVME_CQE_SC_SPC_INV_FW_IMG:
206 		return ("invalid firmware image");
207 	case NVME_CQE_SC_SPC_INV_INT_VECT:
208 		return ("invalid interrupt vector");
209 	case NVME_CQE_SC_SPC_INV_LOG_PAGE:
210 		return ("invalid log page");
211 	case NVME_CQE_SC_SPC_INV_FORMAT:
212 		return ("invalid format");
213 	case NVME_CQE_SC_SPC_FW_RESET:
214 		return ("firmware activation requires conventional reset");
215 	case NVME_CQE_SC_SPC_INV_Q_DEL:
216 		return ("invalid queue deletion");
217 	case NVME_CQE_SC_SPC_FEAT_SAVE:
218 		return ("feature identifier not saveable");
219 	case NVME_CQE_SC_SPC_FEAT_CHG:
220 		return ("feature not changeable");
221 	case NVME_CQE_SC_SPC_FEAT_NS_SPEC:
222 		return ("feature not namespace spec");
223 	case NVME_CQE_SC_SPC_FW_NSSR	:
224 		return ("firmware activation requires nvm subsystem reset");
225 	case NVME_CQE_SC_SPC_FW_NEXT_RESET:
226 		return ("firmware activation requires controller level reset");
227 	case NVME_CQE_SC_SPC_FW_MTFA	:
228 		return ("firmware activation requires maximum time violation");
229 	case NVME_CQE_SC_SPC_FW_PROHIBITED:
230 		return ("firmware activation prohibited");
231 	case NVME_CQE_SC_SPC_FW_OVERLAP:
232 		return ("overlapping range");
233 	case NVME_CQE_SC_SPC_NS_INSUF_CAP:
234 		return ("namespace insufficient capacity");
235 	case NVME_CQE_SC_SPC_NS_NO_ID:
236 		return ("namespace identifier unavailable");
237 	case NVME_CQE_SC_SPC_NS_ATTACHED:
238 		return ("namespace already attached");
239 	case NVME_CQE_SC_SPC_NS_PRIV:
240 		return ("namespace is private");
241 	case NVME_CQE_SC_SPC_NS_NOT_ATTACH:
242 		return ("namespace is not attached");
243 	case NVME_CQE_SC_SPC_THIN_ENOTSUP:
244 		return ("thin provisioning not supported");
245 	case NVME_CQE_SC_SPC_INV_CTRL_LIST:
246 		return ("controller list invalid");
247 	case NVME_CQE_SC_SPC_SELF_TESTING:
248 		return ("device self-test in progress");
249 	case NVME_CQE_SC_SPC_NO_BP_WRITE:
250 		return ("boot partition write protected");
251 	case NVME_CQE_SC_SPC_INV_CTRL_ID:
252 		return ("invalid controller identifier");
253 	case NVME_CQE_SC_SPC_INV_SEC_CTRL:
254 		return ("invalid secondary controller state");
255 	case NVME_CQE_SC_SPC_INV_CTRL_NRSRC:
256 		return ("invalid number of controller resources");
257 	case NVME_CQE_SC_SPC_INV_RSRC_ID:
258 		return ("Invalid resource identifier");
259 	case NVME_CQE_SC_SPC_NO_SAN_PMR:
260 		return ("sanitize prohibited while persistent memory region "
261 		    "is enabled");
262 	case NVME_CQE_SC_SPC_INV_ANA_GID:
263 		return ("ana group identifier invalid");
264 	case NVME_CQE_SC_SPC_ANA_ATTACH:
265 		return ("ana attach failed");
266 	case NVME_CQE_SC_SPC_INSUF_CAP:
267 		return ("insufficient capacity");
268 	case NVME_CQE_SC_SPC_NS_ATTACH_LIM:
269 		return ("namespace attachment limit exceeded");
270 	case NVME_CQE_SC_SPC_LOCKDOWN_UNSUP:
271 		return ("prohibition of command execution not supported");
272 	case NVME_CQE_SC_SPC_UNSUP_IO_CMD:
273 		return ("I/O command set not supported");
274 	case NVME_CQE_SC_SPC_DIS_IO_CMD:
275 		return ("I/O command set not enabled");
276 	case NVME_CQE_SC_SPC_INV_CMD_COMBO:
277 		return ("I/O command set combination rejected");
278 	case NVME_CQE_SC_SPC_INV_IO_CMD:
279 		return ("Invalid I/O command set");
280 	case NVME_CQE_SC_SPC_UNAVAIL_ID:
281 		return ("identifier unavailable");
282 	default:
283 		return ("unknown generic command status code");
284 	}
285 }
286 
287 /*
288  * The NVMe 2.0c spec that introduces many of the zoned related errors has
289  * footnotes to suggest some of these are command set specific, but does not
290  * mark any of them. For the moment we basically assume that they're valid
291  * everywhere due to the fact that they don't overlap.
292  */
293 static const char *
nvme_sctostr_cmd_csi(nvme_csi_t csi,uint32_t sct)294 nvme_sctostr_cmd_csi(nvme_csi_t csi, uint32_t sct)
295 {
296 	switch (sct) {
297 	case NVME_CQE_SC_SPC_NVM_CNFL_ATTR:
298 		return ("conflicting attributes");
299 	case NVME_CQE_SC_SPC_NVM_INV_PROT:
300 		return ("invalid protection");
301 	case NVME_CQE_SC_SPC_NVM_READONLY:
302 		return ("write to read only range");
303 	case NVME_CQE_SC_SPC_ZONE_BDRY_ERR:
304 		return ("zoned boundary error");
305 	case NVME_CQE_SC_SPC_ZONE_FULL:
306 		return ("zone is full");
307 	case NVME_CQE_SC_SPC_ZONE_RDONLY:
308 		return ("zone is read only");
309 	case NVME_CQE_SC_SPC_ZONE_OFFLINE:
310 		return ("zone is offline");
311 	case NVME_CQE_SC_SPC_ZONE_INV_WRITE:
312 		return ("zone invalid write");
313 	case NVME_CQE_SC_SPC_ZONE_ACT:
314 		return ("too many active zones");
315 	case NVME_CQE_SC_SPC_ZONE_OPEN:
316 		return ("too many open zones");
317 	case NVME_CQE_SC_SPC_INV_ZONE_TRANS:
318 		return ("invalid zone state transition");
319 	default:
320 		return ("unknown command specific, I/O command set specific "
321 		    "status code");
322 	}
323 }
324 
325 static const char *
nvme_sctostr_media(nvme_csi_t csi,uint32_t sct)326 nvme_sctostr_media(nvme_csi_t csi, uint32_t sct)
327 {
328 	if (sct >= NVME_CQE_SC_VEND_MIN) {
329 		return ("vendor specific media and data integrity status code");
330 	}
331 
332 	/*
333 	 * Unlike NVMe 1.x, NVMe 2.x declares the following command set
334 	 * independent.
335 	 */
336 	switch (sct) {
337 	case NVME_CQE_SC_INT_NVM_WRITE:
338 		return ("write fault");
339 	case NVME_CQE_SC_INT_NVM_READ:
340 		return ("unrecovered read error");
341 	case NVME_CQE_SC_INT_NVM_GUARD:
342 		return ("guard check error");
343 	case NVME_CQE_SC_INT_NVM_APPL_TAG:
344 		return ("application tag check err");
345 	case NVME_CQE_SC_INT_NVM_REF_TAG:
346 		return ("reference tag check err");
347 	case NVME_CQE_SC_INT_NVM_ACCESS:
348 		return ("access denied");
349 	case NVME_CQE_SC_INT_NVM_TAG:
350 		return ("end-to-end storage tag check error");
351 	default:
352 		break;
353 	}
354 
355 	/*
356 	 * The only command-set specific values are currently defined for the
357 	 * NVM command set.
358 	 */
359 	if (csi != NVME_CSI_NVM) {
360 		return ("unknown media and data integrity status code");
361 	}
362 
363 	switch (sct) {
364 	case NVME_CQE_SC_INT_NVM_COMPARE:
365 		return ("compare failure");
366 	case NVME_CQE_SC_INT_NVM_DEALLOC:
367 		return ("deallocated or unwritten logical block");
368 	default:
369 		return ("unknown media and data integrity status code");
370 	}
371 }
372 
373 static const char *
nvme_sctostr_path(uint32_t sct)374 nvme_sctostr_path(uint32_t sct)
375 {
376 	switch (sct) {
377 	case NVME_CQE_SC_PATH_INT_ERR:
378 		return ("internal path error");
379 	case NVME_CQE_SC_PATH_AA_PLOSS:
380 		return ("asymmetric access persistent loss");
381 	case NVME_CQE_SC_PATH_AA_INACC:
382 		return ("asymmetric access inaccessible");
383 	case NVME_CQE_SC_PATH_AA_TRANS:
384 		return ("asymmetric access transition");
385 	case NVME_CQE_SC_PATH_CTRL_ERR:
386 		return ("controller pathing error");
387 	case NVME_CQE_SC_PATH_HOST_ERR:
388 		return ("host pathing error");
389 	case NVME_CQE_SC_PATH_HOST_ABRT:
390 		return ("command aborted by host");
391 	default:
392 		return ("unknown path related status code");
393 	}
394 }
395 
396 const char *
nvme_sctostr(nvme_ctrl_t * ctrl __unused,nvme_csi_t csi,uint32_t sct,uint32_t sc)397 nvme_sctostr(nvme_ctrl_t *ctrl __unused, nvme_csi_t csi, uint32_t sct,
398     uint32_t sc)
399 {
400 	switch (sct) {
401 	case NVME_CQE_SCT_GENERIC:
402 		if (sc <= NVME_CQE_SC_GEN_MAX) {
403 			return (nvme_sctostr_gen_gen(sc));
404 		} else if (sc <= NVME_CQE_SC_CSI_MAX) {
405 			return (nvme_sctostr_gen_csi(csi, sc));
406 		} else {
407 			return ("generic vendor specific status code");
408 		}
409 	case NVME_CQE_SCT_SPECIFIC:
410 		if (sc <= NVME_CQE_SC_GEN_MAX) {
411 			return (nvme_sctostr_cmd_gen(sc));
412 		} else if (sc <= NVME_CQE_SC_CSI_MAX) {
413 			return (nvme_sctostr_cmd_csi(csi, sc));
414 		} else {
415 			return ("command specific vendor specific status code");
416 		}
417 	case NVME_CQE_SCT_INTEGRITY:
418 		return (nvme_sctostr_media(csi, sc));
419 	case NVME_CQE_SCT_PATH:
420 		return (nvme_sctostr_path(sc));
421 	case NVME_CQE_SCT_VENDOR:
422 		return ("vendor specific");
423 	default:
424 		return ("unknown status code");
425 	}
426 }
427 
428 nvme_err_t
nvme_err(nvme_t * nvme)429 nvme_err(nvme_t *nvme)
430 {
431 	return (nvme->nh_err.ne_err);
432 }
433 
434 int32_t
nvme_syserr(nvme_t * nvme)435 nvme_syserr(nvme_t *nvme)
436 {
437 	return (nvme->nh_err.ne_syserr);
438 }
439 
440 const char *
nvme_errmsg(nvme_t * nvme)441 nvme_errmsg(nvme_t *nvme)
442 {
443 	return (nvme->nh_err.ne_errmsg);
444 }
445 
446 size_t
nvme_errlen(nvme_t * nvme)447 nvme_errlen(nvme_t *nvme)
448 {
449 	return (nvme->nh_err.ne_errlen);
450 }
451 
452 const char *
nvme_errtostr(nvme_t * nvme,nvme_err_t err)453 nvme_errtostr(nvme_t *nvme, nvme_err_t err)
454 {
455 	switch (err) {
456 	case NVME_ERR_OK:
457 		return ("NVME_ERR_OK");
458 	case NVME_ERR_CONTROLLER:
459 		return ("NVME_ERR_CONTROLLER");
460 	case NVME_ERR_NO_MEM:
461 		return ("NVME_ERR_NO_MEM");
462 	case NVME_ERR_NO_DMA_MEM:
463 		return ("NVME_ERR_NO_DMA_MEM");
464 	case NVME_ERR_LIBDEVINFO:
465 		return ("NVME_ERR_LIBDEVINFO");
466 	case NVME_ERR_INTERNAL:
467 		return ("NVME_ERR_INTERNAL");
468 	case NVME_ERR_BAD_PTR:
469 		return ("NVME_ERR_BAD_PTR");
470 	case NVME_ERR_BAD_FLAG:
471 		return ("NVME_ERR_BAD_FLAG");
472 	case NVME_ERR_BAD_DEVI:
473 		return ("NVME_ERR_BAD_DEVI");
474 	case NVME_ERR_BAD_DEVI_PROP:
475 		return ("NVME_ERR_BAD_DEVI_PROP");
476 	case NVME_ERR_ILLEGAL_INSTANCE:
477 		return ("NVME_ERR_ILLEGAL_INSTANCE");
478 	case NVME_ERR_BAD_CONTROLLER:
479 		return ("NVME_ERR_BAD_CONTROLLER");
480 	case NVME_ERR_PRIVS:
481 		return ("NVME_ERR_PRIVS");
482 	case NVME_ERR_OPEN_DEV:
483 		return ("NVME_ERR_OPEN_DEV");
484 	case NVME_ERR_BAD_RESTORE:
485 		return ("NVME_ERR_BAD_RESTORE");
486 	case NVME_ERR_NS_RANGE:
487 		return ("NVME_ERR_NS_RANGE");
488 	case NVME_ERR_NS_UNUSE:
489 		return ("NVME_ERR_NS_UNUSE");
490 	case NVME_ERR_LOG_CSI_RANGE:
491 		return ("NVME_ERR_LOG_CSI_RANGE");
492 	case NVME_ERR_LOG_LID_RANGE:
493 		return ("NVME_ERR_LOG_LID_RANGE");
494 	case NVME_ERR_LOG_LSP_RANGE:
495 		return ("NVME_ERR_LOG_LSP_RANGE");
496 	case NVME_ERR_LOG_LSI_RANGE:
497 		return ("NVME_ERR_LOG_LSI_RANGE");
498 	case NVME_ERR_LOG_RAE_RANGE:
499 		return ("NVME_ERR_LOG_RAE_RANGE");
500 	case NVME_ERR_LOG_SIZE_RANGE:
501 		return ("NVME_ERR_LOG_SIZE_RANGE");
502 	case NVME_ERR_LOG_OFFSET_RANGE:
503 		return ("NVME_ERR_LOG_OFFSET_RANGE");
504 	case NVME_ERR_LOG_CSI_UNSUP:
505 		return ("NVME_ERR_LOG_CSI_UNSUP");
506 	case NVME_ERR_LOG_LSP_UNSUP:
507 		return ("NVME_ERR_LOG_LSP_UNSUP");
508 	case NVME_ERR_LOG_LSI_UNSUP:
509 		return ("NVME_ERR_LOG_LSI_UNSUP");
510 	case NVME_ERR_LOG_RAE_UNSUP:
511 		return ("NVME_ERR_LOG_RAE_UNSUP");
512 	case NVME_ERR_LOG_OFFSET_UNSUP:
513 		return ("NVME_ERR_LOG_OFFSET_UNSUP");
514 	case NVME_ERR_LOG_LSP_UNUSE:
515 		return ("NVME_ERR_LOG_LSP_UNUSE");
516 	case NVME_ERR_LOG_LSI_UNUSE:
517 		return ("NVME_ERR_LOG_LSI_UNUSE");
518 	case NVME_ERR_LOG_RAE_UNUSE:
519 		return ("NVME_ERR_LOG_RAE_UNUSE");
520 	case NVME_ERR_LOG_SCOPE_MISMATCH:
521 		return ("NVME_ERR_LOG_SCOPE_MISMATCH");
522 	case NVME_ERR_LOG_REQ_MISSING_FIELDS:
523 		return ("NVME_ERR_LOG_REQ_MISSING_FIELDS");
524 	case NVME_ERR_LOG_NAME_UNKNOWN:
525 		return ("NVME_ERR_LOG_NAME_UNKNOWN");
526 	case NVME_ERR_LOG_UNSUP_BY_DEV:
527 		return ("NVME_ERR_LOG_UNSUP_BY_DEV");
528 	case NVME_ERR_IDENTIFY_UNKNOWN:
529 		return ("NVME_ERR_IDENTIFY_UNKNOWN");
530 	case NVME_ERR_IDENTIFY_UNSUP_BY_DEV:
531 		return ("NVME_ERR_IDENTIFY_UNSUP_BY_DEV");
532 	case NVME_ERR_IDENTIFY_CTRLID_RANGE:
533 		return ("NVME_ERR_IDENTIFY_CTRLID_RANGE");
534 	case NVME_ERR_IDENTIFY_OUTPUT_RANGE:
535 		return ("NVME_ERR_IDENTIFY_OUTPUT_RANGE");
536 	case NVME_ERR_IDENTIFY_CTRLID_UNSUP:
537 		return ("NVME_ERR_IDENTIFY_CTRLID_UNSUP");
538 	case NVME_ERR_IDENTIFY_CTRLID_UNUSE:
539 		return ("NVME_ERR_IDENTIFY_CTRLID_UNUSE");
540 	case NVME_ERR_IDENTIFY_REQ_MISSING_FIELDS:
541 		return ("NVME_ERR_IDENTIFY_REQ_MISSING_FIELDS");
542 	case NVME_ERR_VUC_UNSUP_BY_DEV:
543 		return ("NVME_ERR_VUC_UNSUP_BY_DEV");
544 	case NVME_ERR_VUC_TIMEOUT_RANGE:
545 		return ("NVME_ERR_VUC_TIMEOUT_RANGE");
546 	case NVME_ERR_VUC_OPCODE_RANGE:
547 		return ("NVME_ERR_VUC_OPCODE_RANGE");
548 	case NVME_ERR_VUC_IMPACT_RANGE:
549 		return ("NVME_ERR_VUC_IMPACT_RANGE");
550 	case NVME_ERR_VUC_NDT_RANGE:
551 		return ("NVME_ERR_VUC_NDT_RANGE");
552 	case NVME_ERR_VUC_CANNOT_RW:
553 		return ("NVME_ERR_VUC_CANNOT_RW");
554 	case NVME_ERR_VUC_NO_RESULTS:
555 		return ("NVME_ERR_VUC_NO_RESULTS");
556 	case NVME_ERR_VUC_UNKNOWN:
557 		return ("NVME_ERR_VUC_UNKNOWN");
558 	case NVME_ERR_VUC_REQ_MISSING_FIELDS:
559 		return ("NVME_ERR_VUC_REQ_MISSING_FIELDS");
560 	case NVME_ERR_VU_FUNC_UNSUP_BY_DEV:
561 		return ("NVME_ERR_VU_FUNC_UNSUP_BY_DEV");
562 	case NVME_ERR_WDC_E6_OFFSET_RANGE:
563 		return ("NVME_ERR_WDC_E6_OFFSET_RANGE");
564 	case NVME_ERR_FW_UNSUP_BY_DEV:
565 		return ("NVME_ERR_FW_UNSUP_BY_DEV");
566 	case NVME_ERR_KERN_FW_IMPOS:
567 		return ("NVME_ERR_KERN_FW_IMPOS");
568 	case NVME_ERR_FW_LOAD_LEN_RANGE:
569 		return ("NVME_ERR_FW_LOAD_LEN_RANGE");
570 	case NVME_ERR_FW_LOAD_OFFSET_RANGE:
571 		return ("NVME_ERR_FW_LOAD_OFFSET_RANGE");
572 	case NVME_ERR_FW_COMMIT_SLOT_RANGE:
573 		return ("NVME_ERR_FW_COMMIT_SLOT_RANGE");
574 	case NVME_ERR_FW_COMMIT_ACTION_RANGE:
575 		return ("NVME_ERR_FW_COMMIT_ACTION_RANGE");
576 	case NVME_ERR_FW_COMMIT_REQ_MISSING_FIELDS:
577 		return ("NVME_ERR_FW_COMMIT_REQ_MISSING_FIELDS");
578 	case NVME_ERR_FW_SLOT_RO:
579 		return ("NVME_ERR_FW_SLOT_RO");
580 	case NVME_ERR_FORMAT_UNSUP_BY_DEV:
581 		return ("NVME_ERR_FORMAT_UNSUP_BY_DEV");
582 	case NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV:
583 		return ("NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV");
584 	case NVME_ERR_NS_FORMAT_UNSUP_BY_DEV:
585 		return ("NVME_ERR_NS_FORMAT_UNSUP_BY_DEV");
586 	case NVME_ERR_KERN_FORMAT_UNSUP:
587 		return ("NVME_ERR_KERN_FORMAT_UNSUP");
588 	case NVME_ERR_FORMAT_LBAF_RANGE:
589 		return ("NVME_ERR_FORMAT_LBAF_RANGE");
590 	case NVME_ERR_FORMAT_SES_RANGE:
591 		return ("NVME_ERR_FORMAT_SES_RANGE");
592 	case NVME_ERR_FORMAT_PARAM_UNSUP:
593 		return ("NVME_ERR_FORMAT_PARAM_UNSUP");
594 	case NVME_ERR_FORMAT_REQ_MISSING_FIELDS:
595 		return ("NVME_ERR_FORMAT_REQ_MISSING_FIELDS");
596 	case NVME_ERR_WDC_E6_REQ_MISSING_FIELDS:
597 		return ("NVME_ERR_WDC_E6_REQ_MISSING_FIELDS");
598 	case NVME_ERR_FEAT_NAME_UNKNOWN:
599 		return ("NVME_ERR_FEAT_NAME_UNKNOWN");
600 	case NVME_ERR_FEAT_UNSUP_BY_DEV:
601 		return ("NVME_ERR_FEAT_UNSUP_BY_DEV");
602 	case NVME_ERR_FEAT_FID_RANGE:
603 		return ("NVME_ERR_FEAT_FID_RANGE");
604 	case NVME_ERR_FEAT_SEL_RANGE:
605 		return ("NVME_ERR_FEAT_SEL_RANGE");
606 	case NVME_ERR_FEAT_CDW11_RANGE:
607 		return ("NVME_ERR_FEAT_CDW11_RANGE");
608 	case NVME_ERR_FEAT_DATA_RANGE:
609 		return ("NVME_ERR_FEAT_DATA_RANGE");
610 	case NVME_ERR_FEAT_SEL_UNSUP:
611 		return ("NVME_ERR_FEAT_SEL_UNSUP");
612 	case NVME_ERR_FEAT_CDW11_UNUSE:
613 		return ("NVME_ERR_FEAT_CDW11_UNUSE");
614 	case NVME_ERR_FEAT_DATA_UNUSE:
615 		return ("NVME_ERR_FEAT_DATA_UNUSE");
616 	case NVME_ERR_FEAT_NO_RESULTS:
617 		return ("NVME_ERR_FEAT_NO_RESULTS");
618 	case NVME_ERR_GET_FEAT_REQ_MISSING_FIELDS:
619 		return ("NVME_ERR_GET_FEAT_REQ_MISSING_FIELDS");
620 	case NVME_ERR_NEED_CTRL_WRLOCK:
621 		return ("NVME_ERR_NEED_CTRL_WRLOCK");
622 	case NVME_ERR_NEED_NS_WRLOCK:
623 		return ("NVME_ERR_NEED_NS_WRLOCK");
624 	case NVME_ERR_CTRL_LOCKED:
625 		return ("NVME_ERR_CTRL_LOCKED");
626 	case NVME_ERR_NS_LOCKED:
627 		return ("NVME_ERR_NS_LOCKED");
628 	case NVME_ERR_LOCK_PROG:
629 		return ("NVME_ERR_LOCK_PROG");
630 	case NVME_ERR_LOCK_ORDER:
631 		return ("NVME_ERR_LOCK_ORDER");
632 	case NVME_ERR_LOCK_WAIT_INTR:
633 		return ("NVME_ERR_LOCK_WAIT_INTR");
634 	case NVME_ERR_LOCK_WOULD_BLOCK:
635 		return ("NVME_ERR_LOCK_WOULD_BLOCK");
636 	case NVME_ERR_DETACH_KERN:
637 		return ("NVME_ERR_DETACH_KERN");
638 	case NVME_ERR_ATTACH_KERN:
639 		return ("NVME_ERR_ATTACH_KERN");
640 	case NVME_ERR_ATTACH_UNSUP_KERN:
641 		return ("NVME_ERR_ATTACH_UNSUP_KERN");
642 	case NVME_ERR_NS_BLKDEV_ATTACH:
643 		return ("NVME_ERR_NS_BLKDEV_ATTACH");
644 	case NVME_ERR_NO_KERN_MEM:
645 		return ("NVME_ERR_NO_KERN_MEM");
646 	case NVME_ERR_CTRL_DEAD:
647 		return ("NVME_ERR_CTRL_DEAD");
648 	case NVME_ERR_CTRL_GONE:
649 		return ("NVME_ERR_CTRL_GONE");
650 	case NVME_ERR_NS_MGMT_UNSUP_BY_DEV:
651 		return ("NVME_ERR_NS_MGMT_UNSUP_BY_DEV");
652 	case NVME_ERR_THIN_PROV_UNSUP_BY_DEV:
653 		return ("NVME_ERR_THIN_PROV_UNSUP_BY_DEV");
654 	case NVME_ERR_NS_ATTACH_REQ_MISSING_FIELDS:
655 		return ("NVME_ERR_NS_ATTACH_REQ_MISSING_FIELDS");
656 	case NVME_ERR_NS_CREATE_REQ_MISSING_FIELDS:
657 		return ("NVME_ERR_NS_CREATE_REQ_MISSING_FIELDS");
658 	case NVME_ERR_NS_DELETE_REQ_MISSING_FIELDS:
659 		return ("NVME_ERR_NS_DELETE_REQ_MISSING_FIELDS");
660 	case NVME_ERR_NS_CREATE_BAD_CSI:
661 		return ("NVME_ERR_NS_CREATE_BAD_CSI");
662 	case NVME_ERR_NS_ATTACH_BAD_SEL:
663 		return ("NVME_ERR_NS_ATTACH_BAD_SEL");
664 	case NVME_ERR_NS_CREATE_NO_RESULTS:
665 		return ("NVME_ERR_NS_CREATE_NO_RESULTS");
666 	case NVME_ERR_NS_CREATE_NCAP_RANGE:
667 		return ("NVME_ERR_NS_CREATE_NCAP_RANGE");
668 	case NVME_ERR_NS_CREATE_NSZE_RANGE:
669 		return ("NVME_ERR_NS_CREATE_NSZE_RANGE");
670 	case NVME_ERR_NS_CREATE_NMIC_RANGE:
671 		return ("NVME_ERR_NS_CREATE_NMIC_RANGE");
672 	case NVME_ERR_NS_CREATE_FLBAS_RANGE:
673 		return ("NVME_ERR_NS_CREATE_FLBAS_RANGE");
674 	case NVME_ERR_NS_CTRL_ATTACHED:
675 		return ("NVME_ERR_NS_CTRL_ATTACHED");
676 	case NVME_ERR_NS_CTRL_NOT_ATTACHED:
677 		return ("NVME_ERR_NS_CTRL_NOT_ATTACHED");
678 	case NVME_ERR_NS_UNALLOC:
679 		return ("NVME_ERR_NS_UNALLOC");
680 	default:
681 		return ("unknown error");
682 	}
683 }
684 
685 nvme_err_t
nvme_ctrl_err(nvme_ctrl_t * ctrl)686 nvme_ctrl_err(nvme_ctrl_t *ctrl)
687 {
688 	return (ctrl->nc_err.ne_err);
689 }
690 
691 int32_t
nvme_ctrl_syserr(nvme_ctrl_t * ctrl)692 nvme_ctrl_syserr(nvme_ctrl_t *ctrl)
693 {
694 	return (ctrl->nc_err.ne_syserr);
695 }
696 
697 const char *
nvme_ctrl_errmsg(nvme_ctrl_t * ctrl)698 nvme_ctrl_errmsg(nvme_ctrl_t *ctrl)
699 {
700 	return (ctrl->nc_err.ne_errmsg);
701 }
702 
703 size_t
nvme_ctrl_errlen(nvme_ctrl_t * ctrl)704 nvme_ctrl_errlen(nvme_ctrl_t *ctrl)
705 {
706 	return (ctrl->nc_err.ne_errlen);
707 }
708 
709 void
nvme_ctrl_deverr(nvme_ctrl_t * ctrl,uint32_t * sct,uint32_t * sc)710 nvme_ctrl_deverr(nvme_ctrl_t *ctrl, uint32_t *sct, uint32_t *sc)
711 {
712 	if (sct != NULL) {
713 		*sct = ctrl->nc_err.ne_ctrl_sct;
714 	}
715 
716 	if (sc != NULL) {
717 		*sc = ctrl->nc_err.ne_ctrl_sc;
718 	}
719 }
720 
721 const char *
nvme_ctrl_errtostr(nvme_ctrl_t * ctrl,nvme_err_t err)722 nvme_ctrl_errtostr(nvme_ctrl_t *ctrl, nvme_err_t err)
723 {
724 	return (nvme_errtostr(ctrl->nc_nvme, err));
725 }
726 
727 static void
nvme_error_common(nvme_err_data_t * ep,nvme_err_t err,int32_t sys,const char * fmt,va_list ap)728 nvme_error_common(nvme_err_data_t *ep, nvme_err_t err, int32_t sys,
729     const char *fmt, va_list ap)
730 {
731 	int ret;
732 
733 	ep->ne_err = err;
734 	ep->ne_syserr = sys;
735 	ep->ne_ctrl_sct = 0;
736 	ep->ne_ctrl_sc = 0;
737 	ret = vsnprintf(ep->ne_errmsg,
738 	    sizeof (ep->ne_errmsg), fmt, ap);
739 	if (ret >= sizeof (ep->ne_errmsg)) {
740 		ep->ne_errlen = sizeof (ep->ne_errmsg) - 1;
741 	} else if (ret <= 0) {
742 		ep->ne_errlen = 0;
743 		ep->ne_errmsg[0] = '\0';
744 	} else {
745 		ep->ne_errlen = (size_t)ret;
746 	}
747 }
748 
749 bool
nvme_error(nvme_t * nvme,nvme_err_t err,int32_t sys,const char * fmt,...)750 nvme_error(nvme_t *nvme, nvme_err_t err, int32_t sys, const char *fmt, ...)
751 {
752 	va_list ap;
753 
754 	va_start(ap, fmt);
755 	nvme_error_common(&nvme->nh_err, err, sys, fmt, ap);
756 	va_end(ap);
757 
758 	return (false);
759 }
760 
761 bool
nvme_ctrl_error(nvme_ctrl_t * ctrl,nvme_err_t err,int32_t sys,const char * fmt,...)762 nvme_ctrl_error(nvme_ctrl_t *ctrl, nvme_err_t err, int32_t sys,
763     const char *fmt, ...)
764 {
765 	va_list ap;
766 
767 	va_start(ap, fmt);
768 	nvme_error_common(&ctrl->nc_err, err, sys, fmt, ap);
769 	va_end(ap);
770 
771 	return (false);
772 }
773 
774 static bool
nvme_success_common(nvme_err_data_t * err)775 nvme_success_common(nvme_err_data_t *err)
776 {
777 	err->ne_err = NVME_ERR_OK;
778 	err->ne_syserr = 0;
779 	err->ne_ctrl_sct = 0;
780 	err->ne_ctrl_sc = 0;
781 	err->ne_errmsg[0] = '\0';
782 	err->ne_errlen = 0;
783 
784 	return (true);
785 }
786 
787 bool
nvme_success(nvme_t * nvme)788 nvme_success(nvme_t *nvme)
789 {
790 	return (nvme_success_common(&nvme->nh_err));
791 }
792 
793 bool
nvme_ctrl_success(nvme_ctrl_t * ctrl)794 nvme_ctrl_success(nvme_ctrl_t *ctrl)
795 {
796 	return (nvme_success_common(&ctrl->nc_err));
797 }
798 
799 void
nvme_err_save(const nvme_t * nvme,nvme_err_data_t * out)800 nvme_err_save(const nvme_t *nvme, nvme_err_data_t *out)
801 {
802 	*out = nvme->nh_err;
803 }
804 
805 void
nvme_err_set(nvme_t * nvme,const nvme_err_data_t * err)806 nvme_err_set(nvme_t *nvme, const nvme_err_data_t *err)
807 {
808 	nvme->nh_err = *err;
809 }
810 
811 void
nvme_ctrl_err_save(const nvme_ctrl_t * ctrl,nvme_err_data_t * out)812 nvme_ctrl_err_save(const nvme_ctrl_t *ctrl, nvme_err_data_t *out)
813 {
814 	*out = ctrl->nc_err;
815 }
816 
817 void
nvme_ctrl_err_set(nvme_ctrl_t * ctrl,const nvme_err_data_t * err)818 nvme_ctrl_err_set(nvme_ctrl_t *ctrl, const nvme_err_data_t *err)
819 {
820 	ctrl->nc_err = *err;
821 }
822 
823 /*
824  * This table deals with mapping a kernel error to a library error and provides
825  * a short description of what it is. Note, we do not expect all kernel errors
826  * to occur and we may want to revisit which of these end up indicating a
827  * programmer error that we caused somehow.
828  */
829 typedef struct {
830 	nvme_ioctl_errno_t kl_kern;
831 	nvme_err_t kl_lib;
832 	const char *kl_desc;
833 } nvme_ktolmap_t;
834 
835 /*
836  * Please keep this table ordered based on the nvme_ioctl_error_t enumeration
837  * order. This is not required for correctness, but helps when scanning for
838  * missing entries. Please document why certain entries are skipped.
839  */
840 static const nvme_ktolmap_t nvme_ktolmap[] = {
841 	/*
842 	 * NVME_IOCTL_E_OK and NVME_IOCTL_E_CTRL_ERROR should already have been
843 	 * dealt with and shouldn't be included here.
844 	 */
845 	{ NVME_IOCTL_E_CTRL_DEAD, NVME_ERR_CTRL_DEAD, "the controller is no "
846 	    "longer usable by the system" },
847 	{ NVME_IOCTL_E_CTRL_GONE, NVME_ERR_CTRL_GONE, "the controller has been "
848 	    "physically removed from the system" },
849 	{ NVME_IOCTL_E_NS_RANGE, NVME_ERR_NS_RANGE, "invalid namespace "
850 	    "requested" },
851 	{ NVME_IOCTL_E_NS_UNUSE, NVME_ERR_NS_UNUSE, "a namespace ID may not be "
852 	    "specified in this context" },
853 	/*
854 	 * We have purposefully skipped NVME_IOCTL_E_MINOR_WRONG_NS and
855 	 * NVME_IOCTL_E_NOT_CTRL as the library should not ever use the
856 	 * namespace minor.
857 	 */
858 	{ NVME_IOCTL_E_NO_BCAST_NS, NVME_ERR_NS_RANGE, "the broadcast "
859 	    "namespace may not be used in this context" },
860 	{ NVME_IOCTL_E_NEED_CTRL_WRLOCK, NVME_ERR_NEED_CTRL_WRLOCK, "operation "
861 	    "requires a controller write lock, but it is not owned" },
862 	{ NVME_IOCTL_E_NEED_NS_WRLOCK, NVME_ERR_NEED_NS_WRLOCK, "operation "
863 	    "requires a namespace write lock, but it is not owned" },
864 	{ NVME_IOCTL_E_CTRL_LOCKED, NVME_ERR_CTRL_LOCKED, "controller locked" },
865 	{ NVME_IOCTL_E_NS_LOCKED, NVME_ERR_NS_LOCKED, "namespace locked" },
866 	/*
867 	 * We have purposefully skipped NVME_IOCTL_E_UNKNOWN_LOG_PAGE as in
868 	 * theory the library and kernel should be in sync with the set of known
869 	 * log pages. If it is out of sync due to someone distributing the two
870 	 * weirdly or a bad build, we'd rather that end up as an internal error
871 	 * rather than a first class error for users.
872 	 */
873 	{ NVME_IOCTL_E_UNSUP_LOG_PAGE, NVME_ERR_LOG_UNSUP_BY_DEV, "controller "
874 	    "does not support the specified log page" },
875 	{ NVME_IOCTL_E_BAD_LOG_SCOPE, NVME_ERR_LOG_SCOPE_MISMATCH, "log page "
876 	    "does not work with the requested scope" },
877 	{ NVME_IOCTL_E_LOG_CSI_RANGE, NVME_ERR_LOG_CSI_RANGE, "invalid command "
878 	    "set interface value" },
879 	{ NVME_IOCTL_E_LOG_LID_RANGE, NVME_ERR_LOG_LID_RANGE, "invalid log "
880 	    "identifier value" },
881 	{ NVME_IOCTL_E_LOG_LSP_RANGE, NVME_ERR_LOG_LSP_RANGE, "invalid log "
882 	    "specific parameter value" },
883 	{ NVME_IOCTL_E_LOG_LSI_RANGE, NVME_ERR_LOG_LSI_RANGE, "invalid log "
884 	    "specific identifier value" },
885 	{ NVME_IOCTL_E_LOG_RAE_RANGE, NVME_ERR_LOG_SIZE_RANGE, "invalid retain "
886 	    "asynchronous event value" },
887 	{ NVME_IOCTL_E_LOG_SIZE_RANGE, NVME_ERR_LOG_SIZE_RANGE, "invalid log "
888 	    "length value" },
889 	{ NVME_IOCTL_E_LOG_OFFSET_RANGE, NVME_ERR_LOG_OFFSET_RANGE, "invalid "
890 	    "log offset value" },
891 	{ NVME_IOCTL_E_LOG_CSI_UNSUP, NVME_ERR_LOG_CSI_UNSUP,
892 	    "the controller does not support specifying the csi" },
893 	{ NVME_IOCTL_E_LOG_LSP_UNSUP, NVME_ERR_LOG_LSP_UNSUP,
894 	    "the controller does not support specifying the lsp" },
895 	{ NVME_IOCTL_E_LOG_LSI_UNSUP, NVME_ERR_LOG_LSI_UNSUP,
896 	    "or controller do not support specifying the lsi" },
897 	{ NVME_IOCTL_E_LOG_RAE_UNSUP, NVME_ERR_LOG_RAE_UNSUP,
898 	    "the controller does not support retaining an asynchronous event" },
899 	{ NVME_IOCTL_E_LOG_OFFSET_UNSUP, NVME_ERR_LOG_OFFSET_UNSUP,
900 	    "the controller do not support specifying a a read offset" },
901 	{ NVME_IOCTL_E_LOG_LSP_UNUSE, NVME_ERR_LOG_LSP_UNUSE, "the log page "
902 	    "does not allow the lsp to be used" },
903 	{ NVME_IOCTL_E_LOG_LSI_UNUSE, NVME_ERR_LOG_LSI_UNUSE, "the log page "
904 	    "does not allow the lsi to be used" },
905 	{ NVME_IOCTL_E_LOG_RAE_UNUSE, NVME_ERR_LOG_RAE_UNUSE,  "the log page "
906 	    "does not allow rae to be set" },
907 	{ NVME_IOCTL_E_NO_DMA_MEM, NVME_ERR_NO_DMA_MEM, "the kernel failed to "
908 	    "allocate sufficient DMA resources" },
909 	{ NVME_IOCTL_E_NO_KERN_MEM, NVME_ERR_NO_KERN_MEM, "the kernel failed "
910 	    "to allocate sufficient memory for this operation" },
911 	{ NVME_IOCTL_E_BAD_PRP, NVME_ERR_INTERNAL, "a driver error occurred "
912 	    "while filling out the command's DMA resources" },
913 	{ NVME_IOCTL_E_BAD_USER_DATA, NVME_ERR_BAD_PTR, "the kernel "
914 	    "detected an invalid user buffer while trying to read/write the "
915 	    "passed in data buffer" },
916 	{ NVME_IOCTL_E_UNKNOWN_IDENTIFY, NVME_ERR_IDENTIFY_UNKNOWN, "unknown "
917 	    "identify command requested" },
918 	{ NVME_IOCTL_E_UNSUP_IDENTIFY, NVME_ERR_IDENTIFY_UNSUP_BY_DEV,
919 	    "controller does not support the requested identify command" },
920 	{ NVME_IOCTL_E_IDENTIFY_CTRLID_RANGE, NVME_ERR_IDENTIFY_CTRLID_RANGE,
921 	    "invalid controller id value" },
922 	{ NVME_IOCTL_E_IDENTIFY_CTRLID_UNSUP, NVME_ERR_IDENTIFY_CTRLID_UNSUP,
923 	    "the controller does not support specifying the controller ID" },
924 	{ NVME_IOCTL_E_IDENTIFY_CTRLID_UNUSE, NVME_ERR_IDENTIFY_CTRLID_UNUSE,
925 	    "this specific identify request does not allow setting the "
926 	    "controller id" },
927 	{ NVME_IOCTL_E_CTRL_VUC_UNSUP, NVME_ERR_VUC_UNSUP_BY_DEV,
928 	    "the controller does not support standard NVMe vendor unique "
929 	    "commands" },
930 	/*
931 	 * The following indicate bad values for given NVMe vendor unique
932 	 * command fields. Note, we do not include an entry for
933 	 * NVME_IOCTL_E_VUC_FLAGS_RANGE because these flags are entirely owned
934 	 * by the library.
935 	 */
936 	{ NVME_IOCTL_E_VUC_TIMEOUT_RANGE, NVME_ERR_VUC_TIMEOUT_RANGE, "invalid "
937 	    "command timeout value" },
938 	{ NVME_IOCTL_E_VUC_OPCODE_RANGE, NVME_ERR_VUC_OPCODE_RANGE, "invalid "
939 	    "vendor unique opcode specified" },
940 	{ NVME_IOCTL_E_VUC_IMPACT_RANGE, NVME_ERR_VUC_IMPACT_RANGE, "invalid "
941 	    "vendor unique impact specified" },
942 	{ NVME_IOCTL_E_VUC_NDT_RANGE, NVME_ERR_VUC_NDT_RANGE, "invalid "
943 	    "data transfer size specified" },
944 	/*
945 	 * We skip NVME_IOCTL_E_INCONSIST_VUC_FLAGS_NDT and
946 	 * NVME_IOCTL_E_INCONSIST_VUC_BUF_NDT because these are solely under the
947 	 * library control and would indicate a programming error at our end.
948 	 * The user shouldn't be able to cause this.
949 	 */
950 	{ NVME_IOCTL_E_BLKDEV_DETACH, NVME_ERR_DETACH_KERN, "the kernel failed "
951 	    "to detach the requested namespace" },
952 	{ NVME_IOCTL_E_BLKDEV_ATTACH, NVME_ERR_ATTACH_KERN, "the kernel failed "
953 	    "to attach the requested namespace" },
954 	{ NVME_IOCTL_E_UNSUP_ATTACH_NS, NVME_ERR_ATTACH_UNSUP_KERN,
955 	    "the namespace is not supported by the kernel" },
956 	{ NVME_IOCTL_E_CTRL_FORMAT_UNSUP, NVME_ERR_FORMAT_UNSUP_BY_DEV, "the "
957 	    "controller does not support formatting namespaces" },
958 	{ NVME_IOCTL_E_CTRL_CRYPTO_SE_UNSUP, NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV,
959 	    "the controller does not support cryptographic secure erase" },
960 	{ NVME_IOCTL_E_CTRL_NS_FORMAT_UNSUP, NVME_ERR_NS_FORMAT_UNSUP_BY_DEV,
961 	    "the controller cannot format a single namespace" },
962 	{ NVME_IOCTL_E_CTRL_NS_SE_UNSUP, NVME_ERR_NS_FORMAT_UNSUP_BY_DEV,
963 	    "the controller cannot secure erase a single namespace" },
964 	{ NVME_IOCTL_E_FORMAT_LBAF_RANGE, NVME_ERR_FORMAT_LBAF_RANGE,
965 	    "invalid LBA format value" },
966 	{ NVME_IOCTL_E_FORMAT_SES_RANGE, NVME_ERR_FORMAT_SES_RANGE,
967 	    "invalid secure erase settings value" },
968 	{ NVME_IOCTL_E_UNSUP_LBAF_META, NVME_ERR_KERN_FORMAT_UNSUP, "cannot "
969 	    "format due to the use of unsupported metadata sectors" },
970 	{ NVME_IOCTL_E_CTRL_FW_UNSUP, NVME_ERR_FW_UNSUP_BY_DEV, "the "
971 	    "controller does not support firmware commands" },
972 	{ NVME_IOCTL_E_FW_LOAD_IMPOS_GRAN, NVME_ERR_KERN_FW_IMPOS, "controller "
973 	    "reported firmware upgrade granularity does not work with the "
974 	    "calculated maximum DMA transfer size" },
975 	{ NVME_IOCTL_E_FW_LOAD_LEN_RANGE, NVME_ERR_FW_LOAD_LEN_RANGE,
976 	    "invalid firmware load length value" },
977 	{ NVME_IOCTL_E_FW_LOAD_OFFSET_RANGE, NVME_ERR_FW_LOAD_OFFSET_RANGE,
978 	    "invalid firmware load offset value" },
979 	{ NVME_IOCTL_E_FW_COMMIT_SLOT_RANGE, NVME_ERR_FW_COMMIT_SLOT_RANGE,
980 	    "invalid firmware commit slot value" },
981 	{ NVME_IOCTL_E_FW_COMMIT_ACTION_RANGE, NVME_ERR_FW_COMMIT_ACTION_RANGE,
982 	    "invalid firmware commit action value" },
983 	{ NVME_IOCTL_E_RO_FW_SLOT, NVME_ERR_FW_SLOT_RO, "cannot write to read-"
984 	    "only slot" },
985 	/*
986 	 * We have purposefully skipped NVME_IOCTL_E_UNKNOWN_FEATURE for the
987 	 * same reasons we did with NVME_IOCTL_E_UNKNOWN_LOG above.
988 	 */
989 	{ NVME_IOCTL_E_UNSUP_FEATURE, NVME_ERR_FEAT_UNSUP_BY_DEV, "the "
990 	    "controller does not supported the requested feature" },
991 	{ NVME_IOCTL_E_GET_FEAT_SEL_RANGE, NVME_ERR_FEAT_SEL_RANGE, "invalid "
992 	    "feature selector value" },
993 	{ NVME_IOCTL_E_GET_FEAT_CDW11_RANGE, NVME_ERR_FEAT_CDW11_RANGE,
994 	    "invalid feature-specific cdw11 value" },
995 	{ NVME_IOCTL_E_GET_FEAT_DATA_RANGE, NVME_ERR_FEAT_DATA_RANGE, "invalid "
996 	    "feature data, likely a size mismatch" },
997 	{ NVME_IOCTL_E_GET_FEAT_SEL_UNSUP, NVME_ERR_FEAT_SEL_UNSUP, "the "
998 	    "controller does not support specifying a feature selector" },
999 	{ NVME_IOCTL_E_GET_FEAT_CDW11_UNUSE, NVME_ERR_FEAT_CDW11_UNUSE,
1000 	    "the feature does not support specifying a cdw11 argument" },
1001 	{ NVME_IOCTL_E_GET_FEAT_DATA_UNUSE, NVME_ERR_FEAT_DATA_UNUSE,
1002 	    "the feature does not support specifying a data buffer" },
1003 	/*
1004 	 * We skip the NVME_IOCTL_E_BAD_LOCK_ENTITY,
1005 	 * NVME_IOCTL_E_BAD_LOCK_LEVEL, and NVME_IOCTL_E_BAD_LOCK_FLAGS
1006 	 * arguments as these are all generally passed by the library and not
1007 	 * really under direct user control. Therefore if there is a problem,
1008 	 * that should be an internal error.
1009 	 *
1010 	 * Similarly we skip NVME_IOCTL_E_NS_CANNOT_LOCK_CTRL and
1011 	 * NVME_IOCTL_E_NS_CANNOT_UNLOCK_CTRL because the library does not
1012 	 * utilize namespace minors and these can only apply to those.
1013 	 */
1014 	{ NVME_IOCTL_E_LOCK_ALREADY_HELD, NVME_ERR_LOCK_PROG, "fatal "
1015 	    "programmer error: recursive lock attempt" },
1016 	{ NVME_IOCTL_E_LOCK_NO_CTRL_WITH_NS, NVME_ERR_LOCK_ORDER,
1017 	    "control locks cannot be acquired while holding a namespace lock" },
1018 	{ NVME_IOCTL_LOCK_NO_NS_WITH_CTRL_WRLOCK, NVME_ERR_LOCK_ORDER,
1019 	    "no namespace locks may be acquired while holding a controller "
1020 	    "write lock" },
1021 	{ NVME_IOCTL_E_LOCK_NO_2ND_NS, NVME_ERR_LOCK_ORDER, "only a single "
1022 	    "namespace lock can be held at any time" },
1023 	{ NVME_IOCTL_E_LOCK_WAIT_SIGNAL, NVME_ERR_LOCK_WAIT_INTR, "signal "
1024 	    "received while blocking" },
1025 	{ NVME_IOCTL_E_LOCK_WOULD_BLOCK, NVME_ERR_LOCK_WOULD_BLOCK, "lock not "
1026 	    "available and no blocking allowed" },
1027 	{ NVME_IOCTL_E_LOCK_PENDING, NVME_ERR_LOCK_ORDER, "a handle may only "
1028 	    "block on one lock at a time" },
1029 	{ NVME_IOCTL_E_LOCK_NOT_HELD, NVME_ERR_LOCK_PROG, "fatal "
1030 	    "programmer error: asked to unlock lock that was not held" },
1031 	/*
1032 	 * This error is almost a can't happen due to the library construction
1033 	 * and should result in the above error, but if this does happen, we
1034 	 * treat this as a fatal lock error regardless.
1035 	 */
1036 	{ NVME_IOCTL_E_LOCK_WRONG_NS, NVME_ERR_LOCK_PROG, "fatal "
1037 	    "programmer error: asked to unlock namespace lock that was not "
1038 	    "held" },
1039 	{ NVME_IOCTL_E_NS_BLKDEV_ATTACH, NVME_ERR_NS_BLKDEV_ATTACH, "cannot "
1040 	    "execute request while blkdev is attached to the namespace" },
1041 	/*
1042 	 * We purposefully skip NVME_IOCTL_E_BD_ADDR_OVER right now because
1043 	 * there is nothing that a user can do about this. This is a
1044 	 * libnvme/kernel interface issue.
1045 	 */
1046 	{ NVME_IOCTL_E_CTRL_NS_MGMT_UNSUP, NVME_ERR_NS_MGMT_UNSUP_BY_DEV,
1047 	    "controller does not support namespace management" },
1048 	{ NVME_IOCTL_E_NS_CTRL_ATTACHED, NVME_ERR_NS_CTRL_ATTACHED,
1049 	    "cannot execute request against an attached namespace" },
1050 	{ NVME_IOCTL_E_NS_CTRL_NOT_ATTACHED, NVME_ERR_NS_CTRL_NOT_ATTACHED,
1051 	    "cannot execute request against an unattached namespace" },
1052 	{ NVME_IOCTL_E_NS_NO_NS, NVME_ERR_NS_UNALLOC, "cannot execute request "
1053 	    "against an unallocated namespace" },
1054 	{ NVME_IOCTL_E_NS_CREATE_NSZE_RANGE, NVME_ERR_NS_CREATE_NSZE_RANGE,
1055 	    "invalid namespace create size specified" },
1056 	{ NVME_IOCTL_E_NS_CREATE_NCAP_RANGE, NVME_ERR_NS_CREATE_NCAP_RANGE,
1057 	    "invalid namespace create capacity specified" },
1058 	/*
1059 	 * Right now the library only has a single error for an invalid CSI on
1060 	 * namespace create regardless of the reason.
1061 	 */
1062 	{ NVME_IOCTL_E_NS_CREATE_CSI_RANGE, NVME_ERR_NS_CREATE_BAD_CSI,
1063 	    "invalid namespace create command set identifier specified" },
1064 	{ NVME_IOCTL_E_NS_CREATE_FLBAS_RANGE, NVME_ERR_NS_CREATE_FLBAS_RANGE,
1065 	    "invalid namespace create LBA format specified" },
1066 	{ NVME_IOCTL_E_NS_CREATE_NMIC_RANGE, NVME_ERR_NS_CREATE_NMIC_RANGE,
1067 	    "invalid namespace multi-path and sharing capability specified" },
1068 	{ NVME_IOCTL_E_NS_CREATE_CSI_UNSUP, NVME_ERR_NS_CREATE_BAD_CSI, "the "
1069 	    "controller does not support specifying a CSI when creating "
1070 	    "namespaces" },
1071 	{ NVME_IOCTL_E_DRV_CSI_UNSUP, NVME_ERR_NS_CREATE_BAD_CSI, "the nvme "
1072 	    "driver does not supporting CSIs with that value" },
1073 	{ NVME_IOCTL_E_CTRL_THIN_PROV_UNSUP, NVME_ERR_THIN_PROV_UNSUP_BY_DEV,
1074 	    "controller does not support thin provisioning of namespaces" },
1075 };
1076 
1077 /*
1078  * Translate a kernel ioctl error into the library's error. We handle the
1079  * controller error separately. Otherwise, everything else is done based upon
1080  * our translation table.
1081  */
1082 bool
nvme_ioctl_error(nvme_ctrl_t * ctrl,const nvme_ioctl_common_t * ioc,const char * desc)1083 nvme_ioctl_error(nvme_ctrl_t *ctrl, const nvme_ioctl_common_t *ioc,
1084     const char *desc)
1085 {
1086 	int ret;
1087 	nvme_err_data_t *err = &ctrl->nc_err;
1088 	VERIFY3U(ioc->nioc_drv_err, !=, NVME_IOCTL_E_OK);
1089 
1090 	err->ne_syserr = 0;
1091 	err->ne_ctrl_sct = 0;
1092 	err->ne_ctrl_sc = 0;
1093 
1094 	if (ioc->nioc_drv_err == NVME_IOCTL_E_CTRL_ERROR) {
1095 		const char *sct, *sc;
1096 		err->ne_err = NVME_ERR_CONTROLLER;
1097 		err->ne_ctrl_sct = ioc->nioc_ctrl_sct;
1098 		err->ne_ctrl_sc = ioc->nioc_ctrl_sc;
1099 		sct = nvme_scttostr(ctrl, ioc->nioc_ctrl_sct);
1100 		sc = nvme_sctostr(ctrl, NVME_CSI_NVM, ioc->nioc_ctrl_sct,
1101 		    ioc->nioc_ctrl_sc);
1102 		ret = snprintf(err->ne_errmsg, sizeof (err->ne_errmsg),
1103 		    "failed to execute %s command: received controller error "
1104 		    "sct/sc %s/%s (0x%x/0x%x)", desc, sct, sc,
1105 		    ioc->nioc_ctrl_sct, ioc->nioc_ctrl_sc);
1106 	} else {
1107 		const nvme_ktolmap_t *map = NULL;
1108 		for (size_t i = 0; i < ARRAY_SIZE(nvme_ktolmap); i++) {
1109 			if (nvme_ktolmap[i].kl_kern == ioc->nioc_drv_err) {
1110 				map = &nvme_ktolmap[i];
1111 				break;
1112 			}
1113 		}
1114 
1115 		if (map != NULL) {
1116 			err->ne_err = map->kl_lib;
1117 			ret = snprintf(err->ne_errmsg, sizeof (err->ne_errmsg),
1118 			    "failed to execute %s command: %s", desc,
1119 			    map->kl_desc);
1120 		} else {
1121 			err->ne_err = NVME_ERR_INTERNAL;
1122 			ret = snprintf(err->ne_errmsg, sizeof (err->ne_errmsg),
1123 			    "failed to execute %s command: failed to map "
1124 			    "kernel error 0x%x to a known cause", desc,
1125 			    ioc->nioc_drv_err);
1126 		}
1127 	}
1128 
1129 	if (ret >= sizeof (err->ne_errmsg)) {
1130 		err->ne_errlen = sizeof (err->ne_errmsg) - 1;
1131 	} else if (ret <= 0) {
1132 		err->ne_errlen = 0;
1133 		err->ne_errmsg[0] = '\0';
1134 	} else {
1135 		err->ne_errlen = (size_t)ret;
1136 	}
1137 
1138 	return (false);
1139 }
1140 
1141 /*
1142  * Evaluate the set of ioctl errors that we see and translate and/or abort a few
1143  * of the expected values. Most things will end up being translated into a
1144  * generic internal error as we expect a rather tight error set at this point.
1145  *
1146  * We choose to panic on EFAULT because we are responsible for all such EFAULT
1147  * errors. These are structure that are coming from the library. This is not
1148  * something that the user could have passed us (their buffers will trigger
1149  * an explicit nvme_ioctl_errno_t). Therefore, something has gone very wrong
1150  * with our stack or we just corrupted some memory.
1151  *
1152  * The same is true with EBADF. In this case, that'd happen either because our
1153  * controller fd was bandit'd away by someone or somehow we lost FREAD or FWRITE
1154  * on the fd. That should not be possible assuming everyone is acting in good
1155  * faith, so we treat this as a sign that something quite bad has happened and
1156  * we shouldn't continue.
1157  */
1158 bool
nvme_ioctl_syserror(nvme_ctrl_t * ctrl,int err,const char * desc)1159 nvme_ioctl_syserror(nvme_ctrl_t *ctrl, int err, const char *desc)
1160 {
1161 	switch (err) {
1162 	case EFAULT:
1163 	case EBADF: {
1164 		const char *base = "fatal libnvme internal programming error: "
1165 		    "failed to issue ioctl";
1166 		char msg[1024];
1167 		int ret;
1168 		const char *up;
1169 		size_t ulen;
1170 
1171 		ret = snprintf(msg, sizeof (msg), "%s %s: %s (controller %p)",
1172 		    base, desc, strerror(err), ctrl);
1173 		if (ret >= sizeof (msg)) {
1174 			ulen = sizeof (msg);
1175 			up = msg;
1176 		} else if (ret <= 0) {
1177 			up = base;
1178 			ulen = strlen(base) + 1;
1179 		} else {
1180 			ulen = (size_t)ret;
1181 			up = msg;
1182 		}
1183 
1184 		upanic(up, ulen);
1185 	}
1186 	case EPERM:
1187 		return (nvme_ctrl_error(ctrl, NVME_ERR_PRIVS, err,
1188 		    "failed to issue %s ioctl due to missing privileges",
1189 		    desc));
1190 	default:
1191 		return (nvme_ctrl_error(ctrl, NVME_ERR_INTERNAL, err,
1192 		    "failed to issue %s ioctl due to unexpected system "
1193 		    "error: %s", desc, strerror(err)));
1194 	}
1195 }
1196 
1197 /*
1198  * Generate the standard warning about which fields are unused.
1199  */
1200 bool
nvme_field_miss_err(nvme_ctrl_t * ctrl,const nvme_field_info_t * fields,size_t nfields,nvme_err_t err,const char * desc,uint32_t val)1201 nvme_field_miss_err(nvme_ctrl_t *ctrl, const nvme_field_info_t *fields,
1202     size_t nfields, nvme_err_t err, const char *desc, uint32_t val)
1203 {
1204 	char buf[512];
1205 	bool comma = false;
1206 
1207 	VERIFY3U(val, !=, 0);
1208 	buf[0] = '\0';
1209 	for (size_t i = 0; i < nfields; i++) {
1210 		if ((val & (1 << i)) == 0) {
1211 			continue;
1212 		}
1213 
1214 		if (comma) {
1215 			(void) strlcat(buf, ",", sizeof (buf));
1216 		}
1217 		(void) strlcat(buf, fields[i].nlfi_spec, sizeof (buf));
1218 		comma = true;
1219 	}
1220 
1221 	return (nvme_ctrl_error(ctrl, err, 0, "cannot execute %s request due "
1222 	    "to missing fields: %s", desc, buf));
1223 }
1224 
1225 bool
nvme_field_check_one(nvme_ctrl_t * ctrl,uint64_t val,const char * req,const nvme_field_check_t * check,uint32_t allow)1226 nvme_field_check_one(nvme_ctrl_t *ctrl, uint64_t val, const char *req,
1227     const nvme_field_check_t *check, uint32_t allow)
1228 {
1229 	const nvme_field_info_t *field = &check->chk_fields[check->chk_index];
1230 	nvme_valid_ctrl_data_t data;
1231 	nvme_field_error_t err;
1232 	char msg[256];
1233 
1234 	if (allow != 0 && (allow & (1 << check->chk_index)) == 0) {
1235 		VERIFY3U(check->chk_field_unuse, !=, 0);
1236 		return (nvme_ctrl_error(ctrl, check->chk_field_unuse, 0,
1237 		    "field %s (%s) cannot be set in this %s request",
1238 		    field->nlfi_human, field->nlfi_spec, req));
1239 	}
1240 
1241 	data.vcd_vers = &ctrl->nc_vers;
1242 	data.vcd_id = &ctrl->nc_info;
1243 
1244 	err = nvme_field_validate(field, &data, val, msg, sizeof (msg));
1245 	switch (err) {
1246 	case NVME_FIELD_ERR_OK:
1247 		break;
1248 	case NVME_FIELD_ERR_UNSUP_VERSION:
1249 	case NVME_FIELD_ERR_UNSUP_FIELD:
1250 		VERIFY3U(check->chk_field_unsup, !=, 0);
1251 		return (nvme_ctrl_error(ctrl, check->chk_field_unsup, 0, "%s",
1252 		    msg));
1253 	case NVME_FIELD_ERR_BAD_VALUE:
1254 		VERIFY3U(check->chk_field_range, !=, 0);
1255 		return (nvme_ctrl_error(ctrl, check->chk_field_range, 0, "%s",
1256 		    msg));
1257 	}
1258 
1259 	return (true);
1260 }
1261