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 2024 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_VENDOR:
48 		return ("vendor specific");
49 	default:
50 		return ("unknown status type");
51 	}
52 }
53 
54 static const char *
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 	default:
101 		return ("unknown status code");
102 	}
103 }
104 
105 static const char *
106 nvme_sctostr_gen_csi(nvme_csi_t csi, uint32_t sct)
107 {
108 	if (csi != NVME_CSI_NVM) {
109 		return ("unknown command set specific general status code");
110 	}
111 
112 	switch (sct) {
113 	case NVME_CQE_SC_GEN_NVM_LBA_RANGE:
114 		return ("lba out of range");
115 	case NVME_CQE_SC_GEN_NVM_CAP_EXC:
116 		return ("capacity exceeded");
117 	case NVME_CQE_SC_GEN_NVM_NS_NOTRDY:
118 		return ("namespace not ready");
119 	case NVME_CQE_SC_GEN_NVM_RSV_CNFLCT:
120 		return ("reservation conflict");
121 	case NVME_CQE_SC_GEN_NVM_FORMATTING:
122 		return ("format in progress");
123 	default:
124 		return ("unknown command set specific general status code");
125 	}
126 }
127 
128 static const char *
129 nvme_sctostr_cmd_gen(uint32_t sct)
130 {
131 	switch (sct) {
132 	case NVME_CQE_SC_SPC_INV_CQ	:
133 		return ("completion queue invalid");
134 	case NVME_CQE_SC_SPC_INV_QID	:
135 		return ("invalid queue identifier");
136 	case NVME_CQE_SC_SPC_MAX_QSZ_EXC:
137 		return ("max queue size exceeded");
138 	case NVME_CQE_SC_SPC_ABRT_CMD_EXC:
139 		return ("abort command limit exceeded");
140 	case NVME_CQE_SC_SPC_ASYNC_EVREQ_EXC:
141 		return ("asynchronous event request limit");
142 	case NVME_CQE_SC_SPC_INV_FW_SLOT:
143 		return ("invalid firmware slot");
144 	case NVME_CQE_SC_SPC_INV_FW_IMG:
145 		return ("invalid firmware image");
146 	case NVME_CQE_SC_SPC_INV_INT_VECT:
147 		return ("invalid interrupt vector");
148 	case NVME_CQE_SC_SPC_INV_LOG_PAGE:
149 		return ("invalid log page");
150 	case NVME_CQE_SC_SPC_INV_FORMAT:
151 		return ("invalid format");
152 	case NVME_CQE_SC_SPC_FW_RESET:
153 		return ("firmware activation requires conventional reset");
154 	case NVME_CQE_SC_SPC_INV_Q_DEL:
155 		return ("invalid queue deletion");
156 	case NVME_CQE_SC_SPC_FEAT_SAVE:
157 		return ("feature identifier not saveable");
158 	case NVME_CQE_SC_SPC_FEAT_CHG:
159 		return ("feature not changeable");
160 	case NVME_CQE_SC_SPC_FEAT_NS_SPEC:
161 		return ("feature not namespace spec");
162 	case NVME_CQE_SC_SPC_FW_NSSR	:
163 		return ("firmware activation requires nvm subsystem reset");
164 	case NVME_CQE_SC_SPC_FW_NEXT_RESET:
165 		return ("firmware activation requires controller level reset");
166 	case NVME_CQE_SC_SPC_FW_MTFA	:
167 		return ("firmware activation requires maximum time violation");
168 	case NVME_CQE_SC_SPC_FW_PROHIBITED:
169 		return ("firmware activation prohibited");
170 	case NVME_CQE_SC_SPC_FW_OVERLAP:
171 		return ("overlapping range");
172 	default:
173 		return ("unknown generic command status code");
174 	}
175 }
176 
177 static const char *
178 nvme_sctostr_cmd_csi(nvme_csi_t csi, uint32_t sct)
179 {
180 	if (csi != NVME_CSI_NVM) {
181 		return ("unknown command specific, I/O command set specific "
182 		    "status code");
183 	}
184 
185 	switch (sct) {
186 	case NVME_CQE_SC_SPC_NVM_CNFL_ATTR:
187 		return ("conflicting attributes");
188 	case NVME_CQE_SC_SPC_NVM_INV_PROT:
189 		return ("invalid protection");
190 	case NVME_CQE_SC_SPC_NVM_READONLY:
191 		return ("write to read only range");
192 	default:
193 		return ("unknown command specific, I/O command set specific "
194 		    "status code");
195 	}
196 }
197 
198 static const char *
199 nvme_sctostr_media(nvme_csi_t csi, uint32_t sct)
200 {
201 	if (sct >= NVME_CQE_SC_VEND_MIN) {
202 		return ("vendor specific media and data integrity status code");
203 	}
204 
205 	/*
206 	 * Unlike NVMe 1.x, NVMe 2.x declares the following command set
207 	 * independent.
208 	 */
209 	switch (sct) {
210 	case NVME_CQE_SC_INT_NVM_WRITE:
211 		return ("write fault");
212 	case NVME_CQE_SC_INT_NVM_READ:
213 		return ("unrecovered read error");
214 	case NVME_CQE_SC_INT_NVM_GUARD:
215 		return ("guard check error");
216 	case NVME_CQE_SC_INT_NVM_APPL_TAG:
217 		return ("application tag check err");
218 	case NVME_CQE_SC_INT_NVM_REF_TAG:
219 		return ("reference tag check err");
220 	case NVME_CQE_SC_INT_NVM_ACCESS:
221 		return ("access denied");
222 	}
223 
224 	/*
225 	 * The only command-set specific values are currently defined for the
226 	 * NVM command set.
227 	 */
228 	if (csi != NVME_CSI_NVM) {
229 		return ("unknown media and data integrity status code");
230 	}
231 
232 	switch (sct) {
233 	case NVME_CQE_SC_INT_NVM_COMPARE:
234 		return ("compare failure");
235 	default:
236 		return ("unknown media and data integrity status code");
237 	}
238 }
239 
240 const char *
241 nvme_sctostr(nvme_ctrl_t *ctrl __unused, nvme_csi_t csi, uint32_t sct,
242     uint32_t sc)
243 {
244 	switch (sct) {
245 	case NVME_CQE_SCT_GENERIC:
246 		if (sc <= NVME_CQE_SC_GEN_MAX) {
247 			return (nvme_sctostr_gen_gen(sc));
248 		} else if (sc <= NVME_CQE_SC_CSI_MAX) {
249 			return (nvme_sctostr_gen_csi(csi, sc));
250 		} else {
251 			return ("generic vendor specific status code");
252 		}
253 	case NVME_CQE_SCT_SPECIFIC:
254 		if (sc <= NVME_CQE_SC_GEN_MAX) {
255 			return (nvme_sctostr_cmd_gen(sc));
256 		} else if (sc <= NVME_CQE_SC_CSI_MAX) {
257 			return (nvme_sctostr_cmd_csi(csi, sc));
258 		} else {
259 			return ("command specific vendor specific status code");
260 		}
261 	case NVME_CQE_SCT_INTEGRITY:
262 		return (nvme_sctostr_media(csi, sc));
263 	case NVME_CQE_SCT_VENDOR:
264 		return ("vendor specific");
265 	default:
266 		return ("unknown status code");
267 	}
268 }
269 
270 nvme_err_t
271 nvme_err(nvme_t *nvme)
272 {
273 	return (nvme->nh_err.ne_err);
274 }
275 
276 int32_t
277 nvme_syserr(nvme_t *nvme)
278 {
279 	return (nvme->nh_err.ne_syserr);
280 }
281 
282 const char *
283 nvme_errmsg(nvme_t *nvme)
284 {
285 	return (nvme->nh_err.ne_errmsg);
286 }
287 
288 size_t
289 nvme_errlen(nvme_t *nvme)
290 {
291 	return (nvme->nh_err.ne_errlen);
292 }
293 
294 const char *
295 nvme_errtostr(nvme_t *nvme, nvme_err_t err)
296 {
297 	switch (err) {
298 	case NVME_ERR_OK:
299 		return ("NVME_ERR_OK");
300 	case NVME_ERR_CONTROLLER:
301 		return ("NVME_ERR_CONTROLLER");
302 	case NVME_ERR_NO_MEM:
303 		return ("NVME_ERR_NO_MEM");
304 	case NVME_ERR_NO_DMA_MEM:
305 		return ("NVME_ERR_NO_DMA_MEM");
306 	case NVME_ERR_LIBDEVINFO:
307 		return ("NVME_ERR_LIBDEVINFO");
308 	case NVME_ERR_INTERNAL:
309 		return ("NVME_ERR_INTERNAL");
310 	case NVME_ERR_BAD_PTR:
311 		return ("NVME_ERR_BAD_PTR");
312 	case NVME_ERR_BAD_FLAG:
313 		return ("NVME_ERR_BAD_FLAG");
314 	case NVME_ERR_BAD_DEVI:
315 		return ("NVME_ERR_BAD_DEVI");
316 	case NVME_ERR_BAD_DEVI_PROP:
317 		return ("NVME_ERR_BAD_DEVI_PROP");
318 	case NVME_ERR_ILLEGAL_INSTANCE:
319 		return ("NVME_ERR_ILLEGAL_INSTANCE");
320 	case NVME_ERR_BAD_CONTROLLER:
321 		return ("NVME_ERR_BAD_CONTROLLER");
322 	case NVME_ERR_PRIVS:
323 		return ("NVME_ERR_PRIVS");
324 	case NVME_ERR_OPEN_DEV:
325 		return ("NVME_ERR_OPEN_DEV");
326 	case NVME_ERR_BAD_RESTORE:
327 		return ("NVME_ERR_BAD_RESTORE");
328 	case NVME_ERR_NS_RANGE:
329 		return ("NVME_ERR_NS_RANGE");
330 	case NVME_ERR_NS_UNUSE:
331 		return ("NVME_ERR_NS_UNUSE");
332 	case NVME_ERR_LOG_CSI_RANGE:
333 		return ("NVME_ERR_LOG_CSI_RANGE");
334 	case NVME_ERR_LOG_LID_RANGE:
335 		return ("NVME_ERR_LOG_LID_RANGE");
336 	case NVME_ERR_LOG_LSP_RANGE:
337 		return ("NVME_ERR_LOG_LSP_RANGE");
338 	case NVME_ERR_LOG_LSI_RANGE:
339 		return ("NVME_ERR_LOG_LSI_RANGE");
340 	case NVME_ERR_LOG_RAE_RANGE:
341 		return ("NVME_ERR_LOG_RAE_RANGE");
342 	case NVME_ERR_LOG_SIZE_RANGE:
343 		return ("NVME_ERR_LOG_SIZE_RANGE");
344 	case NVME_ERR_LOG_OFFSET_RANGE:
345 		return ("NVME_ERR_LOG_OFFSET_RANGE");
346 	case NVME_ERR_LOG_CSI_UNSUP:
347 		return ("NVME_ERR_LOG_CSI_UNSUP");
348 	case NVME_ERR_LOG_LSP_UNSUP:
349 		return ("NVME_ERR_LOG_LSP_UNSUP");
350 	case NVME_ERR_LOG_LSI_UNSUP:
351 		return ("NVME_ERR_LOG_LSI_UNSUP");
352 	case NVME_ERR_LOG_RAE_UNSUP:
353 		return ("NVME_ERR_LOG_RAE_UNSUP");
354 	case NVME_ERR_LOG_OFFSET_UNSUP:
355 		return ("NVME_ERR_LOG_OFFSET_UNSUP");
356 	case NVME_ERR_LOG_LSP_UNUSE:
357 		return ("NVME_ERR_LOG_LSP_UNUSE");
358 	case NVME_ERR_LOG_LSI_UNUSE:
359 		return ("NVME_ERR_LOG_LSI_UNUSE");
360 	case NVME_ERR_LOG_RAE_UNUSE:
361 		return ("NVME_ERR_LOG_RAE_UNUSE");
362 	case NVME_ERR_LOG_SCOPE_MISMATCH:
363 		return ("NVME_ERR_LOG_SCOPE_MISMATCH");
364 	case NVME_ERR_LOG_REQ_MISSING_FIELDS:
365 		return ("NVME_ERR_LOG_REQ_MISSING_FIELDS");
366 	case NVME_ERR_LOG_NAME_UNKNOWN:
367 		return ("NVME_ERR_LOG_NAME_UNKNOWN");
368 	case NVME_ERR_LOG_UNSUP_BY_DEV:
369 		return ("NVME_ERR_LOG_UNSUP_BY_DEV");
370 	case NVME_ERR_IDENTIFY_UNKNOWN:
371 		return ("NVME_ERR_IDENTIFY_UNKNOWN");
372 	case NVME_ERR_IDENTIFY_UNSUP_BY_DEV:
373 		return ("NVME_ERR_IDENTIFY_UNSUP_BY_DEV");
374 	case NVME_ERR_IDENTIFY_CTRLID_RANGE:
375 		return ("NVME_ERR_IDENTIFY_CTRLID_RANGE");
376 	case NVME_ERR_IDENTIFY_OUTPUT_RANGE:
377 		return ("NVME_ERR_IDENTIFY_OUTPUT_RANGE");
378 	case NVME_ERR_IDENTIFY_CTRLID_UNSUP:
379 		return ("NVME_ERR_IDENTIFY_CTRLID_UNSUP");
380 	case NVME_ERR_IDENTIFY_CTRLID_UNUSE:
381 		return ("NVME_ERR_IDENTIFY_CTRLID_UNUSE");
382 	case NVME_ERR_IDENTIFY_REQ_MISSING_FIELDS:
383 		return ("NVME_ERR_IDENTIFY_REQ_MISSING_FIELDS");
384 	case NVME_ERR_VUC_UNSUP_BY_DEV:
385 		return ("NVME_ERR_VUC_UNSUP_BY_DEV");
386 	case NVME_ERR_VUC_TIMEOUT_RANGE:
387 		return ("NVME_ERR_VUC_TIMEOUT_RANGE");
388 	case NVME_ERR_VUC_OPCODE_RANGE:
389 		return ("NVME_ERR_VUC_OPCODE_RANGE");
390 	case NVME_ERR_VUC_IMPACT_RANGE:
391 		return ("NVME_ERR_VUC_IMPACT_RANGE");
392 	case NVME_ERR_VUC_NDT_RANGE:
393 		return ("NVME_ERR_VUC_NDT_RANGE");
394 	case NVME_ERR_VUC_CANNOT_RW:
395 		return ("NVME_ERR_VUC_CANNOT_RW");
396 	case NVME_ERR_VUC_NO_RESULTS:
397 		return ("NVME_ERR_VUC_NO_RESULTS");
398 	case NVME_ERR_VUC_UNKNOWN:
399 		return ("NVME_ERR_VUC_UNKNOWN");
400 	case NVME_ERR_VUC_REQ_MISSING_FIELDS:
401 		return ("NVME_ERR_VUC_REQ_MISSING_FIELDS");
402 	case NVME_ERR_VU_FUNC_UNSUP_BY_DEV:
403 		return ("NVME_ERR_VU_FUNC_UNSUP_BY_DEV");
404 	case NVME_ERR_WDC_E6_OFFSET_RANGE:
405 		return ("NVME_ERR_WDC_E6_OFFSET_RANGE");
406 	case NVME_ERR_FW_UNSUP_BY_DEV:
407 		return ("NVME_ERR_FW_UNSUP_BY_DEV");
408 	case NVME_ERR_KERN_FW_IMPOS:
409 		return ("NVME_ERR_KERN_FW_IMPOS");
410 	case NVME_ERR_FW_LOAD_LEN_RANGE:
411 		return ("NVME_ERR_FW_LOAD_LEN_RANGE");
412 	case NVME_ERR_FW_LOAD_OFFSET_RANGE:
413 		return ("NVME_ERR_FW_LOAD_OFFSET_RANGE");
414 	case NVME_ERR_FW_COMMIT_SLOT_RANGE:
415 		return ("NVME_ERR_FW_COMMIT_SLOT_RANGE");
416 	case NVME_ERR_FW_COMMIT_ACTION_RANGE:
417 		return ("NVME_ERR_FW_COMMIT_ACTION_RANGE");
418 	case NVME_ERR_FW_COMMIT_REQ_MISSING_FIELDS:
419 		return ("NVME_ERR_FW_COMMIT_REQ_MISSING_FIELDS");
420 	case NVME_ERR_FW_SLOT_RO:
421 		return ("NVME_ERR_FW_SLOT_RO");
422 	case NVME_ERR_FORMAT_UNSUP_BY_DEV:
423 		return ("NVME_ERR_FORMAT_UNSUP_BY_DEV");
424 	case NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV:
425 		return ("NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV");
426 	case NVME_ERR_NS_FORMAT_UNSUP_BY_DEV:
427 		return ("NVME_ERR_NS_FORMAT_UNSUP_BY_DEV");
428 	case NVME_ERR_KERN_FORMAT_UNSUP:
429 		return ("NVME_ERR_KERN_FORMAT_UNSUP");
430 	case NVME_ERR_FORMAT_LBAF_RANGE:
431 		return ("NVME_ERR_FORMAT_LBAF_RANGE");
432 	case NVME_ERR_FORMAT_SES_RANGE:
433 		return ("NVME_ERR_FORMAT_SES_RANGE");
434 	case NVME_ERR_FORMAT_PARAM_UNSUP:
435 		return ("NVME_ERR_FORMAT_PARAM_UNSUP");
436 	case NVME_ERR_FORMAT_REQ_MISSING_FIELDS:
437 		return ("NVME_ERR_FORMAT_REQ_MISSING_FIELDS");
438 	case NVME_ERR_WDC_E6_REQ_MISSING_FIELDS:
439 		return ("NVME_ERR_WDC_E6_REQ_MISSING_FIELDS");
440 	case NVME_ERR_FEAT_NAME_UNKNOWN:
441 		return ("NVME_ERR_FEAT_NAME_UNKNOWN");
442 	case NVME_ERR_FEAT_UNSUP_BY_DEV:
443 		return ("NVME_ERR_FEAT_UNSUP_BY_DEV");
444 	case NVME_ERR_FEAT_FID_RANGE:
445 		return ("NVME_ERR_FEAT_FID_RANGE");
446 	case NVME_ERR_FEAT_SEL_RANGE:
447 		return ("NVME_ERR_FEAT_SEL_RANGE");
448 	case NVME_ERR_FEAT_CDW11_RANGE:
449 		return ("NVME_ERR_FEAT_CDW11_RANGE");
450 	case NVME_ERR_FEAT_DATA_RANGE:
451 		return ("NVME_ERR_FEAT_DATA_RANGE");
452 	case NVME_ERR_FEAT_SEL_UNSUP:
453 		return ("NVME_ERR_FEAT_SEL_UNSUP");
454 	case NVME_ERR_FEAT_CDW11_UNUSE:
455 		return ("NVME_ERR_FEAT_CDW11_UNUSE");
456 	case NVME_ERR_FEAT_DATA_UNUSE:
457 		return ("NVME_ERR_FEAT_DATA_UNUSE");
458 	case NVME_ERR_FEAT_NO_RESULTS:
459 		return ("NVME_ERR_FEAT_NO_RESULTS");
460 	case NVME_ERR_GET_FEAT_REQ_MISSING_FIELDS:
461 		return ("NVME_ERR_GET_FEAT_REQ_MISSING_FIELDS");
462 	case NVME_ERR_NEED_CTRL_WRLOCK:
463 		return ("NVME_ERR_NEED_CTRL_WRLOCK");
464 	case NVME_ERR_NEED_NS_WRLOCK:
465 		return ("NVME_ERR_NEED_NS_WRLOCK");
466 	case NVME_ERR_CTRL_LOCKED:
467 		return ("NVME_ERR_CTRL_LOCKED");
468 	case NVME_ERR_NS_LOCKED:
469 		return ("NVME_ERR_NS_LOCKED");
470 	case NVME_ERR_LOCK_PROG:
471 		return ("NVME_ERR_LOCK_PROG");
472 	case NVME_ERR_LOCK_ORDER:
473 		return ("NVME_ERR_LOCK_ORDER");
474 	case NVME_ERR_LOCK_WAIT_INTR:
475 		return ("NVME_ERR_LOCK_WAIT_INTR");
476 	case NVME_ERR_LOCK_WOULD_BLOCK:
477 		return ("NVME_ERR_LOCK_WOULD_BLOCK");
478 	case NVME_ERR_DETACH_KERN:
479 		return ("NVME_ERR_DETACH_KERN");
480 	case NVME_ERR_ATTACH_KERN:
481 		return ("NVME_ERR_ATTACH_KERN");
482 	case NVME_ERR_ATTACH_UNSUP_KERN:
483 		return ("NVME_ERR_ATTACH_UNSUP_KERN");
484 	case NVME_ERR_NS_BLKDEV_ATTACH:
485 		return ("NVME_ERR_NS_BLKDEV_ATTACH");
486 	case NVME_ERR_NO_KERN_MEM:
487 		return ("NVME_ERR_NO_KERN_MEM");
488 	case NVME_ERR_CTRL_DEAD:
489 		return ("NVME_ERR_CTRL_DEAD");
490 	case NVME_ERR_CTRL_GONE:
491 		return ("NVME_ERR_CTRL_GONE");
492 	default:
493 		return ("unknown error");
494 	}
495 }
496 
497 nvme_err_t
498 nvme_ctrl_err(nvme_ctrl_t *ctrl)
499 {
500 	return (ctrl->nc_err.ne_err);
501 }
502 
503 int32_t
504 nvme_ctrl_syserr(nvme_ctrl_t *ctrl)
505 {
506 	return (ctrl->nc_err.ne_syserr);
507 }
508 
509 const char *
510 nvme_ctrl_errmsg(nvme_ctrl_t *ctrl)
511 {
512 	return (ctrl->nc_err.ne_errmsg);
513 }
514 
515 size_t
516 nvme_ctrl_errlen(nvme_ctrl_t *ctrl)
517 {
518 	return (ctrl->nc_err.ne_errlen);
519 }
520 
521 void
522 nvme_ctrl_deverr(nvme_ctrl_t *ctrl, uint32_t *sct, uint32_t *sc)
523 {
524 	if (sct != NULL) {
525 		*sct = ctrl->nc_err.ne_ctrl_sct;
526 	}
527 
528 	if (sc != NULL) {
529 		*sc = ctrl->nc_err.ne_ctrl_sc;
530 	}
531 }
532 
533 const char *
534 nvme_ctrl_errtostr(nvme_ctrl_t *ctrl, nvme_err_t err)
535 {
536 	return (nvme_errtostr(ctrl->nc_nvme, err));
537 }
538 
539 static void
540 nvme_error_common(nvme_err_data_t *ep, nvme_err_t err, int32_t sys,
541     const char *fmt, va_list ap)
542 {
543 	int ret;
544 
545 	ep->ne_err = err;
546 	ep->ne_syserr = sys;
547 	ep->ne_ctrl_sct = 0;
548 	ep->ne_ctrl_sc = 0;
549 	ret = vsnprintf(ep->ne_errmsg,
550 	    sizeof (ep->ne_errmsg), fmt, ap);
551 	if (ret >= sizeof (ep->ne_errmsg)) {
552 		ep->ne_errlen = sizeof (ep->ne_errmsg) - 1;
553 	} else if (ret <= 0) {
554 		ep->ne_errlen = 0;
555 		ep->ne_errmsg[0] = '\0';
556 	} else {
557 		ep->ne_errlen = (size_t)ret;
558 	}
559 }
560 
561 bool
562 nvme_error(nvme_t *nvme, nvme_err_t err, int32_t sys, const char *fmt, ...)
563 {
564 	va_list ap;
565 
566 	va_start(ap, fmt);
567 	nvme_error_common(&nvme->nh_err, err, sys, fmt, ap);
568 	va_end(ap);
569 
570 	return (false);
571 }
572 
573 bool
574 nvme_ctrl_error(nvme_ctrl_t *ctrl, nvme_err_t err, int32_t sys,
575     const char *fmt, ...)
576 {
577 	va_list ap;
578 
579 	va_start(ap, fmt);
580 	nvme_error_common(&ctrl->nc_err, err, sys, fmt, ap);
581 	va_end(ap);
582 
583 	return (false);
584 }
585 
586 static bool
587 nvme_success_common(nvme_err_data_t *err)
588 {
589 	err->ne_err = NVME_ERR_OK;
590 	err->ne_syserr = 0;
591 	err->ne_ctrl_sct = 0;
592 	err->ne_ctrl_sc = 0;
593 	err->ne_errmsg[0] = '\0';
594 	err->ne_errlen = 0;
595 
596 	return (true);
597 }
598 
599 bool
600 nvme_success(nvme_t *nvme)
601 {
602 	return (nvme_success_common(&nvme->nh_err));
603 }
604 
605 bool
606 nvme_ctrl_success(nvme_ctrl_t *ctrl)
607 {
608 	return (nvme_success_common(&ctrl->nc_err));
609 }
610 
611 void
612 nvme_err_save(const nvme_t *nvme, nvme_err_data_t *out)
613 {
614 	*out = nvme->nh_err;
615 }
616 
617 void
618 nvme_err_set(nvme_t *nvme, const nvme_err_data_t *err)
619 {
620 	nvme->nh_err = *err;
621 }
622 
623 void
624 nvme_ctrl_err_save(const nvme_ctrl_t *ctrl, nvme_err_data_t *out)
625 {
626 	*out = ctrl->nc_err;
627 }
628 
629 void
630 nvme_ctrl_err_set(nvme_ctrl_t *ctrl, const nvme_err_data_t *err)
631 {
632 	ctrl->nc_err = *err;
633 }
634 
635 /*
636  * This table deals with mapping a kernel error to a library error and provides
637  * a short description of what it is. Note, we do not expect all kernel errors
638  * to occur and we may want to revisit which of these end up indicating a
639  * programmer error that we caused somehow.
640  */
641 typedef struct {
642 	nvme_ioctl_errno_t kl_kern;
643 	nvme_err_t kl_lib;
644 	const char *kl_desc;
645 } nvme_ktolmap_t;
646 
647 /*
648  * Please keep this table ordered based on the nvme_ioctl_error_t enumeration
649  * order. This is not required for correctness, but helps when scanning for
650  * missing entries. Please document why certain entries are skipped.
651  */
652 static const nvme_ktolmap_t nvme_ktolmap[] = {
653 	/*
654 	 * NVME_IOCTL_E_OK and NVME_IOCTL_E_CTRL_ERROR should already have been
655 	 * dealt with and shouldn't be included here.
656 	 */
657 	{ NVME_IOCTL_E_CTRL_DEAD, NVME_ERR_CTRL_DEAD, "the controller is no "
658 	    "longer usable by the system" },
659 	{ NVME_IOCTL_E_CTRL_GONE, NVME_ERR_CTRL_GONE, "the controller has been "
660 	    "physically removed from the system" },
661 	{ NVME_IOCTL_E_NS_RANGE, NVME_ERR_NS_RANGE, "invalid namespace "
662 	    "requested" },
663 	{ NVME_IOCTL_E_NS_UNUSE, NVME_ERR_NS_UNUSE, "a namespace ID may not be "
664 	    "specified in this context" },
665 	/*
666 	 * We have purposefully skipped NVME_IOCTL_E_MINOR_WRONG_NS and
667 	 * NVME_IOCTL_E_NOT_CTRL as the library should not ever use the
668 	 * namespace minor.
669 	 */
670 	{ NVME_IOCTL_E_NO_BCAST_NS, NVME_ERR_NS_RANGE, "the broadcast "
671 	    "namespace may not be used in this context" },
672 	{ NVME_IOCTL_E_NEED_CTRL_WRLOCK, NVME_ERR_NEED_CTRL_WRLOCK, "operation "
673 	    "requires a controller write lock, but it is not owned" },
674 	{ NVME_IOCTL_E_NEED_NS_WRLOCK, NVME_ERR_NEED_NS_WRLOCK, "operation "
675 	    "requires a namespace write lock, but it is not owned" },
676 	{ NVME_IOCTL_E_CTRL_LOCKED, NVME_ERR_CTRL_LOCKED, "controller locked" },
677 	{ NVME_IOCTL_E_NS_LOCKED, NVME_ERR_NS_LOCKED, "namespace locked" },
678 	/*
679 	 * We have purposefully skipped NVME_IOCTL_E_UNKNOWN_LOG_PAGE as in
680 	 * theory the library and kernel should be in sync with the set of known
681 	 * log pages. If it is out of sync due to someone distributing the two
682 	 * weirdly or a bad build, we'd rather that end up as an internal error
683 	 * rather than a first class error for users.
684 	 */
685 	{ NVME_IOCTL_E_UNSUP_LOG_PAGE, NVME_ERR_LOG_UNSUP_BY_DEV, "controller "
686 	    "does not support the specified log page" },
687 	{ NVME_IOCTL_E_BAD_LOG_SCOPE, NVME_ERR_LOG_SCOPE_MISMATCH, "log page "
688 	    "does not work with the requested scope" },
689 	{ NVME_IOCTL_E_LOG_CSI_RANGE, NVME_ERR_LOG_CSI_RANGE, "invalid command "
690 	    "set interface value" },
691 	{ NVME_IOCTL_E_LOG_LID_RANGE, NVME_ERR_LOG_LID_RANGE, "invalid log "
692 	    "identifier value" },
693 	{ NVME_IOCTL_E_LOG_LSP_RANGE, NVME_ERR_LOG_LSP_RANGE, "invalid log "
694 	    "specific parameter value" },
695 	{ NVME_IOCTL_E_LOG_LSI_RANGE, NVME_ERR_LOG_LSI_RANGE, "invalid log "
696 	    "specific identifier value" },
697 	{ NVME_IOCTL_E_LOG_RAE_RANGE, NVME_ERR_LOG_SIZE_RANGE, "invalid retain "
698 	    "asynchronous event value" },
699 	{ NVME_IOCTL_E_LOG_SIZE_RANGE, NVME_ERR_LOG_SIZE_RANGE, "invalid log "
700 	    "length value" },
701 	{ NVME_IOCTL_E_LOG_OFFSET_RANGE, NVME_ERR_LOG_OFFSET_RANGE, "invalid "
702 	    "log offset value" },
703 	{ NVME_IOCTL_E_LOG_CSI_UNSUP, NVME_ERR_LOG_CSI_UNSUP,
704 	    "the controller does not support specifying the csi" },
705 	{ NVME_IOCTL_E_LOG_LSP_UNSUP, NVME_ERR_LOG_LSP_UNSUP,
706 	    "the controller does not support specifying the lsp" },
707 	{ NVME_IOCTL_E_LOG_LSI_UNSUP, NVME_ERR_LOG_LSI_UNSUP,
708 	    "or controller do not support specifying the lsi" },
709 	{ NVME_IOCTL_E_LOG_RAE_UNSUP, NVME_ERR_LOG_RAE_UNSUP,
710 	    "the controller does not support retaining an asynchronous event" },
711 	{ NVME_IOCTL_E_LOG_OFFSET_UNSUP, NVME_ERR_LOG_OFFSET_UNSUP,
712 	    "the controller do not support specifying a a read offset" },
713 	{ NVME_IOCTL_E_LOG_LSP_UNUSE, NVME_ERR_LOG_LSP_UNUSE, "the log page "
714 	    "does not allow the lsp to be used" },
715 	{ NVME_IOCTL_E_LOG_LSI_UNUSE, NVME_ERR_LOG_LSI_UNUSE, "the log page "
716 	    "does not allow the lsi to be used" },
717 	{ NVME_IOCTL_E_LOG_RAE_UNUSE, NVME_ERR_LOG_RAE_UNUSE,  "the log page "
718 	    "does not allow rae to be set" },
719 	{ NVME_IOCTL_E_NO_DMA_MEM, NVME_ERR_NO_DMA_MEM, "the kernel failed to "
720 	    "allocate sufficient DMA resources" },
721 	{ NVME_IOCTL_E_NO_KERN_MEM, NVME_ERR_NO_KERN_MEM, "the kernel failed "
722 	    "to allocate sufficient memory for this operation" },
723 	{ NVME_IOCTL_E_BAD_PRP, NVME_ERR_INTERNAL, "a driver error occurred "
724 	    "while filling out the command's DMA resources" },
725 	{ NVME_IOCTL_E_BAD_USER_DATA, NVME_ERR_BAD_PTR, "the kernel "
726 	    "detected an invalid user buffer while trying to read/write the "
727 	    "passed in data buffer" },
728 	{ NVME_IOCTL_E_UNKNOWN_IDENTIFY, NVME_ERR_IDENTIFY_UNKNOWN, "unknown "
729 	    "identify command requested" },
730 	{ NVME_IOCTL_E_UNSUP_IDENTIFY, NVME_ERR_IDENTIFY_UNSUP_BY_DEV,
731 	    "controller does not support the requested identify command" },
732 	{ NVME_IOCTL_E_IDENTIFY_CTRLID_RANGE, NVME_ERR_IDENTIFY_CTRLID_RANGE,
733 	    "invalid controller id value" },
734 	{ NVME_IOCTL_E_IDENTIFY_CTRLID_UNSUP, NVME_ERR_IDENTIFY_CTRLID_UNSUP,
735 	    "the controller does not support specifying the controller ID" },
736 	{ NVME_IOCTL_E_IDENTIFY_CTRLID_UNUSE, NVME_ERR_IDENTIFY_CTRLID_UNUSE,
737 	    "this specific identify request does not allow setting the "
738 	    "controller id" },
739 	{ NVME_IOCTL_E_CTRL_VUC_UNSUP, NVME_ERR_VUC_UNSUP_BY_DEV,
740 	    "the controller does not support standard NVMe vendor unique "
741 	    "commands" },
742 	/*
743 	 * The following indicate bad values for given NVMe vendor unique
744 	 * command fields. Note, we do not include an entry for
745 	 * NVME_IOCTL_E_VUC_FLAGS_RANGE because these flags are entirely owned
746 	 * by the library.
747 	 */
748 	{ NVME_IOCTL_E_VUC_TIMEOUT_RANGE, NVME_ERR_VUC_TIMEOUT_RANGE, "invalid "
749 	    "command timeout value" },
750 	{ NVME_IOCTL_E_VUC_OPCODE_RANGE, NVME_ERR_VUC_OPCODE_RANGE, "invalid "
751 	    "vendor unique opcode specified" },
752 	{ NVME_IOCTL_E_VUC_IMPACT_RANGE, NVME_ERR_VUC_IMPACT_RANGE, "invalid "
753 	    "vendor unique impact specified" },
754 	{ NVME_IOCTL_E_VUC_NDT_RANGE, NVME_ERR_VUC_NDT_RANGE, "invalid "
755 	    "data transfer size specified" },
756 	/*
757 	 * We skip NVME_IOCTL_E_INCONSIST_VUC_FLAGS_NDT and
758 	 * NVME_IOCTL_E_INCONSIST_VUC_BUF_NDT because these are solely under the
759 	 * library control and would indicate a programming error at our end.
760 	 * The user shouldn't be able to cause this.
761 	 */
762 	{ NVME_IOCTL_E_BLKDEV_DETACH, NVME_ERR_DETACH_KERN, "the kernel failed "
763 	    "to detach the requested namespace" },
764 	{ NVME_IOCTL_E_BLKDEV_ATTACH, NVME_ERR_ATTACH_KERN, "the kernel failed "
765 	    "to attach the requested namespace" },
766 	{ NVME_IOCTL_E_UNSUP_ATTACH_NS, NVME_ERR_ATTACH_UNSUP_KERN,
767 	    "the namespace is not supported by the kernel" },
768 	{ NVME_IOCTL_E_CTRL_FORMAT_UNSUP, NVME_ERR_FORMAT_UNSUP_BY_DEV, "the "
769 	    "controller does not support formatting namespaces" },
770 	{ NVME_IOCTL_E_CTRL_CRYPTO_SE_UNSUP, NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV,
771 	    "the controller does not support cryptographic secure erase" },
772 	{ NVME_IOCTL_E_CTRL_NS_FORMAT_UNSUP, NVME_ERR_NS_FORMAT_UNSUP_BY_DEV,
773 	    "the controller cannot format a single namespace" },
774 	{ NVME_IOCTL_E_CTRL_NS_SE_UNSUP, NVME_ERR_NS_FORMAT_UNSUP_BY_DEV,
775 	    "the controller cannot secure erase a single namespace" },
776 	{ NVME_IOCTL_E_FORMAT_LBAF_RANGE, NVME_ERR_FORMAT_LBAF_RANGE,
777 	    "invalid LBA format value" },
778 	{ NVME_IOCTL_E_FORMAT_SES_RANGE, NVME_ERR_FORMAT_SES_RANGE,
779 	    "invalid secure erase settings value" },
780 	{ NVME_IOCTL_E_UNSUP_LBAF_META, NVME_ERR_KERN_FORMAT_UNSUP, "cannot "
781 	    "format due to the use of unsupported metadata sectors" },
782 	{ NVME_IOCTL_E_CTRL_FW_UNSUP, NVME_ERR_FW_UNSUP_BY_DEV, "the "
783 	    "controller does not support firmware commands" },
784 	{ NVME_IOCTL_E_FW_LOAD_IMPOS_GRAN, NVME_ERR_KERN_FW_IMPOS, "controller "
785 	    "reported firmware upgrade granularity does not work with the "
786 	    "calculated maximum DMA transfer size" },
787 	{ NVME_IOCTL_E_FW_LOAD_LEN_RANGE, NVME_ERR_FW_LOAD_LEN_RANGE,
788 	    "invalid firmware load length value" },
789 	{ NVME_IOCTL_E_FW_LOAD_OFFSET_RANGE, NVME_ERR_FW_LOAD_OFFSET_RANGE,
790 	    "invalid firmware load offset value" },
791 	{ NVME_IOCTL_E_FW_COMMIT_SLOT_RANGE, NVME_ERR_FW_COMMIT_SLOT_RANGE,
792 	    "invalid firmware commit slot value" },
793 	{ NVME_IOCTL_E_FW_COMMIT_ACTION_RANGE, NVME_ERR_FW_COMMIT_ACTION_RANGE,
794 	    "invalid firmware commit action value" },
795 	{ NVME_IOCTL_E_RO_FW_SLOT, NVME_ERR_FW_SLOT_RO, "cannot write to read-"
796 	    "only slot" },
797 	/*
798 	 * We have purposefully skipped NVME_IOCTL_E_UNKNOWN_FEATURE for the
799 	 * same reasons we did with NVME_IOCTL_E_UNKNOWN_LOG above.
800 	 */
801 	{ NVME_IOCTL_E_UNSUP_FEATURE, NVME_ERR_FEAT_UNSUP_BY_DEV, "the "
802 	    "controller does not supported the requested feature" },
803 	{ NVME_IOCTL_E_GET_FEAT_SEL_RANGE, NVME_ERR_FEAT_SEL_RANGE, "invalid "
804 	    "feature selector value" },
805 	{ NVME_IOCTL_E_GET_FEAT_CDW11_RANGE, NVME_ERR_FEAT_CDW11_RANGE,
806 	    "invalid feature-specific cdw11 value" },
807 	{ NVME_IOCTL_E_GET_FEAT_DATA_RANGE, NVME_ERR_FEAT_DATA_RANGE, "invalid "
808 	    "feature data, likely a size mismatch" },
809 	{ NVME_IOCTL_E_GET_FEAT_SEL_UNSUP, NVME_ERR_FEAT_SEL_UNSUP, "the "
810 	    "controller does not support specifying a feature selector" },
811 	{ NVME_IOCTL_E_GET_FEAT_CDW11_UNUSE, NVME_ERR_FEAT_CDW11_UNUSE,
812 	    "the feature does not support specifying a cdw11 argument" },
813 	{ NVME_IOCTL_E_GET_FEAT_DATA_UNUSE, NVME_ERR_FEAT_DATA_UNUSE,
814 	    "the feature does not support specifying a data buffer" },
815 	/*
816 	 * We skip the NVME_IOCTL_E_BAD_LOCK_ENTITY,
817 	 * NVME_IOCTL_E_BAD_LOCK_LEVEL, and NVME_IOCTL_E_BAD_LOCK_FLAGS
818 	 * arguments as these are all generally passed by the library and not
819 	 * really under direct user control. Therefore if there is a problem,
820 	 * that should be an internal error.
821 	 *
822 	 * Similarly we skip NVME_IOCTL_E_NS_CANNOT_LOCK_CTRL and
823 	 * NVME_IOCTL_E_NS_CANNOT_UNLOCK_CTRL because the library does not
824 	 * utilize namespace minors and these can only apply to those.
825 	 */
826 	{ NVME_IOCTL_E_LOCK_ALREADY_HELD, NVME_ERR_LOCK_PROG, "fatal "
827 	    "programmer error: recursive lock attempt" },
828 	{ NVME_IOCTL_E_LOCK_NO_CTRL_WITH_NS, NVME_ERR_LOCK_ORDER,
829 	    "control locks cannot be acquired while holding a namespace lock" },
830 	{ NVME_IOCTL_LOCK_NO_NS_WITH_CTRL_WRLOCK, NVME_ERR_LOCK_ORDER,
831 	    "no namespace locks may be acquired while holding a controller "
832 	    "write lock" },
833 	{ NVME_IOCTL_E_LOCK_NO_2ND_NS, NVME_ERR_LOCK_ORDER, "only a single "
834 	    "namespace lock can be held at any time" },
835 	{ NVME_IOCTL_E_LOCK_WAIT_SIGNAL, NVME_ERR_LOCK_WAIT_INTR, "signal "
836 	    "received while blocking" },
837 	{ NVME_IOCTL_E_LOCK_WOULD_BLOCK, NVME_ERR_LOCK_WOULD_BLOCK, "lock not "
838 	    "available and no blocking allowed" },
839 	{ NVME_IOCTL_E_LOCK_PENDING, NVME_ERR_LOCK_ORDER, "a handle may only "
840 	    "block on one lock at a time" },
841 	{ NVME_IOCTL_E_LOCK_NOT_HELD, NVME_ERR_LOCK_PROG, "fatal "
842 	    "programmer error: asked to unlock lock that was not held" },
843 	/*
844 	 * This error is almost a can't happen due to the library construction
845 	 * and should result in the above error, but if this does happen, we
846 	 * treat this as a fatal lock error regardless.
847 	 */
848 	{ NVME_IOCTL_E_LOCK_WRONG_NS, NVME_ERR_LOCK_PROG, "fatal "
849 	    "programmer error: asked to unlock namespace lock that was not "
850 	    "held" },
851 	{ NVME_IOCTL_E_NS_BLKDEV_ATTACH, NVME_ERR_NS_BLKDEV_ATTACH, "cannot "
852 	    "execute request while namespace is attached" },
853 	/*
854 	 * We purposefully skip NVME_IOCTL_E_BD_ADDR_OVER right now because
855 	 * there is nothing that a user can do about this. This is a
856 	 * libnvme/kernel interface issue.
857 	 */
858 };
859 
860 /*
861  * Translate a kernel ioctl error into the library's error. We handle the
862  * controller error separately. Otherwise, everything else is done based upon
863  * our translation table.
864  */
865 bool
866 nvme_ioctl_error(nvme_ctrl_t *ctrl, const nvme_ioctl_common_t *ioc,
867     const char *desc)
868 {
869 	int ret;
870 	nvme_err_data_t *err = &ctrl->nc_err;
871 	VERIFY3U(ioc->nioc_drv_err, !=, NVME_IOCTL_E_OK);
872 
873 	err->ne_syserr = 0;
874 	err->ne_ctrl_sct = 0;
875 	err->ne_ctrl_sc = 0;
876 
877 	if (ioc->nioc_drv_err == NVME_IOCTL_E_CTRL_ERROR) {
878 		const char *sct, *sc;
879 		err->ne_err = NVME_ERR_CONTROLLER;
880 		err->ne_ctrl_sct = ioc->nioc_ctrl_sct;
881 		err->ne_ctrl_sc = ioc->nioc_ctrl_sc;
882 		sct = nvme_scttostr(ctrl, ioc->nioc_ctrl_sct);
883 		sc = nvme_sctostr(ctrl, NVME_CSI_NVM, ioc->nioc_ctrl_sct,
884 		    ioc->nioc_ctrl_sc);
885 		ret = snprintf(err->ne_errmsg, sizeof (err->ne_errmsg),
886 		    "failed to execute %s command: received controller error "
887 		    "sct/sc %s/%s (0x%x/0x%x)", desc, sct, sc,
888 		    ioc->nioc_ctrl_sct, ioc->nioc_ctrl_sc);
889 	} else {
890 		const nvme_ktolmap_t *map = NULL;
891 		for (size_t i = 0; i < ARRAY_SIZE(nvme_ktolmap); i++) {
892 			if (nvme_ktolmap[i].kl_kern == ioc->nioc_drv_err) {
893 				map = &nvme_ktolmap[i];
894 				break;
895 			}
896 		}
897 
898 		if (map != NULL) {
899 			err->ne_err = map->kl_lib;
900 			ret = snprintf(err->ne_errmsg, sizeof (err->ne_errmsg),
901 			    "failed to execute %s command: %s", desc,
902 			    map->kl_desc);
903 		} else {
904 			err->ne_err = NVME_ERR_INTERNAL;
905 			ret = snprintf(err->ne_errmsg, sizeof (err->ne_errmsg),
906 			    "failed to execute %s command: failed to map "
907 			    "kernel error 0x%x to a known cause", desc,
908 			    ioc->nioc_drv_err);
909 		}
910 	}
911 
912 	if (ret >= sizeof (err->ne_errmsg)) {
913 		err->ne_errlen = sizeof (err->ne_errmsg) - 1;
914 	} else if (ret <= 0) {
915 		err->ne_errlen = 0;
916 		err->ne_errmsg[0] = '\0';
917 	} else {
918 		err->ne_errlen = (size_t)ret;
919 	}
920 
921 	return (false);
922 }
923 
924 /*
925  * Evaluate the set of ioctl errors that we see and translate and/or abort a few
926  * of the expected values. Most things will end up being translated into a
927  * generic internal error as we expect a rather tight error set at this point.
928  *
929  * We choose to panic on EFAULT because we are responsible for all such EFAULT
930  * errors. These are structure that are coming from the library. This is not
931  * something that the user could have passed us (their buffers will trigger
932  * an explicit nvme_ioctl_errno_t). Therefore, something has gone very wrong
933  * with our stack or we just corrupted some memory.
934  *
935  * The same is true with EBADF. In this case, that'd happen either because our
936  * controller fd was bandit'd away by someone or somehow we lost FREAD or FWRITE
937  * on the fd. That should not be possible assuming everyone is acting in good
938  * faith, so we treat this as a sign that something quite bad has happened and
939  * we shouldn't continue.
940  */
941 bool
942 nvme_ioctl_syserror(nvme_ctrl_t *ctrl, int err, const char *desc)
943 {
944 	switch (err) {
945 	case EFAULT:
946 	case EBADF: {
947 		const char *base = "fatal libnvme internal programming error: "
948 		    "failed to issue ioctl";
949 		char msg[1024];
950 		int ret;
951 		const char *up;
952 		size_t ulen;
953 
954 		ret = snprintf(msg, sizeof (msg), "%s %s: %s (controller %p)",
955 		    base, desc, strerror(err), ctrl);
956 		if (ret >= sizeof (msg)) {
957 			ulen = sizeof (msg);
958 			up = msg;
959 		} else if (ret <= 0) {
960 			up = base;
961 			ulen = strlen(base) + 1;
962 		} else {
963 			ulen = (size_t)ret;
964 			up = msg;
965 		}
966 
967 		upanic(up, ulen);
968 	}
969 	case EPERM:
970 		return (nvme_ctrl_error(ctrl, NVME_ERR_PRIVS, err,
971 		    "failed to issue %s ioctl due to missing privileges",
972 		    desc));
973 	default:
974 		return (nvme_ctrl_error(ctrl, NVME_ERR_INTERNAL, err,
975 		    "failed to issue %s ioctl due to unexpected system "
976 		    "error: %s", desc, strerror(err)));
977 	}
978 }
979 
980 /*
981  * Generate the standard warning about which fields are unused.
982  */
983 bool
984 nvme_field_miss_err(nvme_ctrl_t *ctrl, const nvme_field_info_t *fields,
985     size_t nfields, nvme_err_t err, const char *desc, uint32_t val)
986 {
987 	char buf[512];
988 	bool comma = false;
989 
990 	VERIFY3U(val, !=, 0);
991 	buf[0] = '\0';
992 	for (size_t i = 0; i < nfields; i++) {
993 		if ((val & (1 << i)) == 0) {
994 			continue;
995 		}
996 
997 		if (comma) {
998 			(void) strlcat(buf, ",", sizeof (buf));
999 		}
1000 		(void) strlcat(buf, fields[i].nlfi_spec, sizeof (buf));
1001 		comma = true;
1002 	}
1003 
1004 	return (nvme_ctrl_error(ctrl, err, 0, "cannot execute %s request due "
1005 	    "to missing fields: %s", desc, buf));
1006 }
1007 
1008 bool
1009 nvme_field_check_one(nvme_ctrl_t *ctrl, uint64_t val, const char *req,
1010     const nvme_field_check_t *check, uint32_t allow)
1011 {
1012 	const nvme_field_info_t *field = &check->chk_fields[check->chk_index];
1013 	nvme_valid_ctrl_data_t data;
1014 	nvme_field_error_t err;
1015 	char msg[256];
1016 
1017 	if (allow != 0 && (allow & (1 << check->chk_index)) == 0) {
1018 		VERIFY3U(check->chk_field_unuse, !=, 0);
1019 		return (nvme_ctrl_error(ctrl, check->chk_field_unuse, 0,
1020 		    "field %s (%s) cannot be set in this %s request",
1021 		    field->nlfi_human, field->nlfi_spec, req));
1022 	}
1023 
1024 	data.vcd_vers = &ctrl->nc_vers;
1025 	data.vcd_id = &ctrl->nc_info;
1026 
1027 	err = nvme_field_validate(field, &data, val, msg, sizeof (msg));
1028 	switch (err) {
1029 	case NVME_FIELD_ERR_OK:
1030 		break;
1031 	case NVME_FIELD_ERR_UNSUP_VERSION:
1032 	case NVME_FIELD_ERR_UNSUP_FIELD:
1033 		VERIFY3U(check->chk_field_unsup, !=, 0);
1034 		return (nvme_ctrl_error(ctrl, check->chk_field_unsup, 0, "%s",
1035 		    msg));
1036 	case NVME_FIELD_ERR_BAD_VALUE:
1037 		VERIFY3U(check->chk_field_range, !=, 0);
1038 		return (nvme_ctrl_error(ctrl, check->chk_field_range, 0, "%s",
1039 		    msg));
1040 	}
1041 
1042 	return (true);
1043 }
1044