xref: /spdk/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c (revision 7a85c283d995a1e960bd35f37a9fb478431cfb1f)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation. All rights reserved.
5  *   Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "common/lib/ut_multithread.c"
37 #include "spdk_cunit.h"
38 #include "spdk_internal/mock.h"
39 #include "spdk_internal/thread.h"
40 
41 #include "nvmf/subsystem.c"
42 
43 SPDK_LOG_REGISTER_COMPONENT(nvmf)
44 
45 DEFINE_STUB(spdk_bdev_module_claim_bdev,
46 	    int,
47 	    (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
48 	     struct spdk_bdev_module *module), 0);
49 
50 DEFINE_STUB_V(spdk_bdev_module_release_bdev,
51 	      (struct spdk_bdev *bdev));
52 
53 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
54 	    (const struct spdk_bdev *bdev), 512);
55 
56 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
57 	    (const struct spdk_bdev *bdev), 0);
58 
59 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
60 	    (const struct spdk_bdev *bdev), false);
61 
62 DEFINE_STUB(spdk_nvmf_transport_stop_listen,
63 	    int,
64 	    (struct spdk_nvmf_transport *transport,
65 	     const struct spdk_nvme_transport_id *trid), 0);
66 
67 int
68 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
69 			   const struct spdk_nvme_transport_id *trid)
70 {
71 	return 0;
72 }
73 
74 void
75 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
76 				 struct spdk_nvme_transport_id *trid,
77 				 struct spdk_nvmf_discovery_log_page_entry *entry)
78 {
79 	entry->trtype = 42;
80 }
81 
82 static struct spdk_nvmf_transport g_transport = {};
83 
84 struct spdk_nvmf_transport *
85 spdk_nvmf_transport_create(const char *transport_name,
86 			   struct spdk_nvmf_transport_opts *tprt_opts)
87 {
88 	if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) {
89 		return &g_transport;
90 	}
91 
92 	return NULL;
93 }
94 
95 struct spdk_nvmf_subsystem *
96 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
97 {
98 	return NULL;
99 }
100 
101 struct spdk_nvmf_transport *
102 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
103 {
104 	if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) {
105 		return &g_transport;
106 	}
107 
108 	return NULL;
109 }
110 
111 int
112 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
113 				 struct spdk_nvmf_subsystem *subsystem)
114 {
115 	return 0;
116 }
117 
118 int
119 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
120 			      struct spdk_nvmf_subsystem *subsystem,
121 			      spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
122 {
123 	return 0;
124 }
125 
126 void
127 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group,
128 				 struct spdk_nvmf_subsystem *subsystem,
129 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
130 {
131 }
132 
133 void
134 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
135 				struct spdk_nvmf_subsystem *subsystem,
136 				spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
137 {
138 }
139 
140 void
141 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
142 				 struct spdk_nvmf_subsystem *subsystem,
143 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
144 {
145 }
146 
147 int
148 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
149 {
150 	if (trtype == NULL || str == NULL) {
151 		return -EINVAL;
152 	}
153 
154 	if (strcasecmp(str, "PCIe") == 0) {
155 		*trtype = SPDK_NVME_TRANSPORT_PCIE;
156 	} else if (strcasecmp(str, "RDMA") == 0) {
157 		*trtype = SPDK_NVME_TRANSPORT_RDMA;
158 	} else {
159 		return -ENOENT;
160 	}
161 	return 0;
162 }
163 
164 int
165 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
166 			       const struct spdk_nvme_transport_id *trid2)
167 {
168 	return 0;
169 }
170 
171 int32_t
172 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr)
173 {
174 	return -1;
175 }
176 
177 int32_t
178 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
179 {
180 	return -1;
181 }
182 
183 int
184 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
185 {
186 	return -1;
187 }
188 
189 void
190 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
191 {
192 }
193 
194 static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL;
195 static uint32_t g_ns_changed_nsid = 0;
196 void
197 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
198 {
199 	g_ns_changed_ctrlr = ctrlr;
200 	g_ns_changed_nsid = nsid;
201 }
202 
203 static struct spdk_bdev g_bdevs[] = {
204 	{ .name = "bdev1" },
205 	{ .name = "bdev2" },
206 };
207 
208 struct spdk_bdev_desc {
209 	struct spdk_bdev	*bdev;
210 };
211 
212 int
213 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
214 		   void *event_ctx, struct spdk_bdev_desc **_desc)
215 {
216 	struct spdk_bdev_desc *desc;
217 	size_t i;
218 
219 	for (i = 0; i < sizeof(g_bdevs); i++) {
220 		if (strcmp(bdev_name, g_bdevs[i].name) == 0) {
221 
222 			desc = calloc(1, sizeof(*desc));
223 			SPDK_CU_ASSERT_FATAL(desc != NULL);
224 
225 			desc->bdev = &g_bdevs[i];
226 			*_desc = desc;
227 			return 0;
228 		}
229 	}
230 
231 	return -EINVAL;
232 }
233 
234 void
235 spdk_bdev_close(struct spdk_bdev_desc *desc)
236 {
237 	free(desc);
238 }
239 
240 struct spdk_bdev *
241 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
242 {
243 	return desc->bdev;
244 }
245 
246 const char *
247 spdk_bdev_get_name(const struct spdk_bdev *bdev)
248 {
249 	return "test";
250 }
251 
252 const struct spdk_uuid *
253 spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
254 {
255 	return &bdev->uuid;
256 }
257 
258 static void
259 test_spdk_nvmf_subsystem_add_ns(void)
260 {
261 	struct spdk_nvmf_tgt tgt = {};
262 	struct spdk_nvmf_subsystem subsystem = {
263 		.max_nsid = 0,
264 		.ns = NULL,
265 		.tgt = &tgt
266 	};
267 	struct spdk_nvmf_ns_opts ns_opts;
268 	uint32_t nsid;
269 	int rc;
270 
271 	tgt.max_subsystems = 1024;
272 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
273 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
274 
275 	/* Allow NSID to be assigned automatically */
276 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
277 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev1", &ns_opts, sizeof(ns_opts), NULL);
278 	/* NSID 1 is the first unused ID */
279 	CU_ASSERT(nsid == 1);
280 	CU_ASSERT(subsystem.max_nsid == 1);
281 	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
282 	SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
283 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[nsid - 1]);
284 
285 	/* Request a specific NSID */
286 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
287 	ns_opts.nsid = 5;
288 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
289 	CU_ASSERT(nsid == 5);
290 	CU_ASSERT(subsystem.max_nsid == 5);
291 	SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
292 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[1]);
293 
294 	/* Request an NSID that is already in use */
295 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
296 	ns_opts.nsid = 5;
297 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
298 	CU_ASSERT(nsid == 0);
299 	CU_ASSERT(subsystem.max_nsid == 5);
300 
301 	/* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */
302 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
303 	ns_opts.nsid = 0xFFFFFFFF;
304 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
305 	CU_ASSERT(nsid == 0);
306 	CU_ASSERT(subsystem.max_nsid == 5);
307 
308 	rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 1);
309 	CU_ASSERT(rc == 0);
310 	rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5);
311 	CU_ASSERT(rc == 0);
312 
313 	free(subsystem.ns);
314 	free(tgt.subsystems);
315 }
316 
317 static void
318 nvmf_test_create_subsystem(void)
319 {
320 	struct spdk_nvmf_tgt tgt = {};
321 	char nqn[256];
322 	struct spdk_nvmf_subsystem *subsystem;
323 
324 	tgt.max_subsystems = 1024;
325 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
326 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
327 
328 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
329 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
330 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
331 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
332 	spdk_nvmf_subsystem_destroy(subsystem);
333 
334 	/* valid name with complex reverse domain */
335 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1");
336 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
337 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
338 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
339 	spdk_nvmf_subsystem_destroy(subsystem);
340 
341 	/* Valid name discovery controller */
342 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
343 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
344 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
345 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
346 	spdk_nvmf_subsystem_destroy(subsystem);
347 
348 
349 	/* Invalid name, no user supplied string */
350 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
351 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
352 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
353 
354 	/* Valid name, only contains top-level domain name */
355 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
356 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
357 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
358 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
359 	spdk_nvmf_subsystem_destroy(subsystem);
360 
361 	/* Invalid name, domain label > 63 characters */
362 	snprintf(nqn, sizeof(nqn),
363 		 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub");
364 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
365 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
366 
367 	/* Invalid name, domain label starts with digit */
368 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub");
369 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
370 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
371 
372 	/* Invalid name, domain label starts with - */
373 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1");
374 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
375 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
376 
377 	/* Invalid name, domain label ends with - */
378 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1");
379 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
380 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
381 
382 	/* Invalid name, domain label with multiple consecutive periods */
383 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1");
384 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
385 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
386 
387 	/* Longest valid name */
388 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
389 	memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn));
390 	nqn[223] = '\0';
391 	CU_ASSERT(strlen(nqn) == 223);
392 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
393 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
394 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
395 	spdk_nvmf_subsystem_destroy(subsystem);
396 
397 	/* Invalid name, too long */
398 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
399 	memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn));
400 	nqn[224] = '\0';
401 	CU_ASSERT(strlen(nqn) == 224);
402 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
403 	CU_ASSERT(subsystem == NULL);
404 
405 	/* Valid name using uuid format */
406 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc");
407 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
408 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
409 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
410 	spdk_nvmf_subsystem_destroy(subsystem);
411 
412 	/* Invalid name user string contains an invalid utf-8 character */
413 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1");
414 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
415 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
416 
417 	/* Valid name with non-ascii but valid utf-8 characters */
418 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80");
419 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
420 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
421 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
422 	spdk_nvmf_subsystem_destroy(subsystem);
423 
424 	/* Invalid uuid (too long) */
425 	snprintf(nqn, sizeof(nqn),
426 		 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef");
427 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
428 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
429 
430 	/* Invalid uuid (dashes placed incorrectly) */
431 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc");
432 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
433 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
434 
435 	/* Invalid uuid (invalid characters in uuid) */
436 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc");
437 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
438 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
439 
440 	free(tgt.subsystems);
441 }
442 
443 static void
444 test_spdk_nvmf_subsystem_set_sn(void)
445 {
446 	struct spdk_nvmf_subsystem subsystem = {};
447 
448 	/* Basic valid serial number */
449 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0);
450 	CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0);
451 
452 	/* Exactly 20 characters (valid) */
453 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0);
454 	CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0);
455 
456 	/* 21 characters (too long, invalid) */
457 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0);
458 
459 	/* Non-ASCII characters (invalid) */
460 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0);
461 }
462 
463 /*
464  * Reservation Unit Test Configuration
465  *       --------             --------    --------
466  *      | Host A |           | Host B |  | Host C |
467  *       --------             --------    --------
468  *      /        \               |           |
469  *  --------   --------       -------     -------
470  * |Ctrlr1_A| |Ctrlr2_A|     |Ctrlr_B|   |Ctrlr_C|
471  *  --------   --------       -------     -------
472  *    \           \              /           /
473  *     \           \            /           /
474  *      \           \          /           /
475  *      --------------------------------------
476  *     |            NAMESPACE 1               |
477  *      --------------------------------------
478  */
479 static struct spdk_nvmf_subsystem g_subsystem;
480 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C;
481 static struct spdk_nvmf_ns g_ns;
482 static struct spdk_bdev g_bdev;
483 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info;
484 
485 void
486 nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr)
487 {
488 }
489 
490 static void
491 ut_reservation_init(void)
492 {
493 
494 	TAILQ_INIT(&g_subsystem.ctrlrs);
495 
496 	memset(&g_ns, 0, sizeof(g_ns));
497 	TAILQ_INIT(&g_ns.registrants);
498 	g_ns.subsystem = &g_subsystem;
499 	g_ns.ptpl_file = NULL;
500 	g_ns.ptpl_activated = false;
501 	spdk_uuid_generate(&g_bdev.uuid);
502 	g_ns.bdev = &g_bdev;
503 
504 	/* Host A has two controllers */
505 	spdk_uuid_generate(&g_ctrlr1_A.hostid);
506 	TAILQ_INIT(&g_ctrlr1_A.log_head);
507 	g_ctrlr1_A.subsys = &g_subsystem;
508 	g_ctrlr1_A.num_avail_log_pages = 0;
509 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link);
510 	spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid);
511 	TAILQ_INIT(&g_ctrlr2_A.log_head);
512 	g_ctrlr2_A.subsys = &g_subsystem;
513 	g_ctrlr2_A.num_avail_log_pages = 0;
514 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link);
515 
516 	/* Host B has 1 controller */
517 	spdk_uuid_generate(&g_ctrlr_B.hostid);
518 	TAILQ_INIT(&g_ctrlr_B.log_head);
519 	g_ctrlr_B.subsys = &g_subsystem;
520 	g_ctrlr_B.num_avail_log_pages = 0;
521 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link);
522 
523 	/* Host C has 1 controller */
524 	spdk_uuid_generate(&g_ctrlr_C.hostid);
525 	TAILQ_INIT(&g_ctrlr_C.log_head);
526 	g_ctrlr_C.subsys = &g_subsystem;
527 	g_ctrlr_C.num_avail_log_pages = 0;
528 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link);
529 }
530 
531 static void
532 ut_reservation_deinit(void)
533 {
534 	struct spdk_nvmf_registrant *reg, *tmp;
535 	struct spdk_nvmf_reservation_log *log, *log_tmp;
536 	struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
537 
538 	TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) {
539 		TAILQ_REMOVE(&g_ns.registrants, reg, link);
540 		free(reg);
541 	}
542 	TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) {
543 		TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link);
544 		free(log);
545 	}
546 	g_ctrlr1_A.num_avail_log_pages = 0;
547 	TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) {
548 		TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link);
549 		free(log);
550 	}
551 	g_ctrlr2_A.num_avail_log_pages = 0;
552 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) {
553 		TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link);
554 		free(log);
555 	}
556 	g_ctrlr_B.num_avail_log_pages = 0;
557 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) {
558 		TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link);
559 		free(log);
560 	}
561 	g_ctrlr_C.num_avail_log_pages = 0;
562 
563 	TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) {
564 		TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link);
565 	}
566 }
567 
568 static struct spdk_nvmf_request *
569 ut_reservation_build_req(uint32_t length)
570 {
571 	struct spdk_nvmf_request *req;
572 
573 	req = calloc(1, sizeof(*req));
574 	assert(req != NULL);
575 
576 	req->data = calloc(1, length);
577 	assert(req->data != NULL);
578 	req->length = length;
579 
580 	req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg));
581 	assert(req->cmd != NULL);
582 
583 	req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg));
584 	assert(req->rsp != NULL);
585 
586 	return req;
587 }
588 
589 static void
590 ut_reservation_free_req(struct spdk_nvmf_request *req)
591 {
592 	free(req->cmd);
593 	free(req->rsp);
594 	free(req->data);
595 	free(req);
596 }
597 
598 static void
599 ut_reservation_build_register_request(struct spdk_nvmf_request *req,
600 				      uint8_t rrega, uint8_t iekey,
601 				      uint8_t cptpl, uint64_t crkey,
602 				      uint64_t nrkey)
603 {
604 	struct spdk_nvme_reservation_register_data key;
605 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
606 
607 	key.crkey = crkey;
608 	key.nrkey = nrkey;
609 	cmd->cdw10 = 0;
610 	cmd->cdw10_bits.resv_register.rrega = rrega;
611 	cmd->cdw10_bits.resv_register.iekey = iekey;
612 	cmd->cdw10_bits.resv_register.cptpl = cptpl;
613 	memcpy(req->data, &key, sizeof(key));
614 }
615 
616 static void
617 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req,
618 				     uint8_t racqa, uint8_t iekey,
619 				     uint8_t rtype, uint64_t crkey,
620 				     uint64_t prkey)
621 {
622 	struct spdk_nvme_reservation_acquire_data key;
623 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
624 
625 	key.crkey = crkey;
626 	key.prkey = prkey;
627 	cmd->cdw10 = 0;
628 	cmd->cdw10_bits.resv_acquire.racqa = racqa;
629 	cmd->cdw10_bits.resv_acquire.iekey = iekey;
630 	cmd->cdw10_bits.resv_acquire.rtype = rtype;
631 	memcpy(req->data, &key, sizeof(key));
632 }
633 
634 static void
635 ut_reservation_build_release_request(struct spdk_nvmf_request *req,
636 				     uint8_t rrela, uint8_t iekey,
637 				     uint8_t rtype, uint64_t crkey)
638 {
639 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
640 
641 	cmd->cdw10 = 0;
642 	cmd->cdw10_bits.resv_release.rrela = rrela;
643 	cmd->cdw10_bits.resv_release.iekey = iekey;
644 	cmd->cdw10_bits.resv_release.rtype = rtype;
645 	memcpy(req->data, &crkey, sizeof(crkey));
646 }
647 
648 /*
649  * Construct four registrants for other test cases.
650  *
651  * g_ctrlr1_A register with key 0xa1.
652  * g_ctrlr2_A register with key 0xa1.
653  * g_ctrlr_B register with key 0xb1.
654  * g_ctrlr_C register with key 0xc1.
655  * */
656 static void
657 ut_reservation_build_registrants(void)
658 {
659 	struct spdk_nvmf_request *req;
660 	struct spdk_nvme_cpl *rsp;
661 	struct spdk_nvmf_registrant *reg;
662 	uint32_t gen;
663 
664 	req = ut_reservation_build_req(16);
665 	rsp = &req->rsp->nvme_cpl;
666 	SPDK_CU_ASSERT_FATAL(req != NULL);
667 	gen = g_ns.gen;
668 
669 	/* TEST CASE: g_ctrlr1_A register with a new key */
670 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
671 					      0, 0, 0, 0xa1);
672 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
673 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
674 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
675 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
676 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1);
677 
678 	/* TEST CASE: g_ctrlr2_A register with a new key, because it has same
679 	 * Host Identifier with g_ctrlr1_A, so the register key should same.
680 	 */
681 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
682 					      0, 0, 0, 0xa2);
683 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req);
684 	/* Reservation conflict for other key than 0xa1 */
685 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT);
686 
687 	/* g_ctrlr_B register with a new key */
688 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
689 					      0, 0, 0, 0xb1);
690 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
691 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
692 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
693 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1);
694 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2);
695 
696 	/* g_ctrlr_C register with a new key */
697 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
698 					      0, 0, 0, 0xc1);
699 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
700 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
701 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
702 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1);
703 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3);
704 
705 	ut_reservation_free_req(req);
706 }
707 
708 static void
709 test_reservation_register(void)
710 {
711 	struct spdk_nvmf_request *req;
712 	struct spdk_nvme_cpl *rsp;
713 	struct spdk_nvmf_registrant *reg;
714 	uint32_t gen;
715 
716 	ut_reservation_init();
717 
718 	req = ut_reservation_build_req(16);
719 	rsp = &req->rsp->nvme_cpl;
720 	SPDK_CU_ASSERT_FATAL(req != NULL);
721 
722 	ut_reservation_build_registrants();
723 
724 	/* TEST CASE: Replace g_ctrlr1_A with a new key */
725 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
726 					      0, 0, 0xa1, 0xa11);
727 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
728 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
729 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
730 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11);
731 
732 	/* TEST CASE: Host A with g_ctrlr1_A get reservation with
733 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
734 	 */
735 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
736 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0);
737 	gen = g_ns.gen;
738 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
739 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
740 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
741 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
742 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11);
743 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
744 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
745 
746 	/* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
747 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
748 					      1, 0, 0, 0);
749 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
750 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
751 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
752 	SPDK_CU_ASSERT_FATAL(reg == NULL);
753 
754 	/* TEST CASE: g_ctrlr_B unregister with correct key */
755 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
756 					      0, 0, 0xb1, 0);
757 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
758 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
759 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
760 	SPDK_CU_ASSERT_FATAL(reg == NULL);
761 
762 	/* TEST CASE: g_ctrlr1_A unregister with correct key,
763 	 * reservation should be removed as well.
764 	 */
765 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
766 					      0, 0, 0xa11, 0);
767 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
768 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
769 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
770 	SPDK_CU_ASSERT_FATAL(reg == NULL);
771 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
772 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
773 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
774 
775 	ut_reservation_free_req(req);
776 	ut_reservation_deinit();
777 }
778 
779 static void
780 test_reservation_register_with_ptpl(void)
781 {
782 	struct spdk_nvmf_request *req;
783 	struct spdk_nvme_cpl *rsp;
784 	struct spdk_nvmf_registrant *reg;
785 	bool update_sgroup = false;
786 	int rc;
787 	struct spdk_nvmf_reservation_info info;
788 
789 	ut_reservation_init();
790 
791 	req = ut_reservation_build_req(16);
792 	rsp = &req->rsp->nvme_cpl;
793 	SPDK_CU_ASSERT_FATAL(req != NULL);
794 
795 	/* TEST CASE: No persistent file, register with PTPL enabled will fail */
796 	g_ns.ptpl_file = NULL;
797 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
798 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
799 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
800 	SPDK_CU_ASSERT_FATAL(update_sgroup == false);
801 	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
802 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
803 	SPDK_CU_ASSERT_FATAL(reg == NULL);
804 
805 	/* TEST CASE: Enable PTPL */
806 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
807 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
808 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
809 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
810 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
811 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
812 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
813 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
814 	SPDK_CU_ASSERT_FATAL(reg != NULL);
815 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
816 	/* Load reservation information from configuration file */
817 	memset(&info, 0, sizeof(info));
818 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
819 	SPDK_CU_ASSERT_FATAL(rc == 0);
820 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
821 
822 	/* TEST CASE: Disable PTPL */
823 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
824 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
825 					      SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1);
826 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
827 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
828 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
829 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false);
830 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
831 	SPDK_CU_ASSERT_FATAL(rc < 0);
832 	unlink(g_ns.ptpl_file);
833 
834 	ut_reservation_free_req(req);
835 	ut_reservation_deinit();
836 }
837 
838 static void
839 test_reservation_acquire_preempt_1(void)
840 {
841 	struct spdk_nvmf_request *req;
842 	struct spdk_nvme_cpl *rsp;
843 	struct spdk_nvmf_registrant *reg;
844 	uint32_t gen;
845 
846 	ut_reservation_init();
847 
848 	req = ut_reservation_build_req(16);
849 	rsp = &req->rsp->nvme_cpl;
850 	SPDK_CU_ASSERT_FATAL(req != NULL);
851 
852 	ut_reservation_build_registrants();
853 
854 	gen = g_ns.gen;
855 	/* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
856 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
857 	 */
858 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
859 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
860 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
861 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
862 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
863 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
864 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1);
865 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
866 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
867 
868 	/* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
869 	 * g_ctrl1_A registrant is unregistred.
870 	 */
871 	gen = g_ns.gen;
872 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
873 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1);
874 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
875 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
876 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
877 	SPDK_CU_ASSERT_FATAL(reg == NULL);
878 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
879 	SPDK_CU_ASSERT_FATAL(reg != NULL);
880 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
881 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
882 	SPDK_CU_ASSERT_FATAL(reg != NULL);
883 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
884 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
885 
886 	/* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B
887 	 * with valid key and PRKEY set to 0, all registrants other the host that issued
888 	 * the command are unregistered.
889 	 */
890 	gen = g_ns.gen;
891 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
892 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0);
893 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
894 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
895 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
896 	SPDK_CU_ASSERT_FATAL(reg == NULL);
897 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
898 	SPDK_CU_ASSERT_FATAL(reg == NULL);
899 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
900 	SPDK_CU_ASSERT_FATAL(reg != NULL);
901 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
902 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
903 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
904 
905 	ut_reservation_free_req(req);
906 	ut_reservation_deinit();
907 }
908 
909 static void
910 test_reservation_acquire_release_with_ptpl(void)
911 {
912 	struct spdk_nvmf_request *req;
913 	struct spdk_nvme_cpl *rsp;
914 	struct spdk_nvmf_registrant *reg;
915 	bool update_sgroup = false;
916 	struct spdk_uuid holder_uuid;
917 	int rc;
918 	struct spdk_nvmf_reservation_info info;
919 
920 	ut_reservation_init();
921 
922 	req = ut_reservation_build_req(16);
923 	rsp = &req->rsp->nvme_cpl;
924 	SPDK_CU_ASSERT_FATAL(req != NULL);
925 
926 	/* TEST CASE: Enable PTPL */
927 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
928 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
929 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
930 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
931 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
932 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
933 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
934 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
935 	SPDK_CU_ASSERT_FATAL(reg != NULL);
936 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
937 	/* Load reservation information from configuration file */
938 	memset(&info, 0, sizeof(info));
939 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
940 	SPDK_CU_ASSERT_FATAL(rc == 0);
941 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
942 
943 	/* TEST CASE: Acquire the reservation */
944 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
945 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
946 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
947 	update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
948 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
949 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
950 	memset(&info, 0, sizeof(info));
951 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
952 	SPDK_CU_ASSERT_FATAL(rc == 0);
953 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
954 	SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
955 	SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1);
956 	spdk_uuid_parse(&holder_uuid, info.holder_uuid);
957 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid));
958 
959 	/* TEST CASE: Release the reservation */
960 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
961 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
962 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1);
963 	update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req);
964 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
965 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
966 	memset(&info, 0, sizeof(info));
967 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
968 	SPDK_CU_ASSERT_FATAL(rc == 0);
969 	SPDK_CU_ASSERT_FATAL(info.rtype == 0);
970 	SPDK_CU_ASSERT_FATAL(info.crkey == 0);
971 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
972 	unlink(g_ns.ptpl_file);
973 
974 	ut_reservation_free_req(req);
975 	ut_reservation_deinit();
976 }
977 
978 static void
979 test_reservation_release(void)
980 {
981 	struct spdk_nvmf_request *req;
982 	struct spdk_nvme_cpl *rsp;
983 	struct spdk_nvmf_registrant *reg;
984 
985 	ut_reservation_init();
986 
987 	req = ut_reservation_build_req(16);
988 	rsp = &req->rsp->nvme_cpl;
989 	SPDK_CU_ASSERT_FATAL(req != NULL);
990 
991 	ut_reservation_build_registrants();
992 
993 	/* ACQUIRE: Host A with g_ctrlr1_A get reservation with
994 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
995 	 */
996 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
997 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0);
998 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
999 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1000 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1001 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1002 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1003 
1004 	/* Test Case: Host B release the reservation */
1005 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1006 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1);
1007 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1008 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1009 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1010 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
1011 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
1012 
1013 	/* Test Case: Host C clear the registrants */
1014 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1015 					     0, 0xc1);
1016 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req);
1017 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1018 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1019 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1020 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
1021 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1022 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1023 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1024 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
1025 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1026 
1027 	ut_reservation_free_req(req);
1028 	ut_reservation_deinit();
1029 }
1030 
1031 void
1032 nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr,
1033 				  struct spdk_nvmf_ns *ns,
1034 				  enum spdk_nvme_reservation_notification_log_page_type type)
1035 {
1036 	ctrlr->num_avail_log_pages++;
1037 }
1038 
1039 static void
1040 test_reservation_unregister_notification(void)
1041 {
1042 	struct spdk_nvmf_request *req;
1043 	struct spdk_nvme_cpl *rsp;
1044 
1045 	ut_reservation_init();
1046 
1047 	req = ut_reservation_build_req(16);
1048 	SPDK_CU_ASSERT_FATAL(req != NULL);
1049 	rsp = &req->rsp->nvme_cpl;
1050 
1051 	ut_reservation_build_registrants();
1052 
1053 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1054 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1055 	 */
1056 	rsp->status.sc = 0xff;
1057 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1058 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1059 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1060 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1061 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1062 
1063 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration.
1064 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for
1065 	 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY
1066 	 * type.
1067 	 */
1068 	rsp->status.sc = 0xff;
1069 	g_ctrlr1_A.num_avail_log_pages = 0;
1070 	g_ctrlr2_A.num_avail_log_pages = 0;
1071 	g_ctrlr_B.num_avail_log_pages = 5;
1072 	g_ctrlr_C.num_avail_log_pages = 0;
1073 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1074 					      0, 0, 0xb1, 0);
1075 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1076 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1077 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1078 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1079 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1080 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1081 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1082 
1083 	ut_reservation_free_req(req);
1084 	ut_reservation_deinit();
1085 }
1086 
1087 static void
1088 test_reservation_release_notification(void)
1089 {
1090 	struct spdk_nvmf_request *req;
1091 	struct spdk_nvme_cpl *rsp;
1092 
1093 	ut_reservation_init();
1094 
1095 	req = ut_reservation_build_req(16);
1096 	SPDK_CU_ASSERT_FATAL(req != NULL);
1097 	rsp = &req->rsp->nvme_cpl;
1098 
1099 	ut_reservation_build_registrants();
1100 
1101 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1102 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1103 	 */
1104 	rsp->status.sc = 0xff;
1105 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1106 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1107 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1108 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1109 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1110 
1111 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1112 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1113 	 */
1114 	rsp->status.sc = 0xff;
1115 	g_ctrlr1_A.num_avail_log_pages = 0;
1116 	g_ctrlr2_A.num_avail_log_pages = 0;
1117 	g_ctrlr_B.num_avail_log_pages = 5;
1118 	g_ctrlr_C.num_avail_log_pages = 0;
1119 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1120 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1);
1121 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1122 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1123 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1124 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1125 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1126 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1127 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1128 
1129 	ut_reservation_free_req(req);
1130 	ut_reservation_deinit();
1131 }
1132 
1133 static void
1134 test_reservation_release_notification_write_exclusive(void)
1135 {
1136 	struct spdk_nvmf_request *req;
1137 	struct spdk_nvme_cpl *rsp;
1138 
1139 	ut_reservation_init();
1140 
1141 	req = ut_reservation_build_req(16);
1142 	SPDK_CU_ASSERT_FATAL(req != NULL);
1143 	rsp = &req->rsp->nvme_cpl;
1144 
1145 	ut_reservation_build_registrants();
1146 
1147 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1148 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
1149 	 */
1150 	rsp->status.sc = 0xff;
1151 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1152 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0);
1153 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1154 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1155 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1156 
1157 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1158 	 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
1159 	 * no reservation notification occurs.
1160 	 */
1161 	rsp->status.sc = 0xff;
1162 	g_ctrlr1_A.num_avail_log_pages = 5;
1163 	g_ctrlr2_A.num_avail_log_pages = 5;
1164 	g_ctrlr_B.num_avail_log_pages = 5;
1165 	g_ctrlr_C.num_avail_log_pages = 5;
1166 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1167 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1);
1168 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1169 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1170 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1171 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages);
1172 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages);
1173 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1174 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1175 
1176 	ut_reservation_free_req(req);
1177 	ut_reservation_deinit();
1178 }
1179 
1180 static void
1181 test_reservation_clear_notification(void)
1182 {
1183 	struct spdk_nvmf_request *req;
1184 	struct spdk_nvme_cpl *rsp;
1185 
1186 	ut_reservation_init();
1187 
1188 	req = ut_reservation_build_req(16);
1189 	SPDK_CU_ASSERT_FATAL(req != NULL);
1190 	rsp = &req->rsp->nvme_cpl;
1191 
1192 	ut_reservation_build_registrants();
1193 
1194 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1195 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1196 	 */
1197 	rsp->status.sc = 0xff;
1198 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1199 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1200 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1201 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1202 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1203 
1204 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation.
1205 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1206 	 */
1207 	rsp->status.sc = 0xff;
1208 	g_ctrlr1_A.num_avail_log_pages = 0;
1209 	g_ctrlr2_A.num_avail_log_pages = 0;
1210 	g_ctrlr_B.num_avail_log_pages = 5;
1211 	g_ctrlr_C.num_avail_log_pages = 0;
1212 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1213 					     0, 0xb1);
1214 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1215 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1216 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1217 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1218 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1219 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1220 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1221 
1222 	ut_reservation_free_req(req);
1223 	ut_reservation_deinit();
1224 }
1225 
1226 static void
1227 test_reservation_preempt_notification(void)
1228 {
1229 	struct spdk_nvmf_request *req;
1230 	struct spdk_nvme_cpl *rsp;
1231 
1232 	ut_reservation_init();
1233 
1234 	req = ut_reservation_build_req(16);
1235 	SPDK_CU_ASSERT_FATAL(req != NULL);
1236 	rsp = &req->rsp->nvme_cpl;
1237 
1238 	ut_reservation_build_registrants();
1239 
1240 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1241 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1242 	 */
1243 	rsp->status.sc = 0xff;
1244 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1245 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1246 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1247 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1248 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1249 
1250 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B,
1251 	 * g_ctrlr_B registrant is unregistred, and reservation is preempted.
1252 	 * Registration Preempted notification sends to g_ctrlr_B.
1253 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A.
1254 	 */
1255 	rsp->status.sc = 0xff;
1256 	g_ctrlr1_A.num_avail_log_pages = 0;
1257 	g_ctrlr2_A.num_avail_log_pages = 0;
1258 	g_ctrlr_B.num_avail_log_pages = 0;
1259 	g_ctrlr_C.num_avail_log_pages = 5;
1260 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1261 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1);
1262 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
1263 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1264 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1265 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1266 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1267 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages);
1268 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1269 
1270 	ut_reservation_free_req(req);
1271 	ut_reservation_deinit();
1272 }
1273 
1274 static void
1275 test_spdk_nvmf_ns_event(void)
1276 {
1277 	struct spdk_nvmf_tgt tgt = {};
1278 	struct spdk_nvmf_subsystem subsystem = {
1279 		.max_nsid = 0,
1280 		.ns = NULL,
1281 		.tgt = &tgt
1282 	};
1283 	struct spdk_nvmf_ctrlr ctrlr = {
1284 		.subsys = &subsystem
1285 	};
1286 	struct spdk_nvmf_ns_opts ns_opts;
1287 	uint32_t nsid;
1288 	struct spdk_bdev *bdev;
1289 
1290 	tgt.max_subsystems = 1024;
1291 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1292 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1293 
1294 	/* Add one namespace */
1295 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1296 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev1", &ns_opts, sizeof(ns_opts), NULL);
1297 	CU_ASSERT(nsid == 1);
1298 	CU_ASSERT(NULL != subsystem.ns[0]);
1299 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[nsid - 1]);
1300 
1301 	bdev = subsystem.ns[nsid - 1]->bdev;
1302 
1303 	/* Add one controller */
1304 	TAILQ_INIT(&subsystem.ctrlrs);
1305 	TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link);
1306 
1307 	/* Namespace resize event */
1308 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1309 	g_ns_changed_nsid = 0xFFFFFFFF;
1310 	g_ns_changed_ctrlr = NULL;
1311 	nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, bdev, subsystem.ns[0]);
1312 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1313 
1314 	poll_threads();
1315 	CU_ASSERT(1 == g_ns_changed_nsid);
1316 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1317 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1318 
1319 	/* Namespace remove event */
1320 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1321 	g_ns_changed_nsid = 0xFFFFFFFF;
1322 	g_ns_changed_ctrlr = NULL;
1323 	nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, bdev, subsystem.ns[0]);
1324 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1325 	CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid);
1326 	CU_ASSERT(NULL == g_ns_changed_ctrlr);
1327 
1328 	poll_threads();
1329 	CU_ASSERT(1 == g_ns_changed_nsid);
1330 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1331 	CU_ASSERT(NULL == subsystem.ns[0]);
1332 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1333 
1334 	free(subsystem.ns);
1335 	free(tgt.subsystems);
1336 }
1337 
1338 
1339 int main(int argc, char **argv)
1340 {
1341 	CU_pSuite	suite = NULL;
1342 	unsigned int	num_failures;
1343 
1344 	CU_set_error_action(CUEA_ABORT);
1345 	CU_initialize_registry();
1346 
1347 	suite = CU_add_suite("nvmf", NULL, NULL);
1348 
1349 	CU_ADD_TEST(suite, nvmf_test_create_subsystem);
1350 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns);
1351 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn);
1352 	CU_ADD_TEST(suite, test_reservation_register);
1353 	CU_ADD_TEST(suite, test_reservation_register_with_ptpl);
1354 	CU_ADD_TEST(suite, test_reservation_acquire_preempt_1);
1355 	CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl);
1356 	CU_ADD_TEST(suite, test_reservation_release);
1357 	CU_ADD_TEST(suite, test_reservation_unregister_notification);
1358 	CU_ADD_TEST(suite, test_reservation_release_notification);
1359 	CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive);
1360 	CU_ADD_TEST(suite, test_reservation_clear_notification);
1361 	CU_ADD_TEST(suite, test_reservation_preempt_notification);
1362 	CU_ADD_TEST(suite, test_spdk_nvmf_ns_event);
1363 
1364 	allocate_threads(1);
1365 	set_thread(0);
1366 
1367 	CU_basic_set_mode(CU_BRM_VERBOSE);
1368 	CU_basic_run_tests();
1369 	num_failures = CU_get_number_of_failures();
1370 	CU_cleanup_registry();
1371 
1372 	free_threads();
1373 
1374 	return num_failures;
1375 }
1376