xref: /illumos-gate/usr/src/test/nvme-tests/tests/libnvme/ctrl-disc.c (revision 533affcbc7fc4d0c8132976ea454aaa715fe2307)
1*533affcbSRobert Mustacchi /*
2*533affcbSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*533affcbSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*533affcbSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*533affcbSRobert Mustacchi  * 1.0 of the CDDL.
6*533affcbSRobert Mustacchi  *
7*533affcbSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*533affcbSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*533affcbSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*533affcbSRobert Mustacchi  */
11*533affcbSRobert Mustacchi 
12*533affcbSRobert Mustacchi /*
13*533affcbSRobert Mustacchi  * Copyright 2024 Oxide Computer Company
14*533affcbSRobert Mustacchi  */
15*533affcbSRobert Mustacchi 
16*533affcbSRobert Mustacchi /*
17*533affcbSRobert Mustacchi  * Test controller discovery. Because we've been given a controller, we expect
18*533affcbSRobert Mustacchi  * to be able to find a controller with the same devi while performing
19*533affcbSRobert Mustacchi  * controller discovery. Its minor should point to the same devi that the normal
20*533affcbSRobert Mustacchi  * discovery and controller do.
21*533affcbSRobert Mustacchi  */
22*533affcbSRobert Mustacchi 
23*533affcbSRobert Mustacchi #include <err.h>
24*533affcbSRobert Mustacchi #include <string.h>
25*533affcbSRobert Mustacchi #include <umem.h>
26*533affcbSRobert Mustacchi #include <sys/stat.h>
27*533affcbSRobert Mustacchi 
28*533affcbSRobert Mustacchi #include "libnvme_test_common.h"
29*533affcbSRobert Mustacchi 
30*533affcbSRobert Mustacchi static bool
ctrl_disc_count_cb(nvme_t * nvme,const nvme_ctrl_disc_t * disc,void * arg)31*533affcbSRobert Mustacchi ctrl_disc_count_cb(nvme_t *nvme, const nvme_ctrl_disc_t *disc, void *arg)
32*533affcbSRobert Mustacchi {
33*533affcbSRobert Mustacchi 	uint32_t *valp = arg;
34*533affcbSRobert Mustacchi 	*valp = *valp + 1;
35*533affcbSRobert Mustacchi 	return (true);
36*533affcbSRobert Mustacchi }
37*533affcbSRobert Mustacchi 
38*533affcbSRobert Mustacchi static bool
ctrl_check_disc(const nvme_ctrl_disc_t * disc)39*533affcbSRobert Mustacchi ctrl_check_disc(const nvme_ctrl_disc_t *disc)
40*533affcbSRobert Mustacchi {
41*533affcbSRobert Mustacchi 	bool ret = true;
42*533affcbSRobert Mustacchi 	di_node_t ctrl_devi, minor_devi;
43*533affcbSRobert Mustacchi 	di_minor_t minor;
44*533affcbSRobert Mustacchi 	const char *mname;
45*533affcbSRobert Mustacchi 
46*533affcbSRobert Mustacchi 	ctrl_devi = nvme_ctrl_disc_devi(disc);
47*533affcbSRobert Mustacchi 	minor = nvme_ctrl_disc_minor(disc);
48*533affcbSRobert Mustacchi 	minor_devi = di_minor_devinfo(minor);
49*533affcbSRobert Mustacchi 	mname = di_minor_name(minor);
50*533affcbSRobert Mustacchi 
51*533affcbSRobert Mustacchi 	if (di_minor_spectype(minor) != S_IFCHR) {
52*533affcbSRobert Mustacchi 		warnx("TEST FAILED: %s minor is not a character device, found "
53*533affcbSRobert Mustacchi 		    "0x%x\n", mname, di_minor_spectype(minor));
54*533affcbSRobert Mustacchi 		ret = false;
55*533affcbSRobert Mustacchi 	} else {
56*533affcbSRobert Mustacchi 		(void) printf("TEST PASSED: %s: minor is a character device\n",
57*533affcbSRobert Mustacchi 		    mname);
58*533affcbSRobert Mustacchi 	}
59*533affcbSRobert Mustacchi 
60*533affcbSRobert Mustacchi 	if (strcmp(di_minor_nodetype(minor), DDI_NT_NVME_NEXUS) != 0) {
61*533affcbSRobert Mustacchi 		warnx("TEST FAILED: %s minor has wrong node type %s, expected "
62*533affcbSRobert Mustacchi 		    "%s", mname, di_minor_nodetype(minor), DDI_NT_NVME_NEXUS);
63*533affcbSRobert Mustacchi 	} else {
64*533affcbSRobert Mustacchi 		(void) printf("TEST PASSED: %s minor has correct node types\n",
65*533affcbSRobert Mustacchi 		    mname);
66*533affcbSRobert Mustacchi 	}
67*533affcbSRobert Mustacchi 
68*533affcbSRobert Mustacchi 	if (minor_devi != ctrl_devi) {
69*533affcbSRobert Mustacchi 		warnx("TEST FAILED: %s minor devi does not match the "
70*533affcbSRobert Mustacchi 		    "controller devi", mname);
71*533affcbSRobert Mustacchi 		ret = false;
72*533affcbSRobert Mustacchi 	} else {
73*533affcbSRobert Mustacchi 		(void) printf("TEST PASSED: %s minor devi matches its "
74*533affcbSRobert Mustacchi 		    "controller\n", mname);
75*533affcbSRobert Mustacchi 	}
76*533affcbSRobert Mustacchi 
77*533affcbSRobert Mustacchi 	return (ret);
78*533affcbSRobert Mustacchi }
79*533affcbSRobert Mustacchi 
80*533affcbSRobert Mustacchi static bool
ctrl_match(nvme_t * nvme,nvme_ctrl_t * targ)81*533affcbSRobert Mustacchi ctrl_match(nvme_t *nvme, nvme_ctrl_t *targ)
82*533affcbSRobert Mustacchi {
83*533affcbSRobert Mustacchi 	bool ret = true, match = false;
84*533affcbSRobert Mustacchi 	nvme_ctrl_iter_t *iter = NULL;
85*533affcbSRobert Mustacchi 	const nvme_ctrl_disc_t *disc;
86*533affcbSRobert Mustacchi 	nvme_iter_t iret;
87*533affcbSRobert Mustacchi 	di_node_t targ_di;
88*533affcbSRobert Mustacchi 
89*533affcbSRobert Mustacchi 	if (!nvme_ctrl_devi(targ, &targ_di)) {
90*533affcbSRobert Mustacchi 		libnvme_test_ctrl_warn(targ, "failed to obtain di_node_t from "
91*533affcbSRobert Mustacchi 		    "controller");
92*533affcbSRobert Mustacchi 		return (false);
93*533affcbSRobert Mustacchi 	}
94*533affcbSRobert Mustacchi 
95*533affcbSRobert Mustacchi 	if (!nvme_ctrl_discover_init(nvme, &iter)) {
96*533affcbSRobert Mustacchi 		libnvme_test_hdl_warn(nvme, "failed to initialize controller "
97*533affcbSRobert Mustacchi 		    "discovery");
98*533affcbSRobert Mustacchi 		return (false);
99*533affcbSRobert Mustacchi 	}
100*533affcbSRobert Mustacchi 
101*533affcbSRobert Mustacchi 	while ((iret = nvme_ctrl_discover_step(iter, &disc)) ==
102*533affcbSRobert Mustacchi 	    NVME_ITER_VALID) {
103*533affcbSRobert Mustacchi 		if (!ctrl_check_disc(disc)) {
104*533affcbSRobert Mustacchi 			ret = false;
105*533affcbSRobert Mustacchi 		}
106*533affcbSRobert Mustacchi 
107*533affcbSRobert Mustacchi 		if (nvme_ctrl_disc_devi(disc) == targ_di) {
108*533affcbSRobert Mustacchi 			match = true;
109*533affcbSRobert Mustacchi 		}
110*533affcbSRobert Mustacchi 	}
111*533affcbSRobert Mustacchi 
112*533affcbSRobert Mustacchi 	if (iret != NVME_ITER_DONE) {
113*533affcbSRobert Mustacchi 		libnvme_test_hdl_warn(nvme, "failed to iterate controllers");
114*533affcbSRobert Mustacchi 		ret = false;
115*533affcbSRobert Mustacchi 	}
116*533affcbSRobert Mustacchi 
117*533affcbSRobert Mustacchi 	if (!match) {
118*533affcbSRobert Mustacchi 		warnx("TEST FAILED: failed to find matching controller");
119*533affcbSRobert Mustacchi 		ret = false;
120*533affcbSRobert Mustacchi 	} else {
121*533affcbSRobert Mustacchi 		(void) printf("TEST PASSED: found matching controller in "
122*533affcbSRobert Mustacchi 		    "discovery for device %s\n", getenv(NVME_TEST_DEV_ENVVAR));
123*533affcbSRobert Mustacchi 	}
124*533affcbSRobert Mustacchi 
125*533affcbSRobert Mustacchi 	nvme_ctrl_discover_fini(iter);
126*533affcbSRobert Mustacchi 	return (ret);
127*533affcbSRobert Mustacchi }
128*533affcbSRobert Mustacchi 
129*533affcbSRobert Mustacchi static bool
ctrl_disc_nop_cb(nvme_t * nvme,const nvme_ctrl_disc_t * disc,void * arg)130*533affcbSRobert Mustacchi ctrl_disc_nop_cb(nvme_t *nvme, const nvme_ctrl_disc_t *disc, void *arg)
131*533affcbSRobert Mustacchi {
132*533affcbSRobert Mustacchi 	return (true);
133*533affcbSRobert Mustacchi }
134*533affcbSRobert Mustacchi 
135*533affcbSRobert Mustacchi static bool
ctrl_disc_bad_disc_init(nvme_t * nvme,nvme_ctrl_iter_t ** iterp,nvme_err_t exp_err,const char * desc)136*533affcbSRobert Mustacchi ctrl_disc_bad_disc_init(nvme_t *nvme, nvme_ctrl_iter_t **iterp,
137*533affcbSRobert Mustacchi     nvme_err_t exp_err, const char *desc)
138*533affcbSRobert Mustacchi {
139*533affcbSRobert Mustacchi 	if (nvme_ctrl_discover_init(nvme, iterp)) {
140*533affcbSRobert Mustacchi 		warnx("TEST FAILED: nvme_ctrl_discover_init() erroneously "
141*533affcbSRobert Mustacchi 		    "passed despite %s\n", desc);
142*533affcbSRobert Mustacchi 		return (false);
143*533affcbSRobert Mustacchi 	} else if (nvme_err(nvme) != exp_err) {
144*533affcbSRobert Mustacchi 		warnx("TEST FAILED: nvme_ctrl_discover_init() returned "
145*533affcbSRobert Mustacchi 		    "wrong error %s (0x%x), not %s (0x%x)",
146*533affcbSRobert Mustacchi 		    nvme_errtostr(nvme, nvme_err(nvme)), nvme_err(nvme),
147*533affcbSRobert Mustacchi 		    nvme_errtostr(nvme, exp_err), exp_err);
148*533affcbSRobert Mustacchi 		return (false);
149*533affcbSRobert Mustacchi 	} else {
150*533affcbSRobert Mustacchi 		(void) printf("TEST PASSED: nvme_ctrl_discover_init() failed "
151*533affcbSRobert Mustacchi 		    "correctly for %s\n", desc);
152*533affcbSRobert Mustacchi 		return (true);
153*533affcbSRobert Mustacchi 	}
154*533affcbSRobert Mustacchi }
155*533affcbSRobert Mustacchi 
156*533affcbSRobert Mustacchi static bool
ctrl_disc_bad_disc(nvme_t * nvme,nvme_ctrl_disc_f func,nvme_err_t exp_err,const char * desc)157*533affcbSRobert Mustacchi ctrl_disc_bad_disc(nvme_t *nvme, nvme_ctrl_disc_f func, nvme_err_t exp_err,
158*533affcbSRobert Mustacchi     const char *desc)
159*533affcbSRobert Mustacchi {
160*533affcbSRobert Mustacchi 	if (nvme_ctrl_discover(nvme, func, NULL)) {
161*533affcbSRobert Mustacchi 		warnx("TEST FAILED: nvme_ctrl_discover() erroneously "
162*533affcbSRobert Mustacchi 		    "passed despite %s\n", desc);
163*533affcbSRobert Mustacchi 		return (false);
164*533affcbSRobert Mustacchi 	} else if (nvme_err(nvme) != exp_err) {
165*533affcbSRobert Mustacchi 		warnx("TEST FAILED: nvme_ctrl_discover() returned "
166*533affcbSRobert Mustacchi 		    "wrong error %s (0x%x), not %s (0x%x)",
167*533affcbSRobert Mustacchi 		    nvme_errtostr(nvme, nvme_err(nvme)), nvme_err(nvme),
168*533affcbSRobert Mustacchi 		    nvme_errtostr(nvme, exp_err), exp_err);
169*533affcbSRobert Mustacchi 		return (false);
170*533affcbSRobert Mustacchi 	} else {
171*533affcbSRobert Mustacchi 		(void) printf("TEST PASSED: nvme_ctrl_discover() failed "
172*533affcbSRobert Mustacchi 		    "correctly for %s\n", desc);
173*533affcbSRobert Mustacchi 		return (true);
174*533affcbSRobert Mustacchi 	}
175*533affcbSRobert Mustacchi }
176*533affcbSRobert Mustacchi 
177*533affcbSRobert Mustacchi int
main(void)178*533affcbSRobert Mustacchi main(void)
179*533affcbSRobert Mustacchi {
180*533affcbSRobert Mustacchi 	int ret = EXIT_SUCCESS;
181*533affcbSRobert Mustacchi 	nvme_t *nvme;
182*533affcbSRobert Mustacchi 	nvme_ctrl_t *ctrl;
183*533affcbSRobert Mustacchi 	uint32_t nctrl = 0;
184*533affcbSRobert Mustacchi 	nvme_ctrl_iter_t *iter;
185*533affcbSRobert Mustacchi 
186*533affcbSRobert Mustacchi 	libnvme_test_init(&nvme, &ctrl);
187*533affcbSRobert Mustacchi 
188*533affcbSRobert Mustacchi 	if (!nvme_ctrl_discover(nvme, ctrl_disc_count_cb, &nctrl)) {
189*533affcbSRobert Mustacchi 		libnvme_test_hdl_warn(nvme, "failed to discover controllers");
190*533affcbSRobert Mustacchi 		ret = EXIT_FAILURE;
191*533affcbSRobert Mustacchi 	} else if (nctrl == 0) {
192*533affcbSRobert Mustacchi 		warnx("TEST FAILED: discovered zero controllers somehow!");
193*533affcbSRobert Mustacchi 		ret = EXIT_FAILURE;
194*533affcbSRobert Mustacchi 	} else {
195*533affcbSRobert Mustacchi 		(void) printf("TEST PASSED: discovered some number of "
196*533affcbSRobert Mustacchi 		    "controllers");
197*533affcbSRobert Mustacchi 	}
198*533affcbSRobert Mustacchi 
199*533affcbSRobert Mustacchi 	if (!ctrl_match(nvme, ctrl)) {
200*533affcbSRobert Mustacchi 		ret = EXIT_FAILURE;
201*533affcbSRobert Mustacchi 	}
202*533affcbSRobert Mustacchi 
203*533affcbSRobert Mustacchi 	if (!ctrl_disc_bad_disc_init(nvme, NULL, NVME_ERR_BAD_PTR,
204*533affcbSRobert Mustacchi 	    "invalid iter pointer")) {
205*533affcbSRobert Mustacchi 		ret = EXIT_FAILURE;
206*533affcbSRobert Mustacchi 	}
207*533affcbSRobert Mustacchi 
208*533affcbSRobert Mustacchi 	if (!ctrl_disc_bad_disc(nvme, NULL, NVME_ERR_BAD_PTR,
209*533affcbSRobert Mustacchi 	    "invalid function pointer")) {
210*533affcbSRobert Mustacchi 		ret = EXIT_FAILURE;
211*533affcbSRobert Mustacchi 	}
212*533affcbSRobert Mustacchi 
213*533affcbSRobert Mustacchi 	umem_setmtbf(1);
214*533affcbSRobert Mustacchi 	if (!ctrl_disc_bad_disc_init(nvme, &iter, NVME_ERR_NO_MEM,
215*533affcbSRobert Mustacchi 	    "no memory")) {
216*533affcbSRobert Mustacchi 		ret = EXIT_FAILURE;
217*533affcbSRobert Mustacchi 	}
218*533affcbSRobert Mustacchi 
219*533affcbSRobert Mustacchi 	if (!ctrl_disc_bad_disc(nvme, ctrl_disc_nop_cb, NVME_ERR_NO_MEM,
220*533affcbSRobert Mustacchi 	    "no memory")) {
221*533affcbSRobert Mustacchi 		ret = EXIT_FAILURE;
222*533affcbSRobert Mustacchi 	}
223*533affcbSRobert Mustacchi 	umem_setmtbf(0);
224*533affcbSRobert Mustacchi 
225*533affcbSRobert Mustacchi 	if (ret == EXIT_SUCCESS) {
226*533affcbSRobert Mustacchi 		(void) printf("All tests passed successfully\n");
227*533affcbSRobert Mustacchi 	}
228*533affcbSRobert Mustacchi 
229*533affcbSRobert Mustacchi 	nvme_ctrl_fini(ctrl);
230*533affcbSRobert Mustacchi 	nvme_fini(nvme);
231*533affcbSRobert Mustacchi 	return (ret);
232*533affcbSRobert Mustacchi }
233