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