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 * Iterate over the namespaces and ensure that the information we get in the
18*533affcbSRobert Mustacchi * discovery is the same as when we take a snapshot. To ensure that nothing
19*533affcbSRobert Mustacchi * changes out from under us, we take a controller write lock which will ensure
20*533affcbSRobert Mustacchi * that no modifications can occur.
21*533affcbSRobert Mustacchi *
22*533affcbSRobert Mustacchi * In addition, we want to test that discovery filters work so we first go
23*533affcbSRobert Mustacchi * through and count the different levels.
24*533affcbSRobert Mustacchi */
25*533affcbSRobert Mustacchi
26*533affcbSRobert Mustacchi #include <err.h>
27*533affcbSRobert Mustacchi #include <string.h>
28*533affcbSRobert Mustacchi #include <umem.h>
29*533affcbSRobert Mustacchi
30*533affcbSRobert Mustacchi #include "libnvme_test_common.h"
31*533affcbSRobert Mustacchi
32*533affcbSRobert Mustacchi static bool
ns_disc_count_cb(nvme_ctrl_t * ctrl,const nvme_ns_disc_t * disc,void * arg)33*533affcbSRobert Mustacchi ns_disc_count_cb(nvme_ctrl_t *ctrl, const nvme_ns_disc_t *disc, void *arg)
34*533affcbSRobert Mustacchi {
35*533affcbSRobert Mustacchi uint32_t *valp = arg;
36*533affcbSRobert Mustacchi *valp = *valp + 1;
37*533affcbSRobert Mustacchi return (true);
38*533affcbSRobert Mustacchi }
39*533affcbSRobert Mustacchi
40*533affcbSRobert Mustacchi static bool
ns_disc_count(nvme_ctrl_t * ctrl,nvme_ns_disc_level_t level,uint32_t exp)41*533affcbSRobert Mustacchi ns_disc_count(nvme_ctrl_t *ctrl, nvme_ns_disc_level_t level, uint32_t exp)
42*533affcbSRobert Mustacchi {
43*533affcbSRobert Mustacchi uint32_t count = 0;
44*533affcbSRobert Mustacchi
45*533affcbSRobert Mustacchi if (!nvme_ns_discover(ctrl, level, ns_disc_count_cb, &count)) {
46*533affcbSRobert Mustacchi libnvme_test_ctrl_warn(ctrl, "failed to discover at level %u",
47*533affcbSRobert Mustacchi level);
48*533affcbSRobert Mustacchi return (false);
49*533affcbSRobert Mustacchi } else if (count != exp) {
50*533affcbSRobert Mustacchi warnx("TEST FAILED: ns discovery level %u found 0x%x "
51*533affcbSRobert Mustacchi "namespaces, but expected 0x%x", level, count, exp);
52*533affcbSRobert Mustacchi return (false);
53*533affcbSRobert Mustacchi } else {
54*533affcbSRobert Mustacchi (void) printf("TEST PASSED: ns discovery level %u had correct "
55*533affcbSRobert Mustacchi "count (0x%x)\n", level, exp);
56*533affcbSRobert Mustacchi return (true);
57*533affcbSRobert Mustacchi }
58*533affcbSRobert Mustacchi }
59*533affcbSRobert Mustacchi
60*533affcbSRobert Mustacchi static bool
ns_disc_blkdev_cb(nvme_ctrl_t * ctrl,const nvme_ns_disc_t * disc,void * arg)61*533affcbSRobert Mustacchi ns_disc_blkdev_cb(nvme_ctrl_t *ctrl, const nvme_ns_disc_t *disc, void *arg)
62*533affcbSRobert Mustacchi {
63*533affcbSRobert Mustacchi int *ret = arg;
64*533affcbSRobert Mustacchi nvme_ns_info_t *info;
65*533affcbSRobert Mustacchi const uint32_t nsid = nvme_ns_disc_nsid(disc);
66*533affcbSRobert Mustacchi const char *addr;
67*533affcbSRobert Mustacchi
68*533affcbSRobert Mustacchi if (nvme_ns_disc_level(disc) < NVME_NS_DISC_F_BLKDEV) {
69*533affcbSRobert Mustacchi warnx("TEST FAILED: ns %u has level %u, but filtering on "
70*533affcbSRobert Mustacchi "blkdev (%u)", nsid, nvme_ns_disc_level(disc),
71*533affcbSRobert Mustacchi NVME_NS_DISC_F_BLKDEV);
72*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
73*533affcbSRobert Mustacchi return (true);
74*533affcbSRobert Mustacchi }
75*533affcbSRobert Mustacchi
76*533affcbSRobert Mustacchi if (!nvme_ctrl_ns_info_snap(ctrl, nsid, &info)) {
77*533affcbSRobert Mustacchi libnvme_test_ctrl_warn(ctrl, "failed to get info snapshot for "
78*533affcbSRobert Mustacchi "nsid %u", nsid);
79*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
80*533affcbSRobert Mustacchi return (true);
81*533affcbSRobert Mustacchi }
82*533affcbSRobert Mustacchi
83*533affcbSRobert Mustacchi if (!nvme_ns_info_bd_addr(info, &addr)) {
84*533affcbSRobert Mustacchi libnvme_test_ctrl_warn(ctrl, "failed to get bd addr for nsid "
85*533affcbSRobert Mustacchi "%u", nsid);
86*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
87*533affcbSRobert Mustacchi } else if (addr[0] == '\0') {
88*533affcbSRobert Mustacchi warnx("TEST FAILED: nsid %u has invalid bd addr", nsid);
89*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
90*533affcbSRobert Mustacchi } else {
91*533affcbSRobert Mustacchi (void) printf("TEST PASSED: nsid %u bd addr valid\n", nsid);
92*533affcbSRobert Mustacchi }
93*533affcbSRobert Mustacchi
94*533affcbSRobert Mustacchi nvme_ns_info_free(info);
95*533affcbSRobert Mustacchi return (true);
96*533affcbSRobert Mustacchi }
97*533affcbSRobert Mustacchi
98*533affcbSRobert Mustacchi static bool
ns_disc_guids_cb(nvme_ctrl_t * ctrl,const nvme_ns_disc_t * disc,void * arg)99*533affcbSRobert Mustacchi ns_disc_guids_cb(nvme_ctrl_t *ctrl, const nvme_ns_disc_t *disc, void *arg)
100*533affcbSRobert Mustacchi {
101*533affcbSRobert Mustacchi int *ret = arg;
102*533affcbSRobert Mustacchi nvme_ns_info_t *info;
103*533affcbSRobert Mustacchi const uint32_t nsid = nvme_ns_disc_nsid(disc);
104*533affcbSRobert Mustacchi const nvme_ns_disc_flags_t flags = nvme_ns_disc_flags(disc);
105*533affcbSRobert Mustacchi uint8_t id[16];
106*533affcbSRobert Mustacchi bool bret;
107*533affcbSRobert Mustacchi
108*533affcbSRobert Mustacchi if (nvme_ns_disc_level(disc) < NVME_NS_DISC_F_ACTIVE) {
109*533affcbSRobert Mustacchi warnx("TEST FAILED: ns %u has level %u, but filtering on "
110*533affcbSRobert Mustacchi "active (%u)", nsid, nvme_ns_disc_level(disc),
111*533affcbSRobert Mustacchi NVME_NS_DISC_F_ACTIVE);
112*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
113*533affcbSRobert Mustacchi return (true);
114*533affcbSRobert Mustacchi }
115*533affcbSRobert Mustacchi
116*533affcbSRobert Mustacchi if (!nvme_ctrl_ns_info_snap(ctrl, nsid, &info)) {
117*533affcbSRobert Mustacchi libnvme_test_ctrl_warn(ctrl, "failed to get info snapshot for "
118*533affcbSRobert Mustacchi "nsid %u", nsid);
119*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
120*533affcbSRobert Mustacchi return (true);
121*533affcbSRobert Mustacchi }
122*533affcbSRobert Mustacchi
123*533affcbSRobert Mustacchi bret = nvme_ns_info_eui64(info, id);
124*533affcbSRobert Mustacchi if (bret != ((flags & NVME_NS_DISC_F_EUI64_VALID) != 0)) {
125*533affcbSRobert Mustacchi warnx("TEST FAILED: nvme_ns_info_eui64() returned %s, but "
126*533affcbSRobert Mustacchi "expected %s from discovery information for nsid %u",
127*533affcbSRobert Mustacchi bret ? "true" : "false",
128*533affcbSRobert Mustacchi (flags & NVME_NS_DISC_F_EUI64_VALID) != 0 ? "true" :
129*533affcbSRobert Mustacchi "false", nsid);
130*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
131*533affcbSRobert Mustacchi } else {
132*533affcbSRobert Mustacchi (void) printf("TEST PASSED: namespace snapshot and discovery "
133*533affcbSRobert Mustacchi "agreed on EUI64 presence for nsid %u\n", nsid);
134*533affcbSRobert Mustacchi }
135*533affcbSRobert Mustacchi
136*533affcbSRobert Mustacchi if (bret) {
137*533affcbSRobert Mustacchi const uint8_t *eui64 = nvme_ns_disc_eui64(disc);
138*533affcbSRobert Mustacchi const uint8_t zero[8] = { 0 };
139*533affcbSRobert Mustacchi
140*533affcbSRobert Mustacchi if (memcmp(eui64, id, sizeof (zero)) != 0) {
141*533affcbSRobert Mustacchi warnx("TEST FAILED: EUI64 differs between "
142*533affcbSRobert Mustacchi "discovery and info snapshot for nsid %u", nsid);
143*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
144*533affcbSRobert Mustacchi } else {
145*533affcbSRobert Mustacchi (void) printf("TEST PASSED: EUI64 equal between "
146*533affcbSRobert Mustacchi "discovery and info snapshot for nsid %u\n", nsid);
147*533affcbSRobert Mustacchi }
148*533affcbSRobert Mustacchi
149*533affcbSRobert Mustacchi if (memcmp(id, zero, sizeof (zero)) == 0) {
150*533affcbSRobert Mustacchi warnx("TEST FAILED: Found invalid zero EUI64 for nsid "
151*533affcbSRobert Mustacchi "%u", nsid);
152*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
153*533affcbSRobert Mustacchi } else {
154*533affcbSRobert Mustacchi (void) printf("TEST PASSED: EUI64 is non-zero for "
155*533affcbSRobert Mustacchi "nsid %u\n", nsid);
156*533affcbSRobert Mustacchi }
157*533affcbSRobert Mustacchi } else {
158*533affcbSRobert Mustacchi if (nvme_ns_disc_eui64(disc) != NULL) {
159*533affcbSRobert Mustacchi warnx("TEST FAILED: discovery EUI64 was valid, but "
160*533affcbSRobert Mustacchi "should be NULL for nsid %u", nsid);
161*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
162*533affcbSRobert Mustacchi } else {
163*533affcbSRobert Mustacchi (void) printf("TEST PASSED: discovery EUI64 correctly "
164*533affcbSRobert Mustacchi "returned NULL for nsid %u\n", nsid);
165*533affcbSRobert Mustacchi }
166*533affcbSRobert Mustacchi
167*533affcbSRobert Mustacchi switch (nvme_ns_info_err(info)) {
168*533affcbSRobert Mustacchi case NVME_INFO_ERR_VERSION:
169*533affcbSRobert Mustacchi case NVME_INFO_ERR_MISSING_CAP:
170*533affcbSRobert Mustacchi (void) printf("TEST PASSED: nvme_ns_info_eui64() "
171*533affcbSRobert Mustacchi "returned a valid error for nsid %u\n", nsid);
172*533affcbSRobert Mustacchi break;
173*533affcbSRobert Mustacchi default:
174*533affcbSRobert Mustacchi warnx("TEST FAILED: nvme_ns_info_eui64() returned an "
175*533affcbSRobert Mustacchi "invalid error for nsid %u: %s (%u)", nsid,
176*533affcbSRobert Mustacchi nvme_ns_info_errtostr(info, nvme_ns_info_err(info)),
177*533affcbSRobert Mustacchi nvme_ns_info_err(info));
178*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
179*533affcbSRobert Mustacchi break;
180*533affcbSRobert Mustacchi }
181*533affcbSRobert Mustacchi }
182*533affcbSRobert Mustacchi
183*533affcbSRobert Mustacchi bret = nvme_ns_info_nguid(info, id);
184*533affcbSRobert Mustacchi if (bret != ((flags & NVME_NS_DISC_F_NGUID_VALID) != 0)) {
185*533affcbSRobert Mustacchi warnx("TEST FAILED: nvme_ns_info_nguid() returned %s, but "
186*533affcbSRobert Mustacchi "expected %s from discovery information for nsid %u",
187*533affcbSRobert Mustacchi bret ? "true" : "false",
188*533affcbSRobert Mustacchi (flags & NVME_NS_DISC_F_NGUID_VALID) != 0 ? "true" :
189*533affcbSRobert Mustacchi "false", nsid);
190*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
191*533affcbSRobert Mustacchi } else {
192*533affcbSRobert Mustacchi (void) printf("TEST PASSED: namespace snapshot and discovery "
193*533affcbSRobert Mustacchi "agreed on NGUID presence for nsid %u\n", nsid);
194*533affcbSRobert Mustacchi }
195*533affcbSRobert Mustacchi
196*533affcbSRobert Mustacchi if (bret) {
197*533affcbSRobert Mustacchi const uint8_t *nguid = nvme_ns_disc_nguid(disc);
198*533affcbSRobert Mustacchi const uint8_t zero[16] = { 0 };
199*533affcbSRobert Mustacchi
200*533affcbSRobert Mustacchi if (memcmp(nguid, id, sizeof (zero)) != 0) {
201*533affcbSRobert Mustacchi warnx("TEST FAILED: NGUID differs between "
202*533affcbSRobert Mustacchi "discovery and info snapshot for nsid %u", nsid);
203*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
204*533affcbSRobert Mustacchi } else {
205*533affcbSRobert Mustacchi (void) printf("TEST PASSED: NGUID equal between "
206*533affcbSRobert Mustacchi "discovery and info snapshot for nsid %u\n", nsid);
207*533affcbSRobert Mustacchi }
208*533affcbSRobert Mustacchi
209*533affcbSRobert Mustacchi if (memcmp(id, zero, sizeof (zero)) == 0) {
210*533affcbSRobert Mustacchi warnx("TEST FAILED: Found invalid zero NGUID for nsid "
211*533affcbSRobert Mustacchi "%u", nsid);
212*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
213*533affcbSRobert Mustacchi } else {
214*533affcbSRobert Mustacchi (void) printf("TEST PASSED: NGUID is non-zero for "
215*533affcbSRobert Mustacchi "nsid %u\n", nsid);
216*533affcbSRobert Mustacchi }
217*533affcbSRobert Mustacchi } else {
218*533affcbSRobert Mustacchi if (nvme_ns_disc_nguid(disc) != NULL) {
219*533affcbSRobert Mustacchi warnx("TEST FAILED: discovery NGUID was valid, but "
220*533affcbSRobert Mustacchi "should be NULL for nsid %u", nsid);
221*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
222*533affcbSRobert Mustacchi } else {
223*533affcbSRobert Mustacchi (void) printf("TEST PASSED: discovery NGUID correctly "
224*533affcbSRobert Mustacchi "returned NULL for nsid %u\n", nsid);
225*533affcbSRobert Mustacchi }
226*533affcbSRobert Mustacchi
227*533affcbSRobert Mustacchi switch (nvme_ns_info_err(info)) {
228*533affcbSRobert Mustacchi case NVME_INFO_ERR_VERSION:
229*533affcbSRobert Mustacchi case NVME_INFO_ERR_MISSING_CAP:
230*533affcbSRobert Mustacchi (void) printf("TEST PASSED: nvme_ns_info_nguid() "
231*533affcbSRobert Mustacchi "returned a valid error for nsid %u\n", nsid);
232*533affcbSRobert Mustacchi break;
233*533affcbSRobert Mustacchi default:
234*533affcbSRobert Mustacchi warnx("TEST FAILED: nvme_ns_info_nguid() returned an "
235*533affcbSRobert Mustacchi "invalid error for nsid %u: %s (%u)", nsid,
236*533affcbSRobert Mustacchi nvme_ns_info_errtostr(info, nvme_ns_info_err(info)),
237*533affcbSRobert Mustacchi nvme_ns_info_err(info));
238*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
239*533affcbSRobert Mustacchi break;
240*533affcbSRobert Mustacchi }
241*533affcbSRobert Mustacchi }
242*533affcbSRobert Mustacchi nvme_ns_info_free(info);
243*533affcbSRobert Mustacchi return (true);
244*533affcbSRobert Mustacchi }
245*533affcbSRobert Mustacchi
246*533affcbSRobert Mustacchi static bool
ns_disc_level_cb(nvme_ctrl_t * ctrl,const nvme_ns_disc_t * disc,void * arg)247*533affcbSRobert Mustacchi ns_disc_level_cb(nvme_ctrl_t *ctrl, const nvme_ns_disc_t *disc, void *arg)
248*533affcbSRobert Mustacchi {
249*533affcbSRobert Mustacchi int *ret = arg;
250*533affcbSRobert Mustacchi nvme_ns_info_t *info;
251*533affcbSRobert Mustacchi const uint32_t nsid = nvme_ns_disc_nsid(disc);
252*533affcbSRobert Mustacchi
253*533affcbSRobert Mustacchi if (!nvme_ctrl_ns_info_snap(ctrl, nsid, &info)) {
254*533affcbSRobert Mustacchi libnvme_test_ctrl_warn(ctrl, "failed to get info snapshot for "
255*533affcbSRobert Mustacchi "nsid %u", nsid);
256*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
257*533affcbSRobert Mustacchi return (true);
258*533affcbSRobert Mustacchi }
259*533affcbSRobert Mustacchi
260*533affcbSRobert Mustacchi if (nvme_ns_disc_level(disc) != nvme_ns_info_level(info)) {
261*533affcbSRobert Mustacchi warnx("TEST FAILED: discovery and ns info snapshot disagree "
262*533affcbSRobert Mustacchi "on discovery level: disc has %u, info has %u",
263*533affcbSRobert Mustacchi nvme_ns_disc_level(disc), nvme_ns_info_level(info));
264*533affcbSRobert Mustacchi *ret = EXIT_FAILURE;
265*533affcbSRobert Mustacchi } else {
266*533affcbSRobert Mustacchi (void) printf("TEST PASSED: discovery and ns info snapshot "
267*533affcbSRobert Mustacchi "agree for nsid %u\n", nsid);
268*533affcbSRobert Mustacchi }
269*533affcbSRobert Mustacchi
270*533affcbSRobert Mustacchi nvme_ns_info_free(info);
271*533affcbSRobert Mustacchi return (true);
272*533affcbSRobert Mustacchi }
273*533affcbSRobert Mustacchi
274*533affcbSRobert Mustacchi static bool
ns_disc_bad_disc_init(nvme_ctrl_t * ctrl,nvme_ns_disc_level_t level,nvme_ns_iter_t ** iterp,nvme_err_t exp_err,const char * desc)275*533affcbSRobert Mustacchi ns_disc_bad_disc_init(nvme_ctrl_t *ctrl, nvme_ns_disc_level_t level,
276*533affcbSRobert Mustacchi nvme_ns_iter_t **iterp, nvme_err_t exp_err, const char *desc)
277*533affcbSRobert Mustacchi {
278*533affcbSRobert Mustacchi if (nvme_ns_discover_init(ctrl, level, iterp)) {
279*533affcbSRobert Mustacchi warnx("TEST FAILED: nvme_ns_discover_init() erroneously "
280*533affcbSRobert Mustacchi "passed despite %s", desc);
281*533affcbSRobert Mustacchi nvme_ns_discover_fini(*iterp);
282*533affcbSRobert Mustacchi return (false);
283*533affcbSRobert Mustacchi } else if (nvme_ctrl_err(ctrl) != exp_err) {
284*533affcbSRobert Mustacchi warnx("TEST FAILED: nvme_ns_discover_init() returned "
285*533affcbSRobert Mustacchi "wrong error %s (0x%x), not %s (0x%x)",
286*533affcbSRobert Mustacchi nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
287*533affcbSRobert Mustacchi nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
288*533affcbSRobert Mustacchi exp_err), exp_err);
289*533affcbSRobert Mustacchi return (false);
290*533affcbSRobert Mustacchi } else {
291*533affcbSRobert Mustacchi (void) printf("TEST PASSED: nvme_ns_discover_init() failed "
292*533affcbSRobert Mustacchi "correctly for %s\n", desc);
293*533affcbSRobert Mustacchi return (true);
294*533affcbSRobert Mustacchi }
295*533affcbSRobert Mustacchi }
296*533affcbSRobert Mustacchi
297*533affcbSRobert Mustacchi static bool
ns_disc_bad_disc(nvme_ctrl_t * ctrl,nvme_ns_disc_level_t level,nvme_ns_disc_f func,nvme_err_t exp_err,const char * desc)298*533affcbSRobert Mustacchi ns_disc_bad_disc(nvme_ctrl_t *ctrl, nvme_ns_disc_level_t level,
299*533affcbSRobert Mustacchi nvme_ns_disc_f func, nvme_err_t exp_err, const char *desc)
300*533affcbSRobert Mustacchi {
301*533affcbSRobert Mustacchi if (nvme_ns_discover(ctrl, level, func, NULL)) {
302*533affcbSRobert Mustacchi warnx("TEST FAILED: nvme_ns_discover() erroneously "
303*533affcbSRobert Mustacchi "passed despite %s", desc);
304*533affcbSRobert Mustacchi return (false);
305*533affcbSRobert Mustacchi } else if (nvme_ctrl_err(ctrl) != exp_err) {
306*533affcbSRobert Mustacchi warnx("TEST FAILED: nvme_ns_discover() returned "
307*533affcbSRobert Mustacchi "wrong error %s (0x%x), not %s (0x%x)",
308*533affcbSRobert Mustacchi nvme_ctrl_errtostr(ctrl, nvme_ctrl_err(ctrl)),
309*533affcbSRobert Mustacchi nvme_ctrl_err(ctrl), nvme_ctrl_errtostr(ctrl,
310*533affcbSRobert Mustacchi exp_err), exp_err);
311*533affcbSRobert Mustacchi return (false);
312*533affcbSRobert Mustacchi } else {
313*533affcbSRobert Mustacchi (void) printf("TEST PASSED: nvme_ns_discover() failed "
314*533affcbSRobert Mustacchi "correctly for %s\n", desc);
315*533affcbSRobert Mustacchi return (true);
316*533affcbSRobert Mustacchi }
317*533affcbSRobert Mustacchi }
318*533affcbSRobert Mustacchi
319*533affcbSRobert Mustacchi static bool
ns_disc_nop_cb(nvme_ctrl_t * ctrl,const nvme_ns_disc_t * disc,void * arg)320*533affcbSRobert Mustacchi ns_disc_nop_cb(nvme_ctrl_t *ctrl, const nvme_ns_disc_t *disc, void *arg)
321*533affcbSRobert Mustacchi {
322*533affcbSRobert Mustacchi return (true);
323*533affcbSRobert Mustacchi }
324*533affcbSRobert Mustacchi
325*533affcbSRobert Mustacchi int
main(void)326*533affcbSRobert Mustacchi main(void)
327*533affcbSRobert Mustacchi {
328*533affcbSRobert Mustacchi int ret = EXIT_SUCCESS;
329*533affcbSRobert Mustacchi nvme_t *nvme;
330*533affcbSRobert Mustacchi nvme_ctrl_t *ctrl;
331*533affcbSRobert Mustacchi nvme_ctrl_info_t *info;
332*533affcbSRobert Mustacchi nvme_iter_t iret;
333*533affcbSRobert Mustacchi nvme_ns_iter_t *iter;
334*533affcbSRobert Mustacchi const nvme_ns_disc_t *disc;
335*533affcbSRobert Mustacchi uint32_t nbd = 0, nni = 0, nact = 0, nalloc = 0, nns = 0;
336*533affcbSRobert Mustacchi
337*533affcbSRobert Mustacchi libnvme_test_init(&nvme, &ctrl);
338*533affcbSRobert Mustacchi if (!nvme_ctrl_lock(ctrl, NVME_LOCK_L_WRITE, NVME_LOCK_F_DONT_BLOCK)) {
339*533affcbSRobert Mustacchi libnvme_test_ctrl_fatal(ctrl, "failed to obtain write lock");
340*533affcbSRobert Mustacchi }
341*533affcbSRobert Mustacchi
342*533affcbSRobert Mustacchi if (!nvme_ns_discover_init(ctrl, NVME_NS_DISC_F_ALL, &iter)) {
343*533affcbSRobert Mustacchi libnvme_test_ctrl_fatal(ctrl, "failed to initialize initial "
344*533affcbSRobert Mustacchi "ns discovery");
345*533affcbSRobert Mustacchi }
346*533affcbSRobert Mustacchi
347*533affcbSRobert Mustacchi while ((iret = nvme_ns_discover_step(iter, &disc)) == NVME_ITER_VALID) {
348*533affcbSRobert Mustacchi switch (nvme_ns_disc_level(disc)) {
349*533affcbSRobert Mustacchi case NVME_NS_DISC_F_BLKDEV:
350*533affcbSRobert Mustacchi nbd++;
351*533affcbSRobert Mustacchi /* FALLTHROUGH */
352*533affcbSRobert Mustacchi case NVME_NS_DISC_F_NOT_IGNORED:
353*533affcbSRobert Mustacchi nni++;
354*533affcbSRobert Mustacchi /* FALLTHROUGH */
355*533affcbSRobert Mustacchi case NVME_NS_DISC_F_ACTIVE:
356*533affcbSRobert Mustacchi nact++;
357*533affcbSRobert Mustacchi /* FALLTHROUGH */
358*533affcbSRobert Mustacchi case NVME_NS_DISC_F_ALLOCATED:
359*533affcbSRobert Mustacchi nalloc++;
360*533affcbSRobert Mustacchi /* FALLTHROUGH */
361*533affcbSRobert Mustacchi case NVME_NS_DISC_F_ALL:
362*533affcbSRobert Mustacchi nns++;
363*533affcbSRobert Mustacchi break;
364*533affcbSRobert Mustacchi }
365*533affcbSRobert Mustacchi }
366*533affcbSRobert Mustacchi
367*533affcbSRobert Mustacchi nvme_ns_discover_fini(iter);
368*533affcbSRobert Mustacchi if (iret != NVME_ITER_DONE) {
369*533affcbSRobert Mustacchi libnvme_test_ctrl_fatal(ctrl, "initial ns discovery failed");
370*533affcbSRobert Mustacchi }
371*533affcbSRobert Mustacchi
372*533affcbSRobert Mustacchi if (!nvme_ctrl_info_snap(ctrl, &info)) {
373*533affcbSRobert Mustacchi libnvme_test_ctrl_fatal(ctrl, "failed to get info snapshot");
374*533affcbSRobert Mustacchi }
375*533affcbSRobert Mustacchi
376*533affcbSRobert Mustacchi if (nns != nvme_ctrl_info_nns(info)) {
377*533affcbSRobert Mustacchi warnx("TEST FAILED: discovery found %u namespaces, but the "
378*533affcbSRobert Mustacchi "identify controller suggests there are %u", nns,
379*533affcbSRobert Mustacchi nvme_ctrl_info_nns(info));
380*533affcbSRobert Mustacchi }
381*533affcbSRobert Mustacchi
382*533affcbSRobert Mustacchi if (!ns_disc_count(ctrl, NVME_NS_DISC_F_BLKDEV, nbd)) {
383*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
384*533affcbSRobert Mustacchi }
385*533affcbSRobert Mustacchi
386*533affcbSRobert Mustacchi if (!ns_disc_count(ctrl, NVME_NS_DISC_F_NOT_IGNORED, nni)) {
387*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
388*533affcbSRobert Mustacchi }
389*533affcbSRobert Mustacchi
390*533affcbSRobert Mustacchi if (!ns_disc_count(ctrl, NVME_NS_DISC_F_ACTIVE, nact)) {
391*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
392*533affcbSRobert Mustacchi }
393*533affcbSRobert Mustacchi
394*533affcbSRobert Mustacchi if (!ns_disc_count(ctrl, NVME_NS_DISC_F_ALLOCATED, nalloc)) {
395*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
396*533affcbSRobert Mustacchi }
397*533affcbSRobert Mustacchi
398*533affcbSRobert Mustacchi if (!ns_disc_count(ctrl, NVME_NS_DISC_F_ALL, nns)) {
399*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
400*533affcbSRobert Mustacchi }
401*533affcbSRobert Mustacchi
402*533affcbSRobert Mustacchi /*
403*533affcbSRobert Mustacchi * For anything that has a blkdev address, ensure that our info snapshot
404*533affcbSRobert Mustacchi * has a valid blkdev address.
405*533affcbSRobert Mustacchi */
406*533affcbSRobert Mustacchi if (!nvme_ns_discover(ctrl, NVME_NS_DISC_F_BLKDEV, ns_disc_blkdev_cb,
407*533affcbSRobert Mustacchi &ret)) {
408*533affcbSRobert Mustacchi libnvme_test_ctrl_warn(ctrl, "discovery failed for blkdev "
409*533affcbSRobert Mustacchi "test");
410*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
411*533affcbSRobert Mustacchi }
412*533affcbSRobert Mustacchi
413*533affcbSRobert Mustacchi /*
414*533affcbSRobert Mustacchi * For anything active, check if there are guids and that the
415*533affcbSRobert Mustacchi * information snapshot matches the same logic.
416*533affcbSRobert Mustacchi */
417*533affcbSRobert Mustacchi if (!nvme_ns_discover(ctrl, NVME_NS_DISC_F_ACTIVE, ns_disc_guids_cb,
418*533affcbSRobert Mustacchi &ret)) {
419*533affcbSRobert Mustacchi libnvme_test_ctrl_warn(ctrl, "discovery failed for guids "
420*533affcbSRobert Mustacchi "test");
421*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
422*533affcbSRobert Mustacchi }
423*533affcbSRobert Mustacchi
424*533affcbSRobert Mustacchi /*
425*533affcbSRobert Mustacchi * For everything, make sure the levels match.
426*533affcbSRobert Mustacchi */
427*533affcbSRobert Mustacchi if (!nvme_ns_discover(ctrl, NVME_NS_DISC_F_ALL, ns_disc_level_cb,
428*533affcbSRobert Mustacchi &ret)) {
429*533affcbSRobert Mustacchi libnvme_test_ctrl_warn(ctrl, "discovery failed for levels "
430*533affcbSRobert Mustacchi "test");
431*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
432*533affcbSRobert Mustacchi }
433*533affcbSRobert Mustacchi
434*533affcbSRobert Mustacchi nvme_ctrl_unlock(ctrl);
435*533affcbSRobert Mustacchi
436*533affcbSRobert Mustacchi if (!ns_disc_bad_disc_init(ctrl, INT32_MAX, &iter, NVME_ERR_BAD_FLAG,
437*533affcbSRobert Mustacchi "invalid level")) {
438*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
439*533affcbSRobert Mustacchi }
440*533affcbSRobert Mustacchi
441*533affcbSRobert Mustacchi if (!ns_disc_bad_disc_init(ctrl, NVME_NS_DISC_F_ALL, NULL,
442*533affcbSRobert Mustacchi NVME_ERR_BAD_PTR, "invalid iter pointer")) {
443*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
444*533affcbSRobert Mustacchi }
445*533affcbSRobert Mustacchi
446*533affcbSRobert Mustacchi if (!ns_disc_bad_disc(ctrl, UINT32_MAX, ns_disc_nop_cb,
447*533affcbSRobert Mustacchi NVME_ERR_BAD_FLAG, "invalid level")) {
448*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
449*533affcbSRobert Mustacchi }
450*533affcbSRobert Mustacchi
451*533affcbSRobert Mustacchi if (!ns_disc_bad_disc(ctrl, NVME_NS_DISC_F_ALL, NULL,
452*533affcbSRobert Mustacchi NVME_ERR_BAD_PTR, "invalid function pointer")) {
453*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
454*533affcbSRobert Mustacchi }
455*533affcbSRobert Mustacchi
456*533affcbSRobert Mustacchi umem_setmtbf(1);
457*533affcbSRobert Mustacchi if (!ns_disc_bad_disc_init(ctrl, NVME_NS_DISC_F_ALL, &iter,
458*533affcbSRobert Mustacchi NVME_ERR_NO_MEM, "no memory")) {
459*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
460*533affcbSRobert Mustacchi }
461*533affcbSRobert Mustacchi
462*533affcbSRobert Mustacchi if (!ns_disc_bad_disc(ctrl, NVME_NS_DISC_F_ALL, ns_disc_nop_cb,
463*533affcbSRobert Mustacchi NVME_ERR_NO_MEM, "no memory")) {
464*533affcbSRobert Mustacchi ret = EXIT_FAILURE;
465*533affcbSRobert Mustacchi }
466*533affcbSRobert Mustacchi umem_setmtbf(0);
467*533affcbSRobert Mustacchi
468*533affcbSRobert Mustacchi if (ret == EXIT_SUCCESS) {
469*533affcbSRobert Mustacchi (void) printf("All tests passed successfully\n");
470*533affcbSRobert Mustacchi }
471*533affcbSRobert Mustacchi
472*533affcbSRobert Mustacchi nvme_ctrl_info_free(info);
473*533affcbSRobert Mustacchi nvme_ctrl_fini(ctrl);
474*533affcbSRobert Mustacchi nvme_fini(nvme);
475*533affcbSRobert Mustacchi return (ret);
476*533affcbSRobert Mustacchi }
477