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