xref: /illumos-gate/usr/src/test/nvme-tests/tests/libnvme/bad-req.c (revision 7f3d7c9289dee6488b3cd2848a68c0b8580d750c)
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
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
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
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
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
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
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
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
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
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