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