1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2025 Oxide Computer Company
14 */
15
16 /*
17 * Go through the various controller request initialization routines and try to
18 * force various bad arguments in them.
19 */
20
21 #include <err.h>
22 #include <string.h>
23 #include <umem.h>
24
25 #include "libnvme_test_common.h"
26
27 static bool
bad_id_req(nvme_ctrl_t * ctrl,nvme_csi_t csi,uint32_t cns,nvme_id_req_t ** reqp,nvme_err_t exp_err,const char * desc)28 bad_id_req(nvme_ctrl_t *ctrl, nvme_csi_t csi, uint32_t cns,
29 nvme_id_req_t **reqp, nvme_err_t exp_err, const char *desc)
30 {
31 if (nvme_id_req_init_by_cns(ctrl, csi, cns, reqp)) {
32 warnx("TEST FAILED: nvme_id_req_init_by_cns() erroneously "
33 "passed despite %s", desc);
34 nvme_id_req_fini(*reqp);
35 return (false);
36 } else if (nvme_ctrl_err(ctrl) != exp_err) {
37 warnx("TEST FAILED: nvme_id_req_init_by_cns() returned "
38 "wrong error %s (0x%x), not %s (0x%x)",
39 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
40 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
41 exp_err), exp_err);
42 return (false);
43 } else {
44 (void) printf("TEST PASSED: nvme_id_req_init_by_cns() "
45 "correctly failed for %s\n", desc);
46 return (true);
47 }
48 }
49
50 static bool
bad_log_req(nvme_ctrl_t * ctrl,nvme_log_req_t ** reqp,nvme_err_t exp_err,const char * desc)51 bad_log_req(nvme_ctrl_t *ctrl, nvme_log_req_t **reqp, nvme_err_t exp_err,
52 const char *desc)
53 {
54 if (nvme_log_req_init(ctrl, reqp)) {
55 warnx("TEST FAILED: nvme_log_req_init() erroneously "
56 "passed despite %s", desc);
57 nvme_log_req_fini(*reqp);
58 return (false);
59 } else if (nvme_ctrl_err(ctrl) != exp_err) {
60 warnx("TEST FAILED: nvme_log_req_init() returned "
61 "wrong error %s (0x%x), not %s (0x%x)",
62 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
63 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
64 exp_err), exp_err);
65 return (false);
66 } else {
67 (void) printf("TEST PASSED: nvme_log_req_init() "
68 "correctly failed for %s\n", desc);
69 return (true);
70 }
71 }
72
73 static bool
bad_log_req_by_name(nvme_ctrl_t * ctrl,const char * name,uint32_t flags,nvme_log_req_t ** reqp,nvme_err_t exp_err,const char * desc)74 bad_log_req_by_name(nvme_ctrl_t *ctrl, const char *name, uint32_t flags,
75 nvme_log_req_t **reqp, nvme_err_t exp_err, const char *desc)
76 {
77 if (nvme_log_req_init_by_name(ctrl, name, flags, NULL, reqp)) {
78 warnx("TEST FAILED: nvme_log_req_init_by_name() erroneously "
79 "passed despite %s", desc);
80 nvme_log_req_fini(*reqp);
81 return (false);
82 } else if (nvme_ctrl_err(ctrl) != exp_err) {
83 warnx("TEST FAILED: nvme_log_req_init_by_name() returned "
84 "wrong error %s (0x%x), not %s (0x%x)",
85 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
86 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
87 exp_err), exp_err);
88 return (false);
89 } else {
90 (void) printf("TEST PASSED: nvme_log_req_init_by_name() "
91 "correctly failed for %s\n", desc);
92 return (true);
93 }
94 }
95
96 static bool
bad_get_feat_req(nvme_ctrl_t * ctrl,nvme_get_feat_req_t ** reqp,nvme_err_t exp_err,const char * desc)97 bad_get_feat_req(nvme_ctrl_t *ctrl, nvme_get_feat_req_t **reqp,
98 nvme_err_t exp_err, const char *desc)
99 {
100 if (nvme_get_feat_req_init(ctrl, reqp)) {
101 warnx("TEST FAILED: nvme_get_feat_req_init() erroneously "
102 "passed despite %s", desc);
103 nvme_get_feat_req_fini(*reqp);
104 return (false);
105 } else if (nvme_ctrl_err(ctrl) != exp_err) {
106 warnx("TEST FAILED: nvme_get_feat_req_init() returned "
107 "wrong error %s (0x%x), not %s (0x%x)",
108 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
109 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
110 exp_err), exp_err);
111 return (false);
112 } else {
113 (void) printf("TEST PASSED: nvme_get_feat_req_init() "
114 "correctly failed for %s\n", desc);
115 return (true);
116 }
117 }
118
119 static bool
bad_get_feat_req_by_name(nvme_ctrl_t * ctrl,const char * name,uint32_t flags,nvme_get_feat_req_t ** reqp,nvme_err_t exp_err,const char * desc)120 bad_get_feat_req_by_name(nvme_ctrl_t *ctrl, const char *name, uint32_t flags,
121 nvme_get_feat_req_t **reqp, nvme_err_t exp_err, const char *desc)
122 {
123 if (nvme_get_feat_req_init_by_name(ctrl, name, flags, NULL, reqp)) {
124 warnx("TEST FAILED: nvme_get_feat_req_init_by_name() "
125 "erroneously passed despite %s", desc);
126 nvme_get_feat_req_fini(*reqp);
127 return (false);
128 } else if (nvme_ctrl_err(ctrl) != exp_err) {
129 warnx("TEST FAILED: nvme_get_feat_req_init_by_name() returned "
130 "wrong error %s (0x%x), not %s (0x%x)",
131 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
132 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
133 exp_err), exp_err);
134 return (false);
135 } else {
136 (void) printf("TEST PASSED: nvme_get_feat_req_init_by_name() "
137 "correctly failed for %s\n", desc);
138 return (true);
139 }
140 }
141
142 static bool
bad_vuc_req(nvme_ctrl_t * ctrl,nvme_vuc_req_t ** reqp,nvme_err_t exp_err,const char * desc)143 bad_vuc_req(nvme_ctrl_t *ctrl, nvme_vuc_req_t **reqp, nvme_err_t exp_err,
144 const char *desc)
145 {
146 if (nvme_vuc_req_init(ctrl, reqp)) {
147 warnx("TEST FAILED: nvme_vuc_req_init() erroneously "
148 "passed despite %s", desc);
149 nvme_vuc_req_fini(*reqp);
150 return (false);
151 } else if (nvme_ctrl_err(ctrl) != exp_err) {
152 /*
153 * We don't have any vendor unique commands for some devices.
154 * Swallow those rather than error.
155 */
156 if (nvme_ctrl_err(ctrl) == NVME_ERR_VUC_UNSUP_BY_DEV) {
157 warnx("TEST IGNORED: nvme_vuc_req_init() returned "
158 "%s (0x%x), not %s (0x%x) due to lack of VUC "
159 "support",
160 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
161 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
162 exp_err), exp_err);
163 return (true);
164 }
165 warnx("TEST FAILED: nvme_vuc_req_init() returned "
166 "wrong error %s (0x%x), not %s (0x%x)",
167 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
168 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
169 exp_err), exp_err);
170 return (false);
171 } else {
172 (void) printf("TEST PASSED: nvme_vuc_req_init() "
173 "correctly failed for %s\n", desc);
174 return (true);
175 }
176 }
177
178 static bool
bad_fw_commit_req(nvme_ctrl_t * ctrl,nvme_fw_commit_req_t ** reqp,nvme_err_t exp_err,const char * desc)179 bad_fw_commit_req(nvme_ctrl_t *ctrl, nvme_fw_commit_req_t **reqp,
180 nvme_err_t exp_err, const char *desc)
181 {
182 if (nvme_fw_commit_req_init(ctrl, reqp)) {
183 warnx("TEST FAILED: nvme_fw_commit_req_init() erroneously "
184 "passed despite %s", desc);
185 nvme_fw_commit_req_fini(*reqp);
186 return (false);
187 } else if (nvme_ctrl_err(ctrl) != exp_err) {
188 warnx("TEST FAILED: nvme_fw_commit_req_init() returned "
189 "wrong error %s (0x%x), not %s (0x%x)",
190 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
191 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
192 exp_err), exp_err);
193 return (false);
194 } else {
195 (void) printf("TEST PASSED: nvme_fw_commit_req_init() "
196 "correctly failed for %s\n", desc);
197 return (true);
198 }
199 }
200
201 static bool
bad_format_req(nvme_ctrl_t * ctrl,nvme_format_req_t ** reqp,nvme_err_t exp_err,const char * desc)202 bad_format_req(nvme_ctrl_t *ctrl, nvme_format_req_t **reqp, nvme_err_t exp_err,
203 const char *desc)
204 {
205 if (nvme_format_req_init(ctrl, reqp)) {
206 warnx("TEST FAILED: nvme_format_req_init() erroneously "
207 "passed despite %s", desc);
208 nvme_format_req_fini(*reqp);
209 return (false);
210 } else if (nvme_ctrl_err(ctrl) != exp_err) {
211 warnx("TEST FAILED: nvme_format_req_init() returned "
212 "wrong error %s (0x%x), not %s (0x%x)",
213 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
214 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
215 exp_err), exp_err);
216 return (false);
217 } else {
218 (void) printf("TEST PASSED: nvme_format_req_init() "
219 "correctly failed for %s\n", desc);
220 return (true);
221 }
222 }
223
224 int
main(void)225 main(void)
226 {
227 int ret = EXIT_SUCCESS;
228 nvme_t *nvme;
229 nvme_ctrl_t *ctrl;
230 nvme_id_req_t *id_req;
231 nvme_log_req_t *log_req;
232 nvme_get_feat_req_t *feat_req;
233 nvme_vuc_req_t *vuc_req;
234 nvme_fw_commit_req_t *fw_commit_req;
235 nvme_format_req_t *format_req;
236
237 libnvme_test_init(&nvme, &ctrl);
238
239 if (!bad_id_req(ctrl, NVME_CSI_NVM, NVME_IDENTIFY_CTRL, NULL,
240 NVME_ERR_BAD_PTR, "invalid req pointer")) {
241 ret = EXIT_FAILURE;
242 }
243
244 if (!bad_id_req(ctrl, 0xff, NVME_IDENTIFY_CTRL, &id_req,
245 NVME_ERR_IDENTIFY_UNKNOWN, "unknown identify (bad csi)")) {
246 ret = EXIT_FAILURE;
247 }
248
249 if (!bad_id_req(ctrl, NVME_CSI_NVM, UINT32_MAX, &id_req,
250 NVME_ERR_IDENTIFY_UNKNOWN, "unknown identify (bad cns)")) {
251 ret = EXIT_FAILURE;
252 }
253
254 if (!bad_log_req(ctrl, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) {
255 ret = EXIT_FAILURE;
256 }
257
258 if (!bad_log_req_by_name(ctrl, "health", 0, NULL, NVME_ERR_BAD_PTR,
259 "bad output pointer")) {
260 ret = EXIT_FAILURE;
261 }
262
263 if (!bad_log_req_by_name(ctrl, NULL, 0, &log_req, NVME_ERR_BAD_PTR,
264 "bad name pointer")) {
265 ret = EXIT_FAILURE;
266 }
267
268 if (!bad_log_req_by_name(ctrl, NULL, 0x12345678, &log_req,
269 NVME_ERR_BAD_PTR, "bad flags")) {
270 ret = EXIT_FAILURE;
271 }
272
273 if (!bad_log_req_by_name(ctrl, "elbereth", 0, &log_req,
274 NVME_ERR_LOG_NAME_UNKNOWN, "unknown log")) {
275 ret = EXIT_FAILURE;
276 }
277
278 if (!bad_get_feat_req(ctrl, NULL, NVME_ERR_BAD_PTR,
279 "invalid req pointer")) {
280 ret = EXIT_FAILURE;
281 }
282
283 if (!bad_get_feat_req_by_name(ctrl, "health", 0, NULL, NVME_ERR_BAD_PTR,
284 "bad output pointer")) {
285 ret = EXIT_FAILURE;
286 }
287
288 if (!bad_get_feat_req_by_name(ctrl, NULL, 0, &feat_req,
289 NVME_ERR_BAD_PTR, "bad name pointer")) {
290 ret = EXIT_FAILURE;
291 }
292
293 if (!bad_get_feat_req_by_name(ctrl, NULL, 0x87654321, &feat_req,
294 NVME_ERR_BAD_PTR, "bad flags")) {
295 ret = EXIT_FAILURE;
296 }
297
298 if (!bad_get_feat_req_by_name(ctrl, "elbereth", 0, &feat_req,
299 NVME_ERR_FEAT_NAME_UNKNOWN, "unknown feat")) {
300 ret = EXIT_FAILURE;
301 }
302
303 if (!bad_vuc_req(ctrl, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) {
304 ret = EXIT_FAILURE;
305 }
306
307 if (!bad_fw_commit_req(ctrl, NULL, NVME_ERR_BAD_PTR,
308 "invalid req pointer")) {
309 ret = EXIT_FAILURE;
310 }
311
312 if (!bad_format_req(ctrl, NULL, NVME_ERR_BAD_PTR,
313 "invalid req pointer")) {
314 ret = EXIT_FAILURE;
315 }
316
317 umem_setmtbf(1);
318 if (!bad_id_req(ctrl, NVME_CSI_NVM, NVME_IDENTIFY_CTRL, &id_req,
319 NVME_ERR_NO_MEM, "no memory")) {
320 ret = EXIT_FAILURE;
321 }
322
323 if (!bad_log_req(ctrl, &log_req, NVME_ERR_NO_MEM, "no memory")) {
324 ret = EXIT_FAILURE;
325 }
326
327 if (!bad_log_req_by_name(ctrl, "health", 0, &log_req, NVME_ERR_NO_MEM,
328 "no memory")) {
329 ret = EXIT_FAILURE;
330 }
331
332 if (!bad_get_feat_req(ctrl, &feat_req, NVME_ERR_NO_MEM, "no memory")) {
333 ret = EXIT_FAILURE;
334 }
335
336 if (!bad_get_feat_req_by_name(ctrl, "health", 0, &feat_req,
337 NVME_ERR_NO_MEM, "no memory")) {
338 ret = EXIT_FAILURE;
339 }
340
341 if (!bad_vuc_req(ctrl, &vuc_req, NVME_ERR_NO_MEM, "no memory")) {
342 ret = EXIT_FAILURE;
343 }
344
345 if (!bad_fw_commit_req(ctrl, &fw_commit_req, NVME_ERR_NO_MEM,
346 "no memory")) {
347 ret = EXIT_FAILURE;
348 }
349
350 if (!bad_format_req(ctrl, &format_req, NVME_ERR_NO_MEM, "no memory")) {
351 ret = EXIT_FAILURE;
352 }
353
354 umem_setmtbf(0);
355
356 if (ret == EXIT_SUCCESS) {
357 (void) printf("All tests passed successfully\n");
358 }
359
360 nvme_ctrl_fini(ctrl);
361 nvme_fini(nvme);
362 return (ret);
363 }
364