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