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 * Perform basic NVMe identify tests on a device. This goes through and issues 18 * an identify controller on a device and then attempts to identify each 19 * namespace present. If namespace management is present, then attempt to get 20 * the generic namespace information. We only attempt to get namespace 21 * information via the namespace fd for ns 1. 22 */ 23 24 #include <err.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 #include <sys/stdbool.h> 29 30 #include "nvme_ioctl_util.h" 31 32 static void 33 basic_id_determine_ns_sup(const void *data, uint32_t *nnsp, bool *hasns) 34 { 35 const nvme_identify_ctrl_t *ctrl = data; 36 *nnsp = ctrl->id_nn; 37 *hasns = ctrl->id_oacs.oa_nsmgmt != 0; 38 } 39 40 int 41 main(void) 42 { 43 int ret = EXIT_SUCCESS; 44 int fd = nvme_ioctl_test_get_fd(0); 45 nvme_ioctl_identify_t id; 46 void *data; 47 bool hasns; 48 uint32_t nns; 49 50 if ((data = malloc(NVME_IDENTIFY_BUFSIZE)) == NULL) { 51 err(EXIT_FAILURE, "TEST FAILED: could not initialize identify " 52 "data buffer"); 53 } 54 55 (void) memset(&id, 0, sizeof (id)); 56 id.nid_cns = NVME_IDENTIFY_CTRL; 57 id.nid_data = (uintptr_t)data; 58 59 if (ioctl(fd, NVME_IOC_IDENTIFY, &id) != 0) { 60 err(EXIT_FAILURE, "TEST FAILED: cannot proceed with tests " 61 "due to failure to issue basic identify controller ioctl"); 62 } else if (id.nid_common.nioc_drv_err != NVME_IOCTL_E_OK) { 63 errx(EXIT_FAILURE, "TEST FAILED: cannot proceed with tests " 64 "due to failure to obtain basic identify controller data, " 65 "got 0x%x", id.nid_common.nioc_drv_err); 66 } 67 68 basic_id_determine_ns_sup(data, &nns, &hasns); 69 if (nns == 0) { 70 errx(EXIT_FAILURE, "TEST FAILED: somehow identified that " 71 "zero namespaces exist"); 72 } 73 (void) printf("TEST PASSED: successfully retrieved identify controller " 74 "data\n"); 75 76 for (uint32_t i = 1; i < nns; i++) { 77 (void) memset(&id, 0, sizeof (id)); 78 id.nid_common.nioc_nsid = i; 79 id.nid_cns = NVME_IDENTIFY_NSID; 80 id.nid_data = (uintptr_t)data; 81 82 if (ioctl(fd, NVME_IOC_IDENTIFY, &id) != 0) { 83 warn("TEST FAILED: failed to issue identify namespace " 84 "0x%x ioctl", i); 85 ret = EXIT_FAILURE; 86 } else if (id.nid_common.nioc_drv_err != NVME_IOCTL_E_OK) { 87 warnx("TEST FAILED: failed to obtain identify " 88 "namespace data for ns 0x%x, got error 0x%x", i, 89 id.nid_common.nioc_drv_err); 90 ret = EXIT_FAILURE; 91 } else { 92 (void) printf("TEST PASSED: retrieved identify " 93 "namespace 0x%x data\n", i); 94 } 95 } 96 97 if (hasns) { 98 (void) memset(&id, 0, sizeof (id)); 99 id.nid_common.nioc_nsid = NVME_NSID_BCAST; 100 id.nid_cns = NVME_IDENTIFY_NSID; 101 id.nid_data = (uintptr_t)data; 102 103 if (ioctl(fd, NVME_IOC_IDENTIFY, &id) != 0) { 104 warn("TEST FAILED: failed to issue identify common " 105 "namespace ioctl"); 106 ret = EXIT_FAILURE; 107 } else if (id.nid_common.nioc_drv_err != NVME_IOCTL_E_OK) { 108 warnx("TEST FAILED: failed to obtain common identify " 109 "namespace data, got error 0x%x", 110 id.nid_common.nioc_drv_err); 111 ret = EXIT_FAILURE; 112 } else { 113 (void) printf("TEST PASSED: retrieved common identify " 114 "namespace data\n"); 115 } 116 } 117 118 VERIFY0(close(fd)); 119 fd = nvme_ioctl_test_get_fd(1); 120 (void) memset(&id, 0, sizeof (id)); 121 id.nid_cns = NVME_IDENTIFY_NSID; 122 id.nid_data = (uintptr_t)data; 123 124 if (ioctl(fd, NVME_IOC_IDENTIFY, &id) != 0) { 125 warn("TEST FAILED: failed to issue identify namespace ioctl " 126 "on ns fd"); 127 ret = EXIT_FAILURE; 128 } else if (id.nid_common.nioc_drv_err != NVME_IOCTL_E_OK) { 129 warnx("TEST FAILED: failed to obtain identify namespace data " 130 "on ns fd, got error 0x%x", id.nid_common.nioc_drv_err); 131 ret = EXIT_FAILURE; 132 } else { 133 (void) printf("TEST PASSED: retrieved identify namespace data" 134 "on ns fd\n"); 135 } 136 VERIFY0(close(fd)); 137 138 return (ret); 139 } 140