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 * Basic test to verify that we can run a namespace out of capacity. We do this 18 * in two ways: 19 * 20 * 1) A single namespace creation that uses all of the device's capacity. 21 * 2) Creating a second namespace where the first has already used up 22 * everything. 23 * 24 * This test starts from the device-empty profile. 25 */ 26 27 #include <err.h> 28 #include <stdlib.h> 29 #include <sys/sysmacros.h> 30 #include "libnvme_test_common.h" 31 32 int 33 main(void) 34 { 35 int ret = EXIT_SUCCESS; 36 nvme_t *nvme; 37 nvme_ctrl_t *ctrl; 38 nvme_ctrl_info_t *info; 39 uint32_t lbaf; 40 nvme_uint128_t cap; 41 uint64_t size; 42 nvme_err_t err; 43 44 libnvme_test_init(&nvme, &ctrl); 45 if (!nvme_ctrl_lock(ctrl, NVME_LOCK_L_WRITE, NVME_LOCK_F_DONT_BLOCK)) { 46 libnvme_test_ctrl_fatal(ctrl, "failed to obtain write lock"); 47 } 48 49 if (!nvme_ctrl_info_snap(ctrl, &info)) { 50 libnvme_test_ctrl_fatal(ctrl, "failed to get info snapshot"); 51 } 52 53 if (!libnvme_test_lbaf(info, NVME_TEST_LBA_SIZE, &lbaf)) { 54 errx(EXIT_FAILURE, "failed to find 4K LBA format, cannot " 55 "continue"); 56 } 57 58 if (!nvme_ctrl_info_cap(info, &cap)) { 59 libnvme_test_ctrl_info_fatal(info, "failed to get device " 60 "capacity"); 61 } 62 63 if (cap.hi != 0) { 64 errx(EXIT_FAILURE, "encountered device with > uint64_t " 65 "capacity, this program needs to be updated to deal with " 66 "that"); 67 } 68 69 size = cap.lo / NVME_TEST_LBA_SIZE; 70 size += NVME_TEST_NS_SIZE / NVME_TEST_LBA_SIZE; 71 72 if (!libnvme_test_ns_create(ctrl, size, lbaf, NULL, &err)) { 73 warnx("TEST FAILED: failed to initialize create namespace for " 74 "namespace larger than the device's capacity (0x%" 75 PRIx64 ")", size); 76 ret = EXIT_FAILURE; 77 } else if (!libnvme_test_ctrl_err(ctrl, NVME_CQE_SCT_SPECIFIC, 78 NVME_CQE_SC_SPC_NS_INSUF_CAP, "namespace exceeds device " 79 "capacity")) { 80 ret = EXIT_FAILURE; 81 } 82 83 size = cap.lo / NVME_TEST_LBA_SIZE; 84 size -= NVME_TEST_NS_SIZE / NVME_TEST_LBA_SIZE; 85 86 if (!libnvme_test_ns_create(ctrl, size, lbaf, NULL, NULL)) { 87 exit(EXIT_FAILURE); 88 } 89 90 size = 2 * (NVME_TEST_NS_SIZE / NVME_TEST_LBA_SIZE); 91 if (!libnvme_test_ns_create(ctrl, size, lbaf, NULL, &err)) { 92 warnx("TEST FAILED: failed to initialize create namespace " 93 "request for namespace with insufficient device capacity " 94 "(0x%" PRIx64 ")", size); 95 ret = EXIT_FAILURE; 96 } else if (!libnvme_test_ctrl_err(ctrl, NVME_CQE_SCT_SPECIFIC, 97 NVME_CQE_SC_SPC_NS_INSUF_CAP, "insufficient device capacity")) { 98 ret = EXIT_FAILURE; 99 } 100 101 nvme_ctrl_info_free(info); 102 nvme_ctrl_unlock(ctrl); 103 nvme_ctrl_fini(ctrl); 104 nvme_fini(nvme); 105 106 if (ret == EXIT_SUCCESS) { 107 (void) printf("All tests passed successfully\n"); 108 } 109 110 return (ret); 111 } 112