/* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2024 Oxide Computer Company */ /* * Go through the various controller request initialization routines and try to * force various bad arguments in them. */ #include #include #include #include "libnvme_test_common.h" 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) { if (nvme_id_req_init_by_cns(ctrl, csi, cns, reqp)) { warnx("TEST FAILED: nvme_id_req_init_by_cns() erroneously " "passed despite %s", desc); nvme_id_req_fini(*reqp); return (false); } else if (nvme_ctrl_err(ctrl) != exp_err) { warnx("TEST FAILED: nvme_id_req_init_by_cns() returned " "wrong error %s (0x%x), not %s (0x%x)", nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, exp_err), exp_err); return (false); } else { (void) printf("TEST PASSED: nvme_id_req_init_by_cns() " "correctly failed for %s\n", desc); return (true); } } static bool bad_log_req(nvme_ctrl_t *ctrl, nvme_log_req_t **reqp, nvme_err_t exp_err, const char *desc) { if (nvme_log_req_init(ctrl, reqp)) { warnx("TEST FAILED: nvme_log_req_init() erroneously " "passed despite %s", desc); nvme_log_req_fini(*reqp); return (false); } else if (nvme_ctrl_err(ctrl) != exp_err) { warnx("TEST FAILED: nvme_log_req_init() returned " "wrong error %s (0x%x), not %s (0x%x)", nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, exp_err), exp_err); return (false); } else { (void) printf("TEST PASSED: nvme_log_req_init() " "correctly failed for %s\n", desc); return (true); } } 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) { if (nvme_log_req_init_by_name(ctrl, name, flags, NULL, reqp)) { warnx("TEST FAILED: nvme_log_req_init_by_name() erroneously " "passed despite %s", desc); nvme_log_req_fini(*reqp); return (false); } else if (nvme_ctrl_err(ctrl) != exp_err) { warnx("TEST FAILED: nvme_log_req_init_by_name() returned " "wrong error %s (0x%x), not %s (0x%x)", nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, exp_err), exp_err); return (false); } else { (void) printf("TEST PASSED: nvme_log_req_init_by_name() " "correctly failed for %s\n", desc); return (true); } } static bool bad_get_feat_req(nvme_ctrl_t *ctrl, nvme_get_feat_req_t **reqp, nvme_err_t exp_err, const char *desc) { if (nvme_get_feat_req_init(ctrl, reqp)) { warnx("TEST FAILED: nvme_get_feat_req_init() erroneously " "passed despite %s", desc); nvme_get_feat_req_fini(*reqp); return (false); } else if (nvme_ctrl_err(ctrl) != exp_err) { warnx("TEST FAILED: nvme_get_feat_req_init() returned " "wrong error %s (0x%x), not %s (0x%x)", nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, exp_err), exp_err); return (false); } else { (void) printf("TEST PASSED: nvme_get_feat_req_init() " "correctly failed for %s\n", desc); return (true); } } 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) { if (nvme_get_feat_req_init_by_name(ctrl, name, flags, NULL, reqp)) { warnx("TEST FAILED: nvme_get_feat_req_init_by_name() " "erroneously passed despite %s", desc); nvme_get_feat_req_fini(*reqp); return (false); } else if (nvme_ctrl_err(ctrl) != exp_err) { warnx("TEST FAILED: nvme_get_feat_req_init_by_name() returned " "wrong error %s (0x%x), not %s (0x%x)", nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, exp_err), exp_err); return (false); } else { (void) printf("TEST PASSED: nvme_get_feat_req_init_by_name() " "correctly failed for %s\n", desc); return (true); } } static bool bad_vuc_req(nvme_ctrl_t *ctrl, nvme_vuc_req_t **reqp, nvme_err_t exp_err, const char *desc) { if (nvme_vuc_req_init(ctrl, reqp)) { warnx("TEST FAILED: nvme_vuc_req_init() erroneously " "passed despite %s", desc); nvme_vuc_req_fini(*reqp); return (false); } else if (nvme_ctrl_err(ctrl) != exp_err) { warnx("TEST FAILED: nvme_vuc_req_init() returned " "wrong error %s (0x%x), not %s (0x%x)", nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, exp_err), exp_err); return (false); } else { (void) printf("TEST PASSED: nvme_vuc_req_init() " "correctly failed for %s\n", desc); return (true); } } static bool bad_fw_commit_req(nvme_ctrl_t *ctrl, nvme_fw_commit_req_t **reqp, nvme_err_t exp_err, const char *desc) { if (nvme_fw_commit_req_init(ctrl, reqp)) { warnx("TEST FAILED: nvme_fw_commit_req_init() erroneously " "passed despite %s", desc); nvme_fw_commit_req_fini(*reqp); return (false); } else if (nvme_ctrl_err(ctrl) != exp_err) { warnx("TEST FAILED: nvme_fw_commit_req_init() returned " "wrong error %s (0x%x), not %s (0x%x)", nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, exp_err), exp_err); return (false); } else { (void) printf("TEST PASSED: nvme_fw_commit_req_init() " "correctly failed for %s\n", desc); return (true); } } static bool bad_format_req(nvme_ctrl_t *ctrl, nvme_format_req_t **reqp, nvme_err_t exp_err, const char *desc) { if (nvme_format_req_init(ctrl, reqp)) { warnx("TEST FAILED: nvme_format_req_init() erroneously " "passed despite %s", desc); nvme_format_req_fini(*reqp); return (false); } else if (nvme_ctrl_err(ctrl) != exp_err) { warnx("TEST FAILED: nvme_format_req_init() returned " "wrong error %s (0x%x), not %s (0x%x)", nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)), nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl, exp_err), exp_err); return (false); } else { (void) printf("TEST PASSED: nvme_format_req_init() " "correctly failed for %s\n", desc); return (true); } } int main(void) { int ret = EXIT_SUCCESS; nvme_t *nvme; nvme_ctrl_t *ctrl; nvme_id_req_t *id_req; nvme_log_req_t *log_req; nvme_get_feat_req_t *feat_req; nvme_vuc_req_t *vuc_req; nvme_fw_commit_req_t *fw_commit_req; nvme_format_req_t *format_req; libnvme_test_init(&nvme, &ctrl); if (!bad_id_req(ctrl, NVME_CSI_NVM, NVME_IDENTIFY_CTRL, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) { ret = false; } if (!bad_id_req(ctrl, 0xff, NVME_IDENTIFY_CTRL, &id_req, NVME_ERR_IDENTIFY_UNKNOWN, "unknown identify (bad csi)")) { ret = false; } if (!bad_id_req(ctrl, NVME_CSI_NVM, UINT32_MAX, &id_req, NVME_ERR_IDENTIFY_UNKNOWN, "unknown identify (bad cns)")) { ret = false; } if (!bad_log_req(ctrl, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) { ret = false; } if (!bad_log_req_by_name(ctrl, "health", 0, NULL, NVME_ERR_BAD_PTR, "bad output pointer")) { ret = false; } if (!bad_log_req_by_name(ctrl, NULL, 0, &log_req, NVME_ERR_BAD_PTR, "bad name pointer")) { ret = false; } if (!bad_log_req_by_name(ctrl, NULL, 0x12345678, &log_req, NVME_ERR_BAD_PTR, "bad flags")) { ret = false; } if (!bad_log_req_by_name(ctrl, "elbereth", 0, &log_req, NVME_ERR_LOG_NAME_UNKNOWN, "unknown log")) { ret = false; } if (!bad_get_feat_req(ctrl, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) { ret = false; } if (!bad_get_feat_req_by_name(ctrl, "health", 0, NULL, NVME_ERR_BAD_PTR, "bad output pointer")) { ret = false; } if (!bad_get_feat_req_by_name(ctrl, NULL, 0, &feat_req, NVME_ERR_BAD_PTR, "bad name pointer")) { ret = false; } if (!bad_get_feat_req_by_name(ctrl, NULL, 0x87654321, &feat_req, NVME_ERR_BAD_PTR, "bad flags")) { ret = false; } if (!bad_get_feat_req_by_name(ctrl, "elbereth", 0, &feat_req, NVME_ERR_FEAT_NAME_UNKNOWN, "unknown feat")) { ret = false; } if (!bad_vuc_req(ctrl, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) { ret = false; } if (!bad_fw_commit_req(ctrl, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) { ret = false; } if (!bad_format_req(ctrl, NULL, NVME_ERR_BAD_PTR, "invalid req pointer")) { ret = false; } umem_setmtbf(1); if (!bad_id_req(ctrl, NVME_CSI_NVM, NVME_IDENTIFY_CTRL, &id_req, NVME_ERR_NO_MEM, "no memory")) { ret = false; } if (!bad_log_req(ctrl, &log_req, NVME_ERR_NO_MEM, "no memory")) { ret = false; } if (!bad_log_req_by_name(ctrl, "health", 0, &log_req, NVME_ERR_NO_MEM, "no memory")) { ret = false; } if (!bad_get_feat_req(ctrl, &feat_req, NVME_ERR_NO_MEM, "no memory")) { ret = false; } if (!bad_get_feat_req_by_name(ctrl, "health", 0, &feat_req, NVME_ERR_NO_MEM, "no memory")) { ret = false; } if (!bad_vuc_req(ctrl, &vuc_req, NVME_ERR_NO_MEM, "no memory")) { ret = false; } if (!bad_fw_commit_req(ctrl, &fw_commit_req, NVME_ERR_NO_MEM, "no memory")) { ret = false; } if (!bad_format_req(ctrl, &format_req, NVME_ERR_NO_MEM, "no memory")) { ret = false; } umem_setmtbf(0); if (ret == EXIT_SUCCESS) { (void) printf("All tests passed successfully\n"); } nvme_ctrl_fini(ctrl); nvme_fini(nvme); return (ret); }