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