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 * 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 warnx("TEST FAILED: nvme_vuc_req_init() returned " 153 "wrong error %s (0x%x), not %s (0x%x)", 154 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), 155 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, 156 exp_err), exp_err); 157 return (false); 158 } else { 159 (void) printf("TEST PASSED: nvme_vuc_req_init() " 160 "correctly failed for %s\n", desc); 161 return (true); 162 } 163 } 164 165 static bool 166 bad_fw_commit_req(nvme_ctrl_t *ctrl, nvme_fw_commit_req_t **reqp, 167 nvme_err_t exp_err, const char *desc) 168 { 169 if (nvme_fw_commit_req_init(ctrl, reqp)) { 170 warnx("TEST FAILED: nvme_fw_commit_req_init() erroneously " 171 "passed despite %s", desc); 172 nvme_fw_commit_req_fini(*reqp); 173 return (false); 174 } else if (nvme_ctrl_err(ctrl) != exp_err) { 175 warnx("TEST FAILED: nvme_fw_commit_req_init() returned " 176 "wrong error %s (0x%x), not %s (0x%x)", 177 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), 178 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, 179 exp_err), exp_err); 180 return (false); 181 } else { 182 (void) printf("TEST PASSED: nvme_fw_commit_req_init() " 183 "correctly failed for %s\n", desc); 184 return (true); 185 } 186 } 187 188 static bool 189 bad_format_req(nvme_ctrl_t *ctrl, nvme_format_req_t **reqp, nvme_err_t exp_err, 190 const char *desc) 191 { 192 if (nvme_format_req_init(ctrl, reqp)) { 193 warnx("TEST FAILED: nvme_format_req_init() erroneously " 194 "passed despite %s", desc); 195 nvme_format_req_fini(*reqp); 196 return (false); 197 } else if (nvme_ctrl_err(ctrl) != exp_err) { 198 warnx("TEST FAILED: nvme_format_req_init() returned " 199 "wrong error %s (0x%x), not %s (0x%x)", 200 nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), 201 nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, 202 exp_err), exp_err); 203 return (false); 204 } else { 205 (void) printf("TEST PASSED: nvme_format_req_init() " 206 "correctly failed for %s\n", desc); 207 return (true); 208 } 209 } 210 211 int 212 main(void) 213 { 214 int ret = EXIT_SUCCESS; 215 nvme_t *nvme; 216 nvme_ctrl_t *ctrl; 217 nvme_id_req_t *id_req; 218 nvme_log_req_t *log_req; 219 nvme_get_feat_req_t *feat_req; 220 nvme_vuc_req_t *vuc_req; 221 nvme_fw_commit_req_t *fw_commit_req; 222 nvme_format_req_t *format_req; 223 224 libnvme_test_init(&nvme, &ctrl); 225 226 if (!bad_id_req(ctrl, NVME_CSI_NVM, NVME_IDENTIFY_CTRL, NULL, 227 NVME_ERR_BAD_PTR, "invalid req pointer")) { 228 ret = false; 229 } 230 231 if (!bad_id_req(ctrl, 0xff, NVME_IDENTIFY_CTRL, &id_req, 232 NVME_ERR_IDENTIFY_UNKNOWN, "unknown identify (bad csi)")) { 233 ret = false; 234 } 235 236 if (!bad_id_req(ctrl, NVME_CSI_NVM, UINT32_MAX, &id_req, 237 NVME_ERR_IDENTIFY_UNKNOWN, "unknown identify (bad cns)")) { 238 ret = false; 239 } 240 241 if (!bad_log_req(ctrl, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) { 242 ret = false; 243 } 244 245 if (!bad_log_req_by_name(ctrl, "health", 0, NULL, NVME_ERR_BAD_PTR, 246 "bad output pointer")) { 247 ret = false; 248 } 249 250 if (!bad_log_req_by_name(ctrl, NULL, 0, &log_req, NVME_ERR_BAD_PTR, 251 "bad name pointer")) { 252 ret = false; 253 } 254 255 if (!bad_log_req_by_name(ctrl, NULL, 0x12345678, &log_req, 256 NVME_ERR_BAD_PTR, "bad flags")) { 257 ret = false; 258 } 259 260 if (!bad_log_req_by_name(ctrl, "elbereth", 0, &log_req, 261 NVME_ERR_LOG_NAME_UNKNOWN, "unknown log")) { 262 ret = false; 263 } 264 265 if (!bad_get_feat_req(ctrl, NULL, NVME_ERR_BAD_PTR, 266 "invalid req pointer")) { 267 ret = false; 268 } 269 270 if (!bad_get_feat_req_by_name(ctrl, "health", 0, NULL, NVME_ERR_BAD_PTR, 271 "bad output pointer")) { 272 ret = false; 273 } 274 275 if (!bad_get_feat_req_by_name(ctrl, NULL, 0, &feat_req, 276 NVME_ERR_BAD_PTR, "bad name pointer")) { 277 ret = false; 278 } 279 280 if (!bad_get_feat_req_by_name(ctrl, NULL, 0x87654321, &feat_req, 281 NVME_ERR_BAD_PTR, "bad flags")) { 282 ret = false; 283 } 284 285 if (!bad_get_feat_req_by_name(ctrl, "elbereth", 0, &feat_req, 286 NVME_ERR_FEAT_NAME_UNKNOWN, "unknown feat")) { 287 ret = false; 288 } 289 290 if (!bad_vuc_req(ctrl, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) { 291 ret = false; 292 } 293 294 if (!bad_fw_commit_req(ctrl, NULL, NVME_ERR_BAD_PTR, 295 "invalid req pointer")) { 296 ret = false; 297 } 298 299 if (!bad_format_req(ctrl, NULL, NVME_ERR_BAD_PTR, 300 "invalid req pointer")) { 301 ret = false; 302 } 303 304 umem_setmtbf(1); 305 if (!bad_id_req(ctrl, NVME_CSI_NVM, NVME_IDENTIFY_CTRL, &id_req, 306 NVME_ERR_NO_MEM, "no memory")) { 307 ret = false; 308 } 309 310 if (!bad_log_req(ctrl, &log_req, NVME_ERR_NO_MEM, "no memory")) { 311 ret = false; 312 } 313 314 if (!bad_log_req_by_name(ctrl, "health", 0, &log_req, NVME_ERR_NO_MEM, 315 "no memory")) { 316 ret = false; 317 } 318 319 if (!bad_get_feat_req(ctrl, &feat_req, NVME_ERR_NO_MEM, "no memory")) { 320 ret = false; 321 } 322 323 if (!bad_get_feat_req_by_name(ctrl, "health", 0, &feat_req, 324 NVME_ERR_NO_MEM, "no memory")) { 325 ret = false; 326 } 327 328 if (!bad_vuc_req(ctrl, &vuc_req, NVME_ERR_NO_MEM, "no memory")) { 329 ret = false; 330 } 331 332 if (!bad_fw_commit_req(ctrl, &fw_commit_req, NVME_ERR_NO_MEM, 333 "no memory")) { 334 ret = false; 335 } 336 337 if (!bad_format_req(ctrl, &format_req, NVME_ERR_NO_MEM, "no memory")) { 338 ret = false; 339 } 340 umem_setmtbf(0); 341 342 if (ret == EXIT_SUCCESS) { 343 (void) printf("All tests passed successfully\n"); 344 } 345 346 nvme_ctrl_fini(ctrl); 347 nvme_fini(nvme); 348 return (ret); 349 } 350