xref: /illumos-gate/usr/src/test/nvme-tests/tests/libnvme/need-write-lock.c (revision f5f0964ce91892f7482efc86903b0ec7c7b6ba66)
1*f5f0964cSRobert Mustacchi /*
2*f5f0964cSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*f5f0964cSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*f5f0964cSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*f5f0964cSRobert Mustacchi  * 1.0 of the CDDL.
6*f5f0964cSRobert Mustacchi  *
7*f5f0964cSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*f5f0964cSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*f5f0964cSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*f5f0964cSRobert Mustacchi  */
11*f5f0964cSRobert Mustacchi 
12*f5f0964cSRobert Mustacchi /*
13*f5f0964cSRobert Mustacchi  * Copyright 2025 Oxide Computer Company
14*f5f0964cSRobert Mustacchi  */
15*f5f0964cSRobert Mustacchi 
16*f5f0964cSRobert Mustacchi /*
17*f5f0964cSRobert Mustacchi  * Various destructive options require a write lock. These include:
18*f5f0964cSRobert Mustacchi  *
19*f5f0964cSRobert Mustacchi  *  - namespace creation and deletion
20*f5f0964cSRobert Mustacchi  *  - attaching or detaching a controller to a namespace
21*f5f0964cSRobert Mustacchi  *  - manipulating blkdev state
22*f5f0964cSRobert Mustacchi  *  - formatting a namespace
23*f5f0964cSRobert Mustacchi  *
24*f5f0964cSRobert Mustacchi  * While firmware operations also require this, that is harder to test in this
25*f5f0964cSRobert Mustacchi  * case as we don't have valid firmware files or want to manipulate the device.
26*f5f0964cSRobert Mustacchi  * We check that operations fail in sevearl different situations:
27*f5f0964cSRobert Mustacchi  *
28*f5f0964cSRobert Mustacchi  * 1) With no locks held.
29*f5f0964cSRobert Mustacchi  * 2) With a namespace read lock.
30*f5f0964cSRobert Mustacchi  * 3) With a controller read lock.
31*f5f0964cSRobert Mustacchi  * 4) With a namespace write lock (note, some items succeed here).
32*f5f0964cSRobert Mustacchi  *
33*f5f0964cSRobert Mustacchi  * This test starts from the device-empty profile.
34*f5f0964cSRobert Mustacchi  */
35*f5f0964cSRobert Mustacchi 
36*f5f0964cSRobert Mustacchi #include <err.h>
37*f5f0964cSRobert Mustacchi #include <stdlib.h>
38*f5f0964cSRobert Mustacchi #include <sys/sysmacros.h>
39*f5f0964cSRobert Mustacchi #include "libnvme_test_common.h"
40*f5f0964cSRobert Mustacchi 
41*f5f0964cSRobert Mustacchi #define	LOCK_NSID	1
42*f5f0964cSRobert Mustacchi 
43*f5f0964cSRobert Mustacchi static uint32_t lock_lbaf;
44*f5f0964cSRobert Mustacchi 
45*f5f0964cSRobert Mustacchi typedef enum {
46*f5f0964cSRobert Mustacchi 	LOCK_NONE,
47*f5f0964cSRobert Mustacchi 	LOCK_NS_RD,
48*f5f0964cSRobert Mustacchi 	LOCK_NS_WR,
49*f5f0964cSRobert Mustacchi 	LOCK_CTRL_RD,
50*f5f0964cSRobert Mustacchi 	LOCK_MAX
51*f5f0964cSRobert Mustacchi } lock_type_t;
52*f5f0964cSRobert Mustacchi 
53*f5f0964cSRobert Mustacchi typedef struct write_test {
54*f5f0964cSRobert Mustacchi 	const char *wt_desc;
55*f5f0964cSRobert Mustacchi 	nvme_err_t wt_errs[LOCK_MAX];
56*f5f0964cSRobert Mustacchi 	nvme_ns_disc_level_t wt_disc;
57*f5f0964cSRobert Mustacchi 	bool (*wt_func)(nvme_ctrl_t *, const char *, nvme_err_t);
58*f5f0964cSRobert Mustacchi } write_test_t;
59*f5f0964cSRobert Mustacchi 
60*f5f0964cSRobert Mustacchi static bool
write_lock_ns_create(nvme_ctrl_t * ctrl,const char * desc,nvme_err_t exp)61*f5f0964cSRobert Mustacchi write_lock_ns_create(nvme_ctrl_t *ctrl, const char *desc, nvme_err_t exp)
62*f5f0964cSRobert Mustacchi {
63*f5f0964cSRobert Mustacchi 	uint64_t create_size = NVME_TEST_NS_SIZE / NVME_TEST_LBA_SIZE;
64*f5f0964cSRobert Mustacchi 	uint32_t nsid;
65*f5f0964cSRobert Mustacchi 	nvme_err_t act;
66*f5f0964cSRobert Mustacchi 
67*f5f0964cSRobert Mustacchi 	if (!libnvme_test_ns_create(ctrl, create_size, lock_lbaf, &nsid,
68*f5f0964cSRobert Mustacchi 	    &act)) {
69*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: failed to initialize namespace create"
70*f5f0964cSRobert Mustacchi 		    "request in lock %s iteration", desc);
71*f5f0964cSRobert Mustacchi 		return (false);
72*f5f0964cSRobert Mustacchi 	} else if (act != exp) {
73*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: namespace create with %s returned %s "
74*f5f0964cSRobert Mustacchi 		    "(0x%x), but expected %s (0x%x)", desc,
75*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, act), act,
76*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, exp), exp);
77*f5f0964cSRobert Mustacchi 		return (false);
78*f5f0964cSRobert Mustacchi 	}
79*f5f0964cSRobert Mustacchi 
80*f5f0964cSRobert Mustacchi 	(void) printf("TEST PASSED: namespace delete with %s returned %s\n",
81*f5f0964cSRobert Mustacchi 	    desc, nvme_ctrl_errtostr(ctrl, act));
82*f5f0964cSRobert Mustacchi 
83*f5f0964cSRobert Mustacchi 	return (true);
84*f5f0964cSRobert Mustacchi }
85*f5f0964cSRobert Mustacchi 
86*f5f0964cSRobert Mustacchi static bool
write_lock_ns_delete(nvme_ctrl_t * ctrl,const char * desc,nvme_err_t exp)87*f5f0964cSRobert Mustacchi write_lock_ns_delete(nvme_ctrl_t *ctrl, const char *desc, nvme_err_t exp)
88*f5f0964cSRobert Mustacchi {
89*f5f0964cSRobert Mustacchi 	nvme_err_t act;
90*f5f0964cSRobert Mustacchi 
91*f5f0964cSRobert Mustacchi 	if (!libnvme_test_ns_delete(ctrl, LOCK_NSID, &act)) {
92*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: failed to initialize namespace delete "
93*f5f0964cSRobert Mustacchi 		    "request in lock %s iteration", desc);
94*f5f0964cSRobert Mustacchi 		return (false);
95*f5f0964cSRobert Mustacchi 	} else if (act != exp) {
96*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: namespace delete with %s returned %s "
97*f5f0964cSRobert Mustacchi 		    "(0x%x), but expected %s (0x%x)", desc,
98*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, act), act,
99*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, exp), exp);
100*f5f0964cSRobert Mustacchi 		return (false);
101*f5f0964cSRobert Mustacchi 	}
102*f5f0964cSRobert Mustacchi 
103*f5f0964cSRobert Mustacchi 	(void) printf("TEST PASSED: namespace delete with %s returned %s\n",
104*f5f0964cSRobert Mustacchi 	    desc, nvme_ctrl_errtostr(ctrl, act));
105*f5f0964cSRobert Mustacchi 	return (true);
106*f5f0964cSRobert Mustacchi }
107*f5f0964cSRobert Mustacchi 
108*f5f0964cSRobert Mustacchi static bool
write_lock_ctrl_detach(nvme_ctrl_t * ctrl,const char * desc,nvme_err_t exp)109*f5f0964cSRobert Mustacchi write_lock_ctrl_detach(nvme_ctrl_t *ctrl, const char *desc, nvme_err_t exp)
110*f5f0964cSRobert Mustacchi {
111*f5f0964cSRobert Mustacchi 	nvme_err_t act;
112*f5f0964cSRobert Mustacchi 
113*f5f0964cSRobert Mustacchi 	if (!libnvme_test_ctrl_attach(ctrl, LOCK_NSID,
114*f5f0964cSRobert Mustacchi 	    NVME_NS_ATTACH_CTRL_DETACH, &act)) {
115*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: failed to initialize controller detach "
116*f5f0964cSRobert Mustacchi 		    "request in lock %s iteration", desc);
117*f5f0964cSRobert Mustacchi 		return (false);
118*f5f0964cSRobert Mustacchi 	} else if (act != exp) {
119*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: controller detach with %s returned %s "
120*f5f0964cSRobert Mustacchi 		    "(0x%x), but expected %s (0x%x)", desc,
121*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, act), act,
122*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, exp), exp);
123*f5f0964cSRobert Mustacchi 		return (false);
124*f5f0964cSRobert Mustacchi 	}
125*f5f0964cSRobert Mustacchi 
126*f5f0964cSRobert Mustacchi 	(void) printf("TEST PASSED: controller detach with %s returned %s\n",
127*f5f0964cSRobert Mustacchi 	    desc, nvme_ctrl_errtostr(ctrl, act));
128*f5f0964cSRobert Mustacchi 	return (true);
129*f5f0964cSRobert Mustacchi }
130*f5f0964cSRobert Mustacchi 
131*f5f0964cSRobert Mustacchi static bool
write_lock_ctrl_attach(nvme_ctrl_t * ctrl,const char * desc,nvme_err_t exp)132*f5f0964cSRobert Mustacchi write_lock_ctrl_attach(nvme_ctrl_t *ctrl, const char *desc, nvme_err_t exp)
133*f5f0964cSRobert Mustacchi {
134*f5f0964cSRobert Mustacchi 	nvme_err_t act;
135*f5f0964cSRobert Mustacchi 
136*f5f0964cSRobert Mustacchi 	if (!libnvme_test_ctrl_attach(ctrl, LOCK_NSID,
137*f5f0964cSRobert Mustacchi 	    NVME_NS_ATTACH_CTRL_ATTACH, &act)) {
138*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: failed to initialize controller attach "
139*f5f0964cSRobert Mustacchi 		    "request in lock %s iteration", desc);
140*f5f0964cSRobert Mustacchi 		return (false);
141*f5f0964cSRobert Mustacchi 	} else if (act != exp) {
142*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: controller attach with %s returned %s "
143*f5f0964cSRobert Mustacchi 		    "(0x%x), but expected %s (0x%x)", desc,
144*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, act), act,
145*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, exp), exp);
146*f5f0964cSRobert Mustacchi 		return (false);
147*f5f0964cSRobert Mustacchi 	}
148*f5f0964cSRobert Mustacchi 
149*f5f0964cSRobert Mustacchi 	(void) printf("TEST PASSED: controller attach with %s returned %s\n",
150*f5f0964cSRobert Mustacchi 	    desc, nvme_ctrl_errtostr(ctrl, act));
151*f5f0964cSRobert Mustacchi 	return (true);
152*f5f0964cSRobert Mustacchi }
153*f5f0964cSRobert Mustacchi 
154*f5f0964cSRobert Mustacchi static bool
write_lock_blkdev_detach(nvme_ctrl_t * ctrl,const char * desc,nvme_err_t exp)155*f5f0964cSRobert Mustacchi write_lock_blkdev_detach(nvme_ctrl_t *ctrl, const char *desc, nvme_err_t exp)
156*f5f0964cSRobert Mustacchi {
157*f5f0964cSRobert Mustacchi 	nvme_err_t act;
158*f5f0964cSRobert Mustacchi 
159*f5f0964cSRobert Mustacchi 	if (!libnvme_test_ns_blkdev(ctrl, LOCK_NSID, false, &act)) {
160*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: failed to initialize blkdev detach "
161*f5f0964cSRobert Mustacchi 		    "request in lock %s iteration", desc);
162*f5f0964cSRobert Mustacchi 		return (false);
163*f5f0964cSRobert Mustacchi 	} else if (act != exp) {
164*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: blkdev detach with %s returned %s (0x%x), "
165*f5f0964cSRobert Mustacchi 		    "but expected %s (0x%x)", desc,
166*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, act), act,
167*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, exp), exp);
168*f5f0964cSRobert Mustacchi 		return (false);
169*f5f0964cSRobert Mustacchi 	}
170*f5f0964cSRobert Mustacchi 
171*f5f0964cSRobert Mustacchi 	(void) printf("TEST PASSED: blkdev detach with %s returned %s\n", desc,
172*f5f0964cSRobert Mustacchi 	    nvme_ctrl_errtostr(ctrl, act));
173*f5f0964cSRobert Mustacchi 	return (true);
174*f5f0964cSRobert Mustacchi }
175*f5f0964cSRobert Mustacchi 
176*f5f0964cSRobert Mustacchi static bool
write_lock_blkdev_attach(nvme_ctrl_t * ctrl,const char * desc,nvme_err_t exp)177*f5f0964cSRobert Mustacchi write_lock_blkdev_attach(nvme_ctrl_t *ctrl, const char *desc, nvme_err_t exp)
178*f5f0964cSRobert Mustacchi {
179*f5f0964cSRobert Mustacchi 	nvme_err_t act;
180*f5f0964cSRobert Mustacchi 
181*f5f0964cSRobert Mustacchi 	if (!libnvme_test_ns_blkdev(ctrl, LOCK_NSID, true, &act)) {
182*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: failed to initialize blkdev attach "
183*f5f0964cSRobert Mustacchi 		    "request in lock %s iteration", desc);
184*f5f0964cSRobert Mustacchi 		return (false);
185*f5f0964cSRobert Mustacchi 	} else if (act != exp) {
186*f5f0964cSRobert Mustacchi 		warnx("TEST FAILED: blkdev attach with %s returned %s (0x%x), "
187*f5f0964cSRobert Mustacchi 		    "but expected %s (0x%x)", desc,
188*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, act), act,
189*f5f0964cSRobert Mustacchi 		    nvme_ctrl_errtostr(ctrl, exp), exp);
190*f5f0964cSRobert Mustacchi 		return (false);
191*f5f0964cSRobert Mustacchi 	}
192*f5f0964cSRobert Mustacchi 
193*f5f0964cSRobert Mustacchi 	(void) printf("TEST PASSED: blkdev attach with %s returned %s\n", desc,
194*f5f0964cSRobert Mustacchi 	    nvme_ctrl_errtostr(ctrl, act));
195*f5f0964cSRobert Mustacchi 	return (true);
196*f5f0964cSRobert Mustacchi }
197*f5f0964cSRobert Mustacchi 
198*f5f0964cSRobert Mustacchi static const write_test_t write_tests[] = { {
199*f5f0964cSRobert Mustacchi 	.wt_desc = "namespace create",
200*f5f0964cSRobert Mustacchi 	.wt_errs = {
201*f5f0964cSRobert Mustacchi 		[LOCK_NONE] = NVME_ERR_NEED_CTRL_WRLOCK,
202*f5f0964cSRobert Mustacchi 		[LOCK_NS_RD] = NVME_ERR_NEED_CTRL_WRLOCK,
203*f5f0964cSRobert Mustacchi 		[LOCK_NS_WR] = NVME_ERR_NEED_CTRL_WRLOCK,
204*f5f0964cSRobert Mustacchi 		[LOCK_CTRL_RD] = NVME_ERR_NEED_CTRL_WRLOCK
205*f5f0964cSRobert Mustacchi 	},
206*f5f0964cSRobert Mustacchi 	.wt_disc = NVME_NS_DISC_F_ALL,
207*f5f0964cSRobert Mustacchi 	.wt_func = write_lock_ns_create
208*f5f0964cSRobert Mustacchi }, {
209*f5f0964cSRobert Mustacchi 	.wt_desc = "namespace delete",
210*f5f0964cSRobert Mustacchi 	.wt_errs = {
211*f5f0964cSRobert Mustacchi 		[LOCK_NONE] = NVME_ERR_NEED_NS_WRLOCK,
212*f5f0964cSRobert Mustacchi 		[LOCK_NS_RD] = NVME_ERR_NEED_NS_WRLOCK,
213*f5f0964cSRobert Mustacchi 		[LOCK_NS_WR] = NVME_ERR_OK,
214*f5f0964cSRobert Mustacchi 		[LOCK_CTRL_RD] = NVME_ERR_NEED_NS_WRLOCK
215*f5f0964cSRobert Mustacchi 	},
216*f5f0964cSRobert Mustacchi 	.wt_disc = NVME_NS_DISC_F_ALLOCATED,
217*f5f0964cSRobert Mustacchi 	.wt_func = write_lock_ns_delete
218*f5f0964cSRobert Mustacchi }, {
219*f5f0964cSRobert Mustacchi 	.wt_desc = "controller attach",
220*f5f0964cSRobert Mustacchi 	.wt_errs = {
221*f5f0964cSRobert Mustacchi 		[LOCK_NONE] = NVME_ERR_NEED_NS_WRLOCK,
222*f5f0964cSRobert Mustacchi 		[LOCK_NS_RD] = NVME_ERR_NEED_NS_WRLOCK,
223*f5f0964cSRobert Mustacchi 		[LOCK_NS_WR] = NVME_ERR_OK,
224*f5f0964cSRobert Mustacchi 		[LOCK_CTRL_RD] = NVME_ERR_NEED_NS_WRLOCK
225*f5f0964cSRobert Mustacchi 	},
226*f5f0964cSRobert Mustacchi 	.wt_disc = NVME_NS_DISC_F_ALLOCATED,
227*f5f0964cSRobert Mustacchi 	.wt_func = write_lock_ctrl_attach
228*f5f0964cSRobert Mustacchi }, {
229*f5f0964cSRobert Mustacchi 	.wt_desc = "controller detach",
230*f5f0964cSRobert Mustacchi 	.wt_errs = {
231*f5f0964cSRobert Mustacchi 		[LOCK_NONE] = NVME_ERR_NEED_NS_WRLOCK,
232*f5f0964cSRobert Mustacchi 		[LOCK_NS_RD] = NVME_ERR_NEED_NS_WRLOCK,
233*f5f0964cSRobert Mustacchi 		[LOCK_NS_WR] = NVME_ERR_OK,
234*f5f0964cSRobert Mustacchi 		[LOCK_CTRL_RD] = NVME_ERR_NEED_NS_WRLOCK
235*f5f0964cSRobert Mustacchi 	},
236*f5f0964cSRobert Mustacchi 	.wt_disc = NVME_NS_DISC_F_ACTIVE,
237*f5f0964cSRobert Mustacchi 	.wt_func = write_lock_ctrl_detach
238*f5f0964cSRobert Mustacchi }, {
239*f5f0964cSRobert Mustacchi 	.wt_desc = "blkdev attach",
240*f5f0964cSRobert Mustacchi 	.wt_errs = {
241*f5f0964cSRobert Mustacchi 		[LOCK_NONE] = NVME_ERR_NEED_NS_WRLOCK,
242*f5f0964cSRobert Mustacchi 		[LOCK_NS_RD] = NVME_ERR_NEED_NS_WRLOCK,
243*f5f0964cSRobert Mustacchi 		[LOCK_NS_WR] = NVME_ERR_OK,
244*f5f0964cSRobert Mustacchi 		[LOCK_CTRL_RD] = NVME_ERR_NEED_NS_WRLOCK
245*f5f0964cSRobert Mustacchi 	},
246*f5f0964cSRobert Mustacchi 	.wt_disc = NVME_NS_DISC_F_NOT_IGNORED,
247*f5f0964cSRobert Mustacchi 	.wt_func = write_lock_blkdev_attach
248*f5f0964cSRobert Mustacchi }, {
249*f5f0964cSRobert Mustacchi 	.wt_desc = "blkdev detach",
250*f5f0964cSRobert Mustacchi 	.wt_errs = {
251*f5f0964cSRobert Mustacchi 		[LOCK_NONE] = NVME_ERR_NEED_NS_WRLOCK,
252*f5f0964cSRobert Mustacchi 		[LOCK_NS_RD] = NVME_ERR_NEED_NS_WRLOCK,
253*f5f0964cSRobert Mustacchi 		[LOCK_NS_WR] = NVME_ERR_OK,
254*f5f0964cSRobert Mustacchi 		[LOCK_CTRL_RD] = NVME_ERR_NEED_NS_WRLOCK
255*f5f0964cSRobert Mustacchi 	},
256*f5f0964cSRobert Mustacchi 	.wt_disc = NVME_NS_DISC_F_BLKDEV,
257*f5f0964cSRobert Mustacchi 	.wt_func = write_lock_blkdev_detach
258*f5f0964cSRobert Mustacchi } };
259*f5f0964cSRobert Mustacchi 
260*f5f0964cSRobert Mustacchi typedef struct lock_info {
261*f5f0964cSRobert Mustacchi 	const char *li_desc;
262*f5f0964cSRobert Mustacchi 	bool (*li_lock_f)(nvme_ctrl_t *, nvme_ns_t *);
263*f5f0964cSRobert Mustacchi 	void (*li_unlock_f)(nvme_ctrl_t *, nvme_ns_t *);
264*f5f0964cSRobert Mustacchi } lock_info_t;
265*f5f0964cSRobert Mustacchi 
266*f5f0964cSRobert Mustacchi static bool
lock_none_lock(nvme_ctrl_t * ctrl,nvme_ns_t * ns)267*f5f0964cSRobert Mustacchi lock_none_lock(nvme_ctrl_t *ctrl, nvme_ns_t *ns)
268*f5f0964cSRobert Mustacchi {
269*f5f0964cSRobert Mustacchi 	return (true);
270*f5f0964cSRobert Mustacchi }
271*f5f0964cSRobert Mustacchi 
272*f5f0964cSRobert Mustacchi static bool
lock_ns_read_lock(nvme_ctrl_t * ctrl,nvme_ns_t * ns)273*f5f0964cSRobert Mustacchi lock_ns_read_lock(nvme_ctrl_t *ctrl, nvme_ns_t *ns)
274*f5f0964cSRobert Mustacchi {
275*f5f0964cSRobert Mustacchi 	return (nvme_ns_lock(ns, NVME_LOCK_L_READ, NVME_LOCK_F_DONT_BLOCK));
276*f5f0964cSRobert Mustacchi }
277*f5f0964cSRobert Mustacchi 
278*f5f0964cSRobert Mustacchi static bool
lock_ns_write_lock(nvme_ctrl_t * ctrl,nvme_ns_t * ns)279*f5f0964cSRobert Mustacchi lock_ns_write_lock(nvme_ctrl_t *ctrl, nvme_ns_t *ns)
280*f5f0964cSRobert Mustacchi {
281*f5f0964cSRobert Mustacchi 	return (nvme_ns_lock(ns, NVME_LOCK_L_WRITE, NVME_LOCK_F_DONT_BLOCK));
282*f5f0964cSRobert Mustacchi }
283*f5f0964cSRobert Mustacchi 
284*f5f0964cSRobert Mustacchi static bool
lock_ctrl_read_lock(nvme_ctrl_t * ctrl,nvme_ns_t * ns)285*f5f0964cSRobert Mustacchi lock_ctrl_read_lock(nvme_ctrl_t *ctrl, nvme_ns_t *ns)
286*f5f0964cSRobert Mustacchi {
287*f5f0964cSRobert Mustacchi 	return (nvme_ctrl_lock(ctrl, NVME_LOCK_L_READ, NVME_LOCK_F_DONT_BLOCK));
288*f5f0964cSRobert Mustacchi }
289*f5f0964cSRobert Mustacchi 
290*f5f0964cSRobert Mustacchi static void
lock_none_unlock(nvme_ctrl_t * ctrl,nvme_ns_t * ns)291*f5f0964cSRobert Mustacchi lock_none_unlock(nvme_ctrl_t *ctrl, nvme_ns_t *ns)
292*f5f0964cSRobert Mustacchi {
293*f5f0964cSRobert Mustacchi }
294*f5f0964cSRobert Mustacchi 
295*f5f0964cSRobert Mustacchi static void
lock_ns_unlock(nvme_ctrl_t * ctrl,nvme_ns_t * ns)296*f5f0964cSRobert Mustacchi lock_ns_unlock(nvme_ctrl_t *ctrl, nvme_ns_t *ns)
297*f5f0964cSRobert Mustacchi {
298*f5f0964cSRobert Mustacchi 	nvme_ns_unlock(ns);
299*f5f0964cSRobert Mustacchi }
300*f5f0964cSRobert Mustacchi 
301*f5f0964cSRobert Mustacchi static void
lock_ctrl_unlock(nvme_ctrl_t * ctrl,nvme_ns_t * ns)302*f5f0964cSRobert Mustacchi lock_ctrl_unlock(nvme_ctrl_t *ctrl, nvme_ns_t *ns)
303*f5f0964cSRobert Mustacchi {
304*f5f0964cSRobert Mustacchi 	nvme_ctrl_unlock(ctrl);
305*f5f0964cSRobert Mustacchi }
306*f5f0964cSRobert Mustacchi 
307*f5f0964cSRobert Mustacchi lock_info_t lock_info[LOCK_MAX] = {
308*f5f0964cSRobert Mustacchi 	[LOCK_NONE] = {
309*f5f0964cSRobert Mustacchi 		.li_desc = "no lock",
310*f5f0964cSRobert Mustacchi 		.li_lock_f = lock_none_lock,
311*f5f0964cSRobert Mustacchi 		.li_unlock_f = lock_none_unlock,
312*f5f0964cSRobert Mustacchi 	},
313*f5f0964cSRobert Mustacchi 	[LOCK_NS_RD] = {
314*f5f0964cSRobert Mustacchi 		.li_desc = "namespace read lock",
315*f5f0964cSRobert Mustacchi 		.li_lock_f = lock_ns_read_lock,
316*f5f0964cSRobert Mustacchi 		.li_unlock_f = lock_ns_unlock,
317*f5f0964cSRobert Mustacchi 	},
318*f5f0964cSRobert Mustacchi 	[LOCK_NS_WR] = {
319*f5f0964cSRobert Mustacchi 		.li_desc = "namespace write lock",
320*f5f0964cSRobert Mustacchi 		.li_lock_f = lock_ns_write_lock,
321*f5f0964cSRobert Mustacchi 		.li_unlock_f = lock_ns_unlock,
322*f5f0964cSRobert Mustacchi 	},
323*f5f0964cSRobert Mustacchi 	[LOCK_CTRL_RD] = {
324*f5f0964cSRobert Mustacchi 		.li_desc = "controller read lock",
325*f5f0964cSRobert Mustacchi 		.li_lock_f = lock_ctrl_read_lock,
326*f5f0964cSRobert Mustacchi 		.li_unlock_f = lock_ctrl_unlock,
327*f5f0964cSRobert Mustacchi 	}
328*f5f0964cSRobert Mustacchi 
329*f5f0964cSRobert Mustacchi };
330*f5f0964cSRobert Mustacchi 
331*f5f0964cSRobert Mustacchi static bool
write_test_one(const write_test_t * test,nvme_ctrl_t * ctrl,nvme_ns_t * ns)332*f5f0964cSRobert Mustacchi write_test_one(const write_test_t *test, nvme_ctrl_t *ctrl, nvme_ns_t *ns)
333*f5f0964cSRobert Mustacchi {
334*f5f0964cSRobert Mustacchi 	bool ret = true;
335*f5f0964cSRobert Mustacchi 
336*f5f0964cSRobert Mustacchi 	for (lock_type_t i = LOCK_NONE; i < LOCK_MAX; i++) {
337*f5f0964cSRobert Mustacchi 		if (!nvme_ctrl_lock(ctrl, NVME_LOCK_L_WRITE,
338*f5f0964cSRobert Mustacchi 		    NVME_LOCK_F_DONT_BLOCK)) {
339*f5f0964cSRobert Mustacchi 			libnvme_test_ctrl_fatal(ctrl, "failed to obtain write "
340*f5f0964cSRobert Mustacchi 			    "lock");
341*f5f0964cSRobert Mustacchi 		}
342*f5f0964cSRobert Mustacchi 
343*f5f0964cSRobert Mustacchi 		if (!libnvme_test_setup_ns(ctrl, test->wt_disc, LOCK_NSID,
344*f5f0964cSRobert Mustacchi 		    lock_lbaf)) {
345*f5f0964cSRobert Mustacchi 			libnvme_test_ctrl_fatal(ctrl, "failed to change state "
346*f5f0964cSRobert Mustacchi 			    "to 0x%x", test->wt_disc);
347*f5f0964cSRobert Mustacchi 		}
348*f5f0964cSRobert Mustacchi 
349*f5f0964cSRobert Mustacchi 		nvme_ctrl_unlock(ctrl);
350*f5f0964cSRobert Mustacchi 
351*f5f0964cSRobert Mustacchi 		if (!lock_info[i].li_lock_f(ctrl, ns)) {
352*f5f0964cSRobert Mustacchi 			ret = false;
353*f5f0964cSRobert Mustacchi 			continue;
354*f5f0964cSRobert Mustacchi 		}
355*f5f0964cSRobert Mustacchi 
356*f5f0964cSRobert Mustacchi 		if (!test->wt_func(ctrl, lock_info[i].li_desc,
357*f5f0964cSRobert Mustacchi 		    test->wt_errs[i])) {
358*f5f0964cSRobert Mustacchi 			ret = false;
359*f5f0964cSRobert Mustacchi 		}
360*f5f0964cSRobert Mustacchi 
361*f5f0964cSRobert Mustacchi 		lock_info[i].li_unlock_f(ctrl, ns);
362*f5f0964cSRobert Mustacchi 	}
363*f5f0964cSRobert Mustacchi 
364*f5f0964cSRobert Mustacchi 	return (ret);
365*f5f0964cSRobert Mustacchi }
366*f5f0964cSRobert Mustacchi 
367*f5f0964cSRobert Mustacchi int
main(void)368*f5f0964cSRobert Mustacchi main(void)
369*f5f0964cSRobert Mustacchi {
370*f5f0964cSRobert Mustacchi 	int ret = EXIT_SUCCESS;
371*f5f0964cSRobert Mustacchi 	nvme_t *nvme;
372*f5f0964cSRobert Mustacchi 	nvme_ctrl_t *ctrl;
373*f5f0964cSRobert Mustacchi 	nvme_ctrl_info_t *info;
374*f5f0964cSRobert Mustacchi 	nvme_ns_t *ns;
375*f5f0964cSRobert Mustacchi 
376*f5f0964cSRobert Mustacchi 	libnvme_test_init(&nvme, &ctrl);
377*f5f0964cSRobert Mustacchi 
378*f5f0964cSRobert Mustacchi 	if (!nvme_ctrl_info_snap(ctrl, &info)) {
379*f5f0964cSRobert Mustacchi 		libnvme_test_ctrl_fatal(ctrl, "failed to get info snapshot");
380*f5f0964cSRobert Mustacchi 	}
381*f5f0964cSRobert Mustacchi 
382*f5f0964cSRobert Mustacchi 	if (!nvme_ns_init(ctrl, LOCK_NSID, &ns)) {
383*f5f0964cSRobert Mustacchi 		libnvme_test_ctrl_fatal(ctrl, "failed to create ns %u "
384*f5f0964cSRobert Mustacchi 		    "nvme_ns_t", LOCK_NSID);
385*f5f0964cSRobert Mustacchi 	}
386*f5f0964cSRobert Mustacchi 
387*f5f0964cSRobert Mustacchi 	if (!libnvme_test_lbaf(info, NVME_TEST_LBA_SIZE, &lock_lbaf)) {
388*f5f0964cSRobert Mustacchi 		errx(EXIT_FAILURE, "failed to find 4K LBA format, cannot "
389*f5f0964cSRobert Mustacchi 		    "continue");
390*f5f0964cSRobert Mustacchi 	}
391*f5f0964cSRobert Mustacchi 
392*f5f0964cSRobert Mustacchi 	for (size_t i = 0; i < ARRAY_SIZE(write_tests); i++) {
393*f5f0964cSRobert Mustacchi 		if (!write_test_one(&write_tests[i], ctrl, ns))
394*f5f0964cSRobert Mustacchi 			ret = EXIT_FAILURE;
395*f5f0964cSRobert Mustacchi 	}
396*f5f0964cSRobert Mustacchi 
397*f5f0964cSRobert Mustacchi 	nvme_ns_fini(ns);
398*f5f0964cSRobert Mustacchi 	nvme_ctrl_info_free(info);
399*f5f0964cSRobert Mustacchi 	nvme_ctrl_fini(ctrl);
400*f5f0964cSRobert Mustacchi 	nvme_fini(nvme);
401*f5f0964cSRobert Mustacchi 
402*f5f0964cSRobert Mustacchi 	if (ret == EXIT_SUCCESS) {
403*f5f0964cSRobert Mustacchi 		(void) printf("All tests passed successfully\n");
404*f5f0964cSRobert Mustacchi 	}
405*f5f0964cSRobert Mustacchi 
406*f5f0964cSRobert Mustacchi 	return (ret);
407*f5f0964cSRobert Mustacchi }
408