xref: /spdk/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c (revision 687cfd4b0d3152d5241be1394b38054d995f23be)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2016 Intel Corporation. All rights reserved.
3  *   Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 
8 #include "common/lib/ut_multithread.c"
9 #include "spdk_cunit.h"
10 #include "spdk_internal/mock.h"
11 
12 #include "spdk/bdev_module.h"
13 #include "nvmf/subsystem.c"
14 
15 SPDK_LOG_REGISTER_COMPONENT(nvmf)
16 
17 DEFINE_STUB(spdk_bdev_module_claim_bdev,
18 	    int,
19 	    (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
20 	     struct spdk_bdev_module *module), 0);
21 
22 DEFINE_STUB_V(spdk_bdev_module_release_bdev,
23 	      (struct spdk_bdev *bdev));
24 
25 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
26 	    (const struct spdk_bdev *bdev), 512);
27 
28 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
29 	    (const struct spdk_bdev *bdev), 0);
30 
31 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
32 	    (const struct spdk_bdev *bdev), false);
33 
34 DEFINE_STUB(spdk_bdev_io_type_supported, bool,
35 	    (struct spdk_bdev *bdev,
36 	     enum spdk_bdev_io_type io_type), false);
37 
38 DEFINE_STUB(spdk_nvmf_transport_stop_listen,
39 	    int,
40 	    (struct spdk_nvmf_transport *transport,
41 	     const struct spdk_nvme_transport_id *trid), 0);
42 
43 DEFINE_STUB_V(nvmf_update_discovery_log,
44 	      (struct spdk_nvmf_tgt *tgt, const char *hostnqn));
45 
46 DEFINE_STUB(spdk_nvmf_qpair_disconnect,
47 	    int,
48 	    (struct spdk_nvmf_qpair *qpair,
49 	     nvmf_qpair_disconnect_cb cb_fn, void *ctx), 0);
50 
51 DEFINE_STUB(nvmf_transport_find_listener,
52 	    struct spdk_nvmf_listener *,
53 	    (struct spdk_nvmf_transport *transport,
54 	     const struct spdk_nvme_transport_id *trid), NULL);
55 
56 DEFINE_STUB(spdk_nvmf_transport_get_first,
57 	    struct spdk_nvmf_transport *,
58 	    (struct spdk_nvmf_tgt *tgt), NULL);
59 
60 DEFINE_STUB(spdk_nvmf_transport_get_next,
61 	    struct spdk_nvmf_transport *,
62 	    (struct spdk_nvmf_transport *transport), NULL);
63 
64 DEFINE_STUB(spdk_nvmf_request_complete,
65 	    int,
66 	    (struct spdk_nvmf_request *req), 0);
67 
68 DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice,
69 	    int,
70 	    (struct spdk_nvmf_ctrlr *ctrlr), 0);
71 
72 DEFINE_STUB(spdk_nvme_transport_id_trtype_str,
73 	    const char *,
74 	    (enum spdk_nvme_transport_type trtype), NULL);
75 
76 DEFINE_STUB(spdk_bdev_is_zoned, bool,
77 	    (const struct spdk_bdev *bdev), false);
78 
79 DEFINE_STUB(spdk_bdev_get_max_zone_append_size, uint32_t,
80 	    (const struct spdk_bdev *bdev), 0);
81 
82 int
83 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
84 			   const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts)
85 {
86 	return 0;
87 }
88 
89 void
90 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
91 				 struct spdk_nvme_transport_id *trid,
92 				 struct spdk_nvmf_discovery_log_page_entry *entry)
93 {
94 	entry->trtype = 42;
95 }
96 
97 static struct spdk_nvmf_transport g_transport = {};
98 
99 int
100 spdk_nvmf_transport_create_async(const char *transport_name,
101 				 struct spdk_nvmf_transport_opts *tprt_opts,
102 				 spdk_nvmf_transport_create_done_cb cb_fn, void *cb_arg)
103 {
104 	if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) {
105 		cb_fn(cb_arg, &g_transport);
106 		return 0;
107 	}
108 
109 	return -1;
110 }
111 
112 struct spdk_nvmf_subsystem *
113 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
114 {
115 	return NULL;
116 }
117 
118 struct spdk_nvmf_transport *
119 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
120 {
121 	if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) {
122 		return &g_transport;
123 	}
124 
125 	return NULL;
126 }
127 
128 int
129 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
130 				 struct spdk_nvmf_subsystem *subsystem)
131 {
132 	return 0;
133 }
134 
135 int
136 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
137 			      struct spdk_nvmf_subsystem *subsystem,
138 			      spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
139 {
140 	return 0;
141 }
142 
143 void
144 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group,
145 				 struct spdk_nvmf_subsystem *subsystem,
146 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
147 {
148 }
149 
150 void
151 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
152 				struct spdk_nvmf_subsystem *subsystem,
153 				uint32_t nsid,
154 				spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
155 {
156 }
157 
158 void
159 nvmf_poll_group_resume_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 int
166 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
167 {
168 	if (trtype == NULL || str == NULL) {
169 		return -EINVAL;
170 	}
171 
172 	if (strcasecmp(str, "PCIe") == 0) {
173 		*trtype = SPDK_NVME_TRANSPORT_PCIE;
174 	} else if (strcasecmp(str, "RDMA") == 0) {
175 		*trtype = SPDK_NVME_TRANSPORT_RDMA;
176 	} else {
177 		return -ENOENT;
178 	}
179 	return 0;
180 }
181 
182 int
183 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
184 			       const struct spdk_nvme_transport_id *trid2)
185 {
186 	return 0;
187 }
188 
189 int32_t
190 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr)
191 {
192 	return -1;
193 }
194 
195 int32_t
196 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
197 {
198 	return -1;
199 }
200 
201 int
202 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
203 {
204 	return -1;
205 }
206 
207 void
208 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
209 {
210 }
211 
212 static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL;
213 static uint32_t g_ns_changed_nsid = 0;
214 void
215 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
216 {
217 	g_ns_changed_ctrlr = ctrlr;
218 	g_ns_changed_nsid = nsid;
219 }
220 
221 static struct spdk_bdev g_bdevs[] = {
222 	{ .name = "bdev1" },
223 	{ .name = "bdev2" },
224 };
225 
226 struct spdk_bdev_desc {
227 	struct spdk_bdev	*bdev;
228 };
229 
230 int
231 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
232 		   void *event_ctx, struct spdk_bdev_desc **_desc)
233 {
234 	struct spdk_bdev_desc *desc;
235 	size_t i;
236 
237 	for (i = 0; i < sizeof(g_bdevs); i++) {
238 		if (strcmp(bdev_name, g_bdevs[i].name) == 0) {
239 
240 			desc = calloc(1, sizeof(*desc));
241 			SPDK_CU_ASSERT_FATAL(desc != NULL);
242 
243 			desc->bdev = &g_bdevs[i];
244 			*_desc = desc;
245 			return 0;
246 		}
247 	}
248 
249 	return -EINVAL;
250 }
251 
252 void
253 spdk_bdev_close(struct spdk_bdev_desc *desc)
254 {
255 	free(desc);
256 }
257 
258 struct spdk_bdev *
259 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
260 {
261 	return desc->bdev;
262 }
263 
264 const char *
265 spdk_bdev_get_name(const struct spdk_bdev *bdev)
266 {
267 	return "test";
268 }
269 
270 const struct spdk_uuid *
271 spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
272 {
273 	return &bdev->uuid;
274 }
275 
276 static void
277 test_spdk_nvmf_subsystem_add_ns(void)
278 {
279 	struct spdk_nvmf_tgt tgt = {};
280 	struct spdk_nvmf_subsystem subsystem = {
281 		.max_nsid = 1024,
282 		.ns = NULL,
283 		.tgt = &tgt,
284 	};
285 	struct spdk_nvmf_ns_opts ns_opts;
286 	uint32_t nsid;
287 	int rc;
288 
289 	subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
290 	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
291 	subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
292 	SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
293 
294 	tgt.max_subsystems = 1024;
295 	RB_INIT(&tgt.subsystems);
296 
297 	/* Request a specific NSID */
298 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
299 	ns_opts.nsid = 5;
300 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
301 	CU_ASSERT(nsid == 5);
302 	CU_ASSERT(subsystem.max_nsid == 1024);
303 	SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
304 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[1]);
305 
306 	/* Request an NSID that is already in use */
307 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
308 	ns_opts.nsid = 5;
309 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
310 	CU_ASSERT(nsid == 0);
311 	CU_ASSERT(subsystem.max_nsid == 1024);
312 
313 	/* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */
314 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
315 	ns_opts.nsid = 0xFFFFFFFF;
316 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
317 	CU_ASSERT(nsid == 0);
318 	CU_ASSERT(subsystem.max_nsid == 1024);
319 
320 	rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5);
321 	CU_ASSERT(rc == 0);
322 
323 	free(subsystem.ns);
324 	free(subsystem.ana_group);
325 }
326 
327 static void
328 nvmf_test_create_subsystem(void)
329 {
330 	struct spdk_nvmf_tgt tgt = {};
331 	char nqn[256];
332 	struct spdk_nvmf_subsystem *subsystem;
333 	int rc;
334 
335 	tgt.max_subsystems = 1024;
336 	tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
337 	RB_INIT(&tgt.subsystems);
338 
339 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
340 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
341 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
342 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
343 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
344 	CU_ASSERT(rc == 0);
345 
346 	/* valid name with complex reverse domain */
347 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1");
348 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
349 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
350 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
351 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
352 	CU_ASSERT(rc == 0);
353 
354 	/* Valid name discovery controller */
355 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
356 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
357 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
358 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
359 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
360 	CU_ASSERT(rc == 0);
361 
362 	/* Invalid name, no user supplied string */
363 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
364 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
365 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
366 
367 	/* Valid name, only contains top-level domain name */
368 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
369 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
370 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
371 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
372 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
373 	CU_ASSERT(rc == 0);
374 
375 	/* Invalid name, domain label > 63 characters */
376 	snprintf(nqn, sizeof(nqn),
377 		 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub");
378 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
379 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
380 
381 	/* Invalid name, domain label starts with digit */
382 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub");
383 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
384 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
385 
386 	/* Invalid name, domain label starts with - */
387 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1");
388 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
389 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
390 
391 	/* Invalid name, domain label ends with - */
392 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1");
393 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
394 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
395 
396 	/* Invalid name, domain label with multiple consecutive periods */
397 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1");
398 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
399 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
400 
401 	/* Longest valid name */
402 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
403 	memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn));
404 	nqn[223] = '\0';
405 	CU_ASSERT(strlen(nqn) == 223);
406 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
407 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
408 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
409 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
410 	CU_ASSERT(rc == 0);
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:ff9b6406-0fc8-4779-80ca-4dca14bda0d2");
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 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
426 	CU_ASSERT(rc == 0);
427 
428 	/* Invalid name user string contains an invalid utf-8 character */
429 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1");
430 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
431 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
432 
433 	/* Valid name with non-ascii but valid utf-8 characters */
434 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80");
435 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
436 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
437 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
438 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
439 	CU_ASSERT(rc == 0);
440 
441 	/* Invalid uuid (too long) */
442 	snprintf(nqn, sizeof(nqn),
443 		 "nqn.2014-08.org.nvmexpress:uuid:ff9b6406-0fc8-4779-80ca-4dca14bda0d2aaaa");
444 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
445 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
446 
447 	/* Invalid uuid (dashes placed incorrectly) */
448 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:ff9b64-060fc8-4779-80ca-4dca14bda0d2");
449 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
450 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
451 
452 	/* Invalid uuid (invalid characters in uuid) */
453 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:ff9hg406-0fc8-4779-80ca-4dca14bda0d2");
454 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
455 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
456 
457 	spdk_bit_array_free(&tgt.subsystem_ids);
458 }
459 
460 static void
461 test_spdk_nvmf_subsystem_set_sn(void)
462 {
463 	struct spdk_nvmf_subsystem subsystem = {};
464 
465 	/* Basic valid serial number */
466 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0);
467 	CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0);
468 
469 	/* Exactly 20 characters (valid) */
470 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0);
471 	CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0);
472 
473 	/* 21 characters (too long, invalid) */
474 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0);
475 
476 	/* Non-ASCII characters (invalid) */
477 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0);
478 }
479 
480 /*
481  * Reservation Unit Test Configuration
482  *       --------             --------    --------
483  *      | Host A |           | Host B |  | Host C |
484  *       --------             --------    --------
485  *      /        \               |           |
486  *  --------   --------       -------     -------
487  * |Ctrlr1_A| |Ctrlr2_A|     |Ctrlr_B|   |Ctrlr_C|
488  *  --------   --------       -------     -------
489  *    \           \              /           /
490  *     \           \            /           /
491  *      \           \          /           /
492  *      --------------------------------------
493  *     |            NAMESPACE 1               |
494  *      --------------------------------------
495  */
496 static struct spdk_nvmf_subsystem g_subsystem;
497 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C;
498 static struct spdk_nvmf_ns g_ns;
499 static struct spdk_bdev g_bdev;
500 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info;
501 
502 void
503 nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr)
504 {
505 }
506 
507 static void
508 ut_reservation_init(void)
509 {
510 
511 	TAILQ_INIT(&g_subsystem.ctrlrs);
512 
513 	memset(&g_ns, 0, sizeof(g_ns));
514 	TAILQ_INIT(&g_ns.registrants);
515 	g_ns.subsystem = &g_subsystem;
516 	g_ns.ptpl_file = NULL;
517 	g_ns.ptpl_activated = false;
518 	spdk_uuid_generate(&g_bdev.uuid);
519 	g_ns.bdev = &g_bdev;
520 
521 	/* Host A has two controllers */
522 	spdk_uuid_generate(&g_ctrlr1_A.hostid);
523 	TAILQ_INIT(&g_ctrlr1_A.log_head);
524 	g_ctrlr1_A.subsys = &g_subsystem;
525 	g_ctrlr1_A.num_avail_log_pages = 0;
526 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link);
527 	spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid);
528 	TAILQ_INIT(&g_ctrlr2_A.log_head);
529 	g_ctrlr2_A.subsys = &g_subsystem;
530 	g_ctrlr2_A.num_avail_log_pages = 0;
531 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link);
532 
533 	/* Host B has 1 controller */
534 	spdk_uuid_generate(&g_ctrlr_B.hostid);
535 	TAILQ_INIT(&g_ctrlr_B.log_head);
536 	g_ctrlr_B.subsys = &g_subsystem;
537 	g_ctrlr_B.num_avail_log_pages = 0;
538 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link);
539 
540 	/* Host C has 1 controller */
541 	spdk_uuid_generate(&g_ctrlr_C.hostid);
542 	TAILQ_INIT(&g_ctrlr_C.log_head);
543 	g_ctrlr_C.subsys = &g_subsystem;
544 	g_ctrlr_C.num_avail_log_pages = 0;
545 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link);
546 }
547 
548 static void
549 ut_reservation_deinit(void)
550 {
551 	struct spdk_nvmf_registrant *reg, *tmp;
552 	struct spdk_nvmf_reservation_log *log, *log_tmp;
553 	struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
554 
555 	TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) {
556 		TAILQ_REMOVE(&g_ns.registrants, reg, link);
557 		free(reg);
558 	}
559 	TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) {
560 		TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link);
561 		free(log);
562 	}
563 	g_ctrlr1_A.num_avail_log_pages = 0;
564 	TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) {
565 		TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link);
566 		free(log);
567 	}
568 	g_ctrlr2_A.num_avail_log_pages = 0;
569 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) {
570 		TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link);
571 		free(log);
572 	}
573 	g_ctrlr_B.num_avail_log_pages = 0;
574 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) {
575 		TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link);
576 		free(log);
577 	}
578 	g_ctrlr_C.num_avail_log_pages = 0;
579 
580 	TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) {
581 		TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link);
582 	}
583 }
584 
585 static struct spdk_nvmf_request *
586 ut_reservation_build_req(uint32_t length)
587 {
588 	struct spdk_nvmf_request *req;
589 
590 	req = calloc(1, sizeof(*req));
591 	assert(req != NULL);
592 
593 	spdk_iov_one(req->iov, &req->iovcnt, calloc(1, length), length);
594 	assert(req->iov[0].iov_base != NULL);
595 	req->data = req->iov[0].iov_base;
596 	req->length = length;
597 
598 	req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg));
599 	assert(req->cmd != NULL);
600 
601 	req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg));
602 	assert(req->rsp != NULL);
603 
604 	return req;
605 }
606 
607 static void
608 ut_reservation_free_req(struct spdk_nvmf_request *req)
609 {
610 	free(req->cmd);
611 	free(req->rsp);
612 	free(req->iov[0].iov_base);
613 	free(req);
614 }
615 
616 static void
617 ut_reservation_build_register_request(struct spdk_nvmf_request *req,
618 				      uint8_t rrega, uint8_t iekey,
619 				      uint8_t cptpl, uint64_t crkey,
620 				      uint64_t nrkey)
621 {
622 	struct spdk_nvme_reservation_register_data key;
623 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
624 
625 	key.crkey = crkey;
626 	key.nrkey = nrkey;
627 	cmd->cdw10 = 0;
628 	cmd->cdw10_bits.resv_register.rrega = rrega;
629 	cmd->cdw10_bits.resv_register.iekey = iekey;
630 	cmd->cdw10_bits.resv_register.cptpl = cptpl;
631 	memcpy(req->iov[0].iov_base, &key, sizeof(key));
632 }
633 
634 static void
635 ut_reservation_build_acquire_request(struct spdk_nvmf_request *req,
636 				     uint8_t racqa, uint8_t iekey,
637 				     uint8_t rtype, uint64_t crkey,
638 				     uint64_t prkey)
639 {
640 	struct spdk_nvme_reservation_acquire_data key;
641 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
642 
643 	key.crkey = crkey;
644 	key.prkey = prkey;
645 	cmd->cdw10 = 0;
646 	cmd->cdw10_bits.resv_acquire.racqa = racqa;
647 	cmd->cdw10_bits.resv_acquire.iekey = iekey;
648 	cmd->cdw10_bits.resv_acquire.rtype = rtype;
649 	memcpy(req->iov[0].iov_base, &key, sizeof(key));
650 }
651 
652 static void
653 ut_reservation_build_release_request(struct spdk_nvmf_request *req,
654 				     uint8_t rrela, uint8_t iekey,
655 				     uint8_t rtype, uint64_t crkey)
656 {
657 	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
658 
659 	cmd->cdw10 = 0;
660 	cmd->cdw10_bits.resv_release.rrela = rrela;
661 	cmd->cdw10_bits.resv_release.iekey = iekey;
662 	cmd->cdw10_bits.resv_release.rtype = rtype;
663 	memcpy(req->iov[0].iov_base, &crkey, sizeof(crkey));
664 }
665 
666 /*
667  * Construct four registrants for other test cases.
668  *
669  * g_ctrlr1_A register with key 0xa1.
670  * g_ctrlr2_A register with key 0xa1.
671  * g_ctrlr_B register with key 0xb1.
672  * g_ctrlr_C register with key 0xc1.
673  * */
674 static void
675 ut_reservation_build_registrants(void)
676 {
677 	struct spdk_nvmf_request *req;
678 	struct spdk_nvme_cpl *rsp;
679 	struct spdk_nvmf_registrant *reg;
680 	uint32_t gen;
681 
682 	req = ut_reservation_build_req(16);
683 	rsp = &req->rsp->nvme_cpl;
684 	SPDK_CU_ASSERT_FATAL(req != NULL);
685 	gen = g_ns.gen;
686 
687 	/* TEST CASE: g_ctrlr1_A register with a new key */
688 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
689 					      0, 0, 0, 0xa1);
690 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
691 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
692 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
693 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
694 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1);
695 
696 	/* TEST CASE: g_ctrlr2_A register with a new key, because it has same
697 	 * Host Identifier with g_ctrlr1_A, so the register key should same.
698 	 */
699 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
700 					      0, 0, 0, 0xa2);
701 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req);
702 	/* Reservation conflict for other key than 0xa1 */
703 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT);
704 
705 	/* g_ctrlr_B register with a new key */
706 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
707 					      0, 0, 0, 0xb1);
708 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
709 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
710 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
711 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1);
712 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2);
713 
714 	/* g_ctrlr_C register with a new key */
715 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
716 					      0, 0, 0, 0xc1);
717 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
718 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
719 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
720 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1);
721 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3);
722 
723 	ut_reservation_free_req(req);
724 }
725 
726 static void
727 test_reservation_register(void)
728 {
729 	struct spdk_nvmf_request *req;
730 	struct spdk_nvme_cpl *rsp;
731 	struct spdk_nvmf_registrant *reg;
732 	uint32_t gen;
733 
734 	ut_reservation_init();
735 
736 	req = ut_reservation_build_req(16);
737 	rsp = &req->rsp->nvme_cpl;
738 	SPDK_CU_ASSERT_FATAL(req != NULL);
739 
740 	ut_reservation_build_registrants();
741 
742 	/* TEST CASE: Replace g_ctrlr1_A with a new key */
743 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
744 					      0, 0, 0xa1, 0xa11);
745 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
746 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
747 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
748 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11);
749 
750 	/* TEST CASE: Host A with g_ctrlr1_A get reservation with
751 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
752 	 */
753 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
754 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0);
755 	gen = g_ns.gen;
756 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
757 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
758 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
759 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
760 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11);
761 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
762 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
763 
764 	/* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
765 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
766 					      1, 0, 0, 0);
767 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
768 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
769 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
770 	SPDK_CU_ASSERT_FATAL(reg == NULL);
771 
772 	/* TEST CASE: g_ctrlr_B unregister with correct key */
773 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
774 					      0, 0, 0xb1, 0);
775 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
776 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
777 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
778 	SPDK_CU_ASSERT_FATAL(reg == NULL);
779 
780 	/* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY disabled */
781 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
782 					      0, 0, 0, 0xb1);
783 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
784 	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
785 
786 	/* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY enabled */
787 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
788 					      1, 0, 0, 0xb1);
789 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
790 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
791 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
792 	SPDK_CU_ASSERT_FATAL(reg != NULL);
793 
794 	/* TEST CASE: g_ctrlr_B replace new key with IEKEY enabled and wrong crkey  */
795 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
796 					      1, 0, 0xff, 0xb2);
797 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
798 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
799 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
800 	SPDK_CU_ASSERT_FATAL(reg != NULL);
801 	SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb2);
802 
803 	/* TEST CASE: g_ctrlr1_A unregister with correct key,
804 	 * reservation should be removed as well.
805 	 */
806 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
807 					      0, 0, 0xa11, 0);
808 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
809 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
810 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
811 	SPDK_CU_ASSERT_FATAL(reg == NULL);
812 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
813 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
814 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
815 
816 	ut_reservation_free_req(req);
817 	ut_reservation_deinit();
818 }
819 
820 static void
821 test_reservation_register_with_ptpl(void)
822 {
823 	struct spdk_nvmf_request *req;
824 	struct spdk_nvme_cpl *rsp;
825 	struct spdk_nvmf_registrant *reg;
826 	bool update_sgroup = false;
827 	int rc;
828 	struct spdk_nvmf_reservation_info info;
829 
830 	ut_reservation_init();
831 
832 	req = ut_reservation_build_req(16);
833 	rsp = &req->rsp->nvme_cpl;
834 	SPDK_CU_ASSERT_FATAL(req != NULL);
835 
836 	/* TEST CASE: No persistent file, register with PTPL enabled will fail */
837 	g_ns.ptpl_file = NULL;
838 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
839 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
840 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
841 	SPDK_CU_ASSERT_FATAL(update_sgroup == false);
842 	SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
843 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
844 	SPDK_CU_ASSERT_FATAL(reg == NULL);
845 
846 	/* TEST CASE: Enable PTPL */
847 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
848 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
849 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
850 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
851 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
852 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
853 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
854 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
855 	SPDK_CU_ASSERT_FATAL(reg != NULL);
856 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
857 	/* Load reservation information from configuration file */
858 	memset(&info, 0, sizeof(info));
859 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
860 	SPDK_CU_ASSERT_FATAL(rc == 0);
861 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
862 
863 	/* TEST CASE: Disable PTPL */
864 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
865 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
866 					      SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1);
867 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
868 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
869 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
870 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false);
871 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
872 	SPDK_CU_ASSERT_FATAL(rc < 0);
873 	unlink(g_ns.ptpl_file);
874 
875 	ut_reservation_free_req(req);
876 	ut_reservation_deinit();
877 }
878 
879 static void
880 test_reservation_acquire_preempt_1(void)
881 {
882 	struct spdk_nvmf_request *req;
883 	struct spdk_nvme_cpl *rsp;
884 	struct spdk_nvmf_registrant *reg;
885 	uint32_t gen;
886 
887 	ut_reservation_init();
888 
889 	req = ut_reservation_build_req(16);
890 	rsp = &req->rsp->nvme_cpl;
891 	SPDK_CU_ASSERT_FATAL(req != NULL);
892 
893 	ut_reservation_build_registrants();
894 
895 	gen = g_ns.gen;
896 	/* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
897 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
898 	 */
899 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
900 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
901 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
902 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
903 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
904 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
905 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1);
906 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
907 	SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
908 
909 	/* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
910 	 * g_ctrl1_A registrant is unregistered.
911 	 */
912 	gen = g_ns.gen;
913 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
914 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1);
915 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
916 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
917 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
918 	SPDK_CU_ASSERT_FATAL(reg == NULL);
919 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
920 	SPDK_CU_ASSERT_FATAL(reg != NULL);
921 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
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.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
925 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
926 
927 	/* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B
928 	 * with valid key and PRKEY set to 0, all registrants other the host that issued
929 	 * the command are unregistered.
930 	 */
931 	gen = g_ns.gen;
932 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
933 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0);
934 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
935 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
936 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
937 	SPDK_CU_ASSERT_FATAL(reg == NULL);
938 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
939 	SPDK_CU_ASSERT_FATAL(reg == NULL);
940 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
941 	SPDK_CU_ASSERT_FATAL(reg != NULL);
942 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
943 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
944 	SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
945 
946 	ut_reservation_free_req(req);
947 	ut_reservation_deinit();
948 }
949 
950 static void
951 test_reservation_acquire_release_with_ptpl(void)
952 {
953 	struct spdk_nvmf_request *req;
954 	struct spdk_nvme_cpl *rsp;
955 	struct spdk_nvmf_registrant *reg;
956 	bool update_sgroup = false;
957 	struct spdk_uuid holder_uuid;
958 	int rc;
959 	struct spdk_nvmf_reservation_info info;
960 
961 	ut_reservation_init();
962 
963 	req = ut_reservation_build_req(16);
964 	rsp = &req->rsp->nvme_cpl;
965 	SPDK_CU_ASSERT_FATAL(req != NULL);
966 
967 	/* TEST CASE: Enable PTPL */
968 	g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
969 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
970 					      SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
971 	update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
972 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
973 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
974 	SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
975 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
976 	SPDK_CU_ASSERT_FATAL(reg != NULL);
977 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &reg->hostid));
978 	/* Load reservation information from configuration file */
979 	memset(&info, 0, sizeof(info));
980 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
981 	SPDK_CU_ASSERT_FATAL(rc == 0);
982 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
983 
984 	/* TEST CASE: Acquire the reservation */
985 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
986 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
987 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
988 	update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
989 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
990 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
991 	memset(&info, 0, sizeof(info));
992 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
993 	SPDK_CU_ASSERT_FATAL(rc == 0);
994 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
995 	SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
996 	SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1);
997 	spdk_uuid_parse(&holder_uuid, info.holder_uuid);
998 	SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid));
999 
1000 	/* TEST CASE: Release the reservation */
1001 	rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
1002 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1003 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1);
1004 	update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req);
1005 	SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1006 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1007 	memset(&info, 0, sizeof(info));
1008 	rc = nvmf_ns_load_reservation(g_ns.ptpl_file, &info);
1009 	SPDK_CU_ASSERT_FATAL(rc == 0);
1010 	SPDK_CU_ASSERT_FATAL(info.rtype == 0);
1011 	SPDK_CU_ASSERT_FATAL(info.crkey == 0);
1012 	SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1013 	unlink(g_ns.ptpl_file);
1014 
1015 	ut_reservation_free_req(req);
1016 	ut_reservation_deinit();
1017 }
1018 
1019 static void
1020 test_reservation_release(void)
1021 {
1022 	struct spdk_nvmf_request *req;
1023 	struct spdk_nvme_cpl *rsp;
1024 	struct spdk_nvmf_registrant *reg;
1025 
1026 	ut_reservation_init();
1027 
1028 	req = ut_reservation_build_req(16);
1029 	rsp = &req->rsp->nvme_cpl;
1030 	SPDK_CU_ASSERT_FATAL(req != NULL);
1031 
1032 	ut_reservation_build_registrants();
1033 
1034 	/* ACQUIRE: Host A with g_ctrlr1_A get reservation with
1035 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
1036 	 */
1037 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1038 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0);
1039 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, 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(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1043 	SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1044 
1045 	/* Test Case: Host B release the reservation */
1046 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1047 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1);
1048 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1049 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1050 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1051 	SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
1052 	SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
1053 
1054 	/* Test Case: Host C clear the registrants */
1055 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1056 					     0, 0xc1);
1057 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req);
1058 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1059 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1060 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1061 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
1062 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1063 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1064 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1065 	reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
1066 	SPDK_CU_ASSERT_FATAL(reg == NULL);
1067 
1068 	ut_reservation_free_req(req);
1069 	ut_reservation_deinit();
1070 }
1071 
1072 void
1073 nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr,
1074 				  struct spdk_nvmf_ns *ns,
1075 				  enum spdk_nvme_reservation_notification_log_page_type type)
1076 {
1077 	ctrlr->num_avail_log_pages++;
1078 }
1079 
1080 static void
1081 test_reservation_unregister_notification(void)
1082 {
1083 	struct spdk_nvmf_request *req;
1084 	struct spdk_nvme_cpl *rsp;
1085 
1086 	ut_reservation_init();
1087 
1088 	req = ut_reservation_build_req(16);
1089 	SPDK_CU_ASSERT_FATAL(req != NULL);
1090 	rsp = &req->rsp->nvme_cpl;
1091 
1092 	ut_reservation_build_registrants();
1093 
1094 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1095 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1096 	 */
1097 	rsp->status.sc = 0xff;
1098 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1099 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1100 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1101 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1102 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1103 
1104 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration.
1105 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for
1106 	 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY
1107 	 * type.
1108 	 */
1109 	rsp->status.sc = 0xff;
1110 	g_ctrlr1_A.num_avail_log_pages = 0;
1111 	g_ctrlr2_A.num_avail_log_pages = 0;
1112 	g_ctrlr_B.num_avail_log_pages = 5;
1113 	g_ctrlr_C.num_avail_log_pages = 0;
1114 	ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1115 					      0, 0, 0xb1, 0);
1116 	nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1117 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1118 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1119 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1120 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1121 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1122 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1123 
1124 	ut_reservation_free_req(req);
1125 	ut_reservation_deinit();
1126 }
1127 
1128 static void
1129 test_reservation_release_notification(void)
1130 {
1131 	struct spdk_nvmf_request *req;
1132 	struct spdk_nvme_cpl *rsp;
1133 
1134 	ut_reservation_init();
1135 
1136 	req = ut_reservation_build_req(16);
1137 	SPDK_CU_ASSERT_FATAL(req != NULL);
1138 	rsp = &req->rsp->nvme_cpl;
1139 
1140 	ut_reservation_build_registrants();
1141 
1142 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1143 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1144 	 */
1145 	rsp->status.sc = 0xff;
1146 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1147 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1148 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1149 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1150 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1151 
1152 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1153 	 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1154 	 */
1155 	rsp->status.sc = 0xff;
1156 	g_ctrlr1_A.num_avail_log_pages = 0;
1157 	g_ctrlr2_A.num_avail_log_pages = 0;
1158 	g_ctrlr_B.num_avail_log_pages = 5;
1159 	g_ctrlr_C.num_avail_log_pages = 0;
1160 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1161 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1);
1162 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1163 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1164 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1165 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1166 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1167 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1168 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1169 
1170 	ut_reservation_free_req(req);
1171 	ut_reservation_deinit();
1172 }
1173 
1174 static void
1175 test_reservation_release_notification_write_exclusive(void)
1176 {
1177 	struct spdk_nvmf_request *req;
1178 	struct spdk_nvme_cpl *rsp;
1179 
1180 	ut_reservation_init();
1181 
1182 	req = ut_reservation_build_req(16);
1183 	SPDK_CU_ASSERT_FATAL(req != NULL);
1184 	rsp = &req->rsp->nvme_cpl;
1185 
1186 	ut_reservation_build_registrants();
1187 
1188 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1189 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
1190 	 */
1191 	rsp->status.sc = 0xff;
1192 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1193 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0);
1194 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1195 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1196 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1197 
1198 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1199 	 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
1200 	 * no reservation notification occurs.
1201 	 */
1202 	rsp->status.sc = 0xff;
1203 	g_ctrlr1_A.num_avail_log_pages = 5;
1204 	g_ctrlr2_A.num_avail_log_pages = 5;
1205 	g_ctrlr_B.num_avail_log_pages = 5;
1206 	g_ctrlr_C.num_avail_log_pages = 5;
1207 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1208 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1);
1209 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1210 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1211 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1212 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages);
1213 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages);
1214 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1215 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1216 
1217 	ut_reservation_free_req(req);
1218 	ut_reservation_deinit();
1219 }
1220 
1221 static void
1222 test_reservation_clear_notification(void)
1223 {
1224 	struct spdk_nvmf_request *req;
1225 	struct spdk_nvme_cpl *rsp;
1226 
1227 	ut_reservation_init();
1228 
1229 	req = ut_reservation_build_req(16);
1230 	SPDK_CU_ASSERT_FATAL(req != NULL);
1231 	rsp = &req->rsp->nvme_cpl;
1232 
1233 	ut_reservation_build_registrants();
1234 
1235 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1236 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1237 	 */
1238 	rsp->status.sc = 0xff;
1239 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1240 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1241 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1242 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1243 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1244 
1245 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation.
1246 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1247 	 */
1248 	rsp->status.sc = 0xff;
1249 	g_ctrlr1_A.num_avail_log_pages = 0;
1250 	g_ctrlr2_A.num_avail_log_pages = 0;
1251 	g_ctrlr_B.num_avail_log_pages = 5;
1252 	g_ctrlr_C.num_avail_log_pages = 0;
1253 	ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1254 					     0, 0xb1);
1255 	nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1256 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1257 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1258 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1259 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1260 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1261 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1262 
1263 	ut_reservation_free_req(req);
1264 	ut_reservation_deinit();
1265 }
1266 
1267 static void
1268 test_reservation_preempt_notification(void)
1269 {
1270 	struct spdk_nvmf_request *req;
1271 	struct spdk_nvme_cpl *rsp;
1272 
1273 	ut_reservation_init();
1274 
1275 	req = ut_reservation_build_req(16);
1276 	SPDK_CU_ASSERT_FATAL(req != NULL);
1277 	rsp = &req->rsp->nvme_cpl;
1278 
1279 	ut_reservation_build_registrants();
1280 
1281 	/* ACQUIRE: Host B with g_ctrlr_B get reservation with
1282 	 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1283 	 */
1284 	rsp->status.sc = 0xff;
1285 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1286 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1287 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1288 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1289 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1290 
1291 	/* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B,
1292 	 * g_ctrlr_B registrant is unregistered, and reservation is preempted.
1293 	 * Registration Preempted notification sends to g_ctrlr_B.
1294 	 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A.
1295 	 */
1296 	rsp->status.sc = 0xff;
1297 	g_ctrlr1_A.num_avail_log_pages = 0;
1298 	g_ctrlr2_A.num_avail_log_pages = 0;
1299 	g_ctrlr_B.num_avail_log_pages = 0;
1300 	g_ctrlr_C.num_avail_log_pages = 5;
1301 	ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1302 					     SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1);
1303 	nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
1304 	SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1305 	SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1306 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1307 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1308 	SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages);
1309 	SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1310 
1311 	ut_reservation_free_req(req);
1312 	ut_reservation_deinit();
1313 }
1314 
1315 static int
1316 nvmf_tgt_create_poll_group(void *io_device, void *ctx_buf)
1317 {
1318 	return 0;
1319 }
1320 
1321 static void
1322 nvmf_tgt_destroy_poll_group(void *io_device, void *ctx_buf)
1323 {
1324 }
1325 
1326 static void
1327 test_spdk_nvmf_ns_event(void)
1328 {
1329 	struct spdk_nvmf_tgt tgt = {};
1330 	struct spdk_nvmf_subsystem subsystem = {
1331 		.max_nsid = 1024,
1332 		.ns = NULL,
1333 		.tgt = &tgt,
1334 	};
1335 	struct spdk_nvmf_ctrlr ctrlr = {
1336 		.subsys = &subsystem
1337 	};
1338 	struct spdk_nvmf_ns_opts ns_opts;
1339 	uint32_t nsid;
1340 	struct spdk_bdev *bdev;
1341 
1342 	subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
1343 	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
1344 	subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
1345 	SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
1346 
1347 	tgt.max_subsystems = 1024;
1348 	tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
1349 	RB_INIT(&tgt.subsystems);
1350 
1351 	spdk_io_device_register(&tgt,
1352 				nvmf_tgt_create_poll_group,
1353 				nvmf_tgt_destroy_poll_group,
1354 				sizeof(struct spdk_nvmf_poll_group),
1355 				NULL);
1356 
1357 	/* Add one namespace */
1358 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1359 	nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev1", &ns_opts, sizeof(ns_opts), NULL);
1360 	CU_ASSERT(nsid == 1);
1361 	CU_ASSERT(NULL != subsystem.ns[0]);
1362 	CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[nsid - 1]);
1363 
1364 	bdev = subsystem.ns[nsid - 1]->bdev;
1365 
1366 	/* Add one controller */
1367 	TAILQ_INIT(&subsystem.ctrlrs);
1368 	TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link);
1369 
1370 	/* Namespace resize event */
1371 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1372 	g_ns_changed_nsid = 0xFFFFFFFF;
1373 	g_ns_changed_ctrlr = NULL;
1374 	nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, bdev, subsystem.ns[0]);
1375 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1376 
1377 	poll_threads();
1378 	CU_ASSERT(1 == g_ns_changed_nsid);
1379 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1380 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1381 
1382 	/* Namespace remove event */
1383 	subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1384 	g_ns_changed_nsid = 0xFFFFFFFF;
1385 	g_ns_changed_ctrlr = NULL;
1386 	nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, bdev, subsystem.ns[0]);
1387 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1388 	CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid);
1389 	CU_ASSERT(NULL == g_ns_changed_ctrlr);
1390 
1391 	poll_threads();
1392 	CU_ASSERT(1 == g_ns_changed_nsid);
1393 	CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1394 	CU_ASSERT(NULL == subsystem.ns[0]);
1395 	CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1396 
1397 	spdk_io_device_unregister(&tgt, NULL);
1398 
1399 	poll_threads();
1400 
1401 	free(subsystem.ns);
1402 	free(subsystem.ana_group);
1403 	spdk_bit_array_free(&tgt.subsystem_ids);
1404 }
1405 
1406 static void
1407 test_nvmf_ns_reservation_add_remove_registrant(void)
1408 {
1409 	struct spdk_nvmf_ns ns = {};
1410 	struct spdk_nvmf_ctrlr ctrlr = {};
1411 	struct spdk_nvmf_registrant *reg = NULL;
1412 	int rc;
1413 
1414 	TAILQ_INIT(&ns.registrants);
1415 	spdk_uuid_generate(&ctrlr.hostid);
1416 
1417 	rc = nvmf_ns_reservation_add_registrant(&ns, &ctrlr, 0xa11);
1418 	CU_ASSERT(rc == 0);
1419 	reg = TAILQ_FIRST(&ns.registrants);
1420 	SPDK_CU_ASSERT_FATAL(reg != NULL);
1421 	CU_ASSERT(ns.gen == 1);
1422 	CU_ASSERT(reg->rkey == 0xa11);
1423 	CU_ASSERT(!strncmp((uint8_t *)&reg->hostid, (uint8_t *)&ctrlr.hostid, sizeof(ctrlr.hostid)));
1424 
1425 	nvmf_ns_reservation_remove_registrant(&ns, reg);
1426 	CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
1427 	CU_ASSERT(ns.gen == 2);
1428 }
1429 
1430 static void
1431 test_nvmf_subsystem_destroy_cb(void *cb_arg)
1432 {
1433 }
1434 
1435 static void
1436 test_nvmf_subsystem_add_ctrlr(void)
1437 {
1438 	int rc;
1439 	struct spdk_nvmf_ctrlr ctrlr = {};
1440 	struct spdk_nvmf_tgt tgt = {};
1441 	char nqn[256] = "nqn.2016-06.io.spdk:subsystem1";
1442 	struct spdk_nvmf_subsystem *subsystem = NULL;
1443 
1444 	tgt.max_subsystems = 1024;
1445 	tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
1446 	RB_INIT(&tgt.subsystems);
1447 
1448 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1449 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1450 	ctrlr.subsys = subsystem;
1451 
1452 	ctrlr.dynamic_ctrlr = true;
1453 	rc = nvmf_subsystem_add_ctrlr(subsystem, &ctrlr);
1454 	CU_ASSERT(rc == 0);
1455 	CU_ASSERT(!TAILQ_EMPTY(&subsystem->ctrlrs));
1456 	CU_ASSERT(ctrlr.cntlid == 1);
1457 	CU_ASSERT(nvmf_subsystem_get_ctrlr(subsystem, 1) == &ctrlr);
1458 
1459 	nvmf_subsystem_remove_ctrlr(subsystem, &ctrlr);
1460 	CU_ASSERT(TAILQ_EMPTY(&subsystem->ctrlrs));
1461 	rc = spdk_nvmf_subsystem_destroy(subsystem, test_nvmf_subsystem_destroy_cb, NULL);
1462 	CU_ASSERT(rc == 0);
1463 	spdk_bit_array_free(&tgt.subsystem_ids);
1464 }
1465 
1466 static void
1467 test_spdk_nvmf_subsystem_add_host(void)
1468 {
1469 	struct spdk_nvmf_tgt tgt = {};
1470 	struct spdk_nvmf_subsystem *subsystem = NULL;
1471 	int rc;
1472 	const char hostnqn[] = "nqn.2016-06.io.spdk:host1";
1473 	const char subsystemnqn[] = "nqn.2016-06.io.spdk:subsystem1";
1474 
1475 	tgt.max_subsystems = 1024;
1476 	tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
1477 	RB_INIT(&tgt.subsystems);
1478 
1479 	subsystem = spdk_nvmf_subsystem_create(&tgt, subsystemnqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1480 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1481 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, subsystemnqn);
1482 
1483 	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn);
1484 	CU_ASSERT(rc == 0);
1485 	CU_ASSERT(!TAILQ_EMPTY(&subsystem->hosts));
1486 
1487 	/* Add existing nqn, this function is allowed to be called if the nqn was previously added. */
1488 	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn);
1489 	CU_ASSERT(rc == 0);
1490 
1491 	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1492 	CU_ASSERT(rc == 0);
1493 	CU_ASSERT(TAILQ_EMPTY(&subsystem->hosts));
1494 
1495 	/* No available nqn */
1496 	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1497 	CU_ASSERT(rc == -ENOENT);
1498 
1499 	spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
1500 	spdk_bit_array_free(&tgt.subsystem_ids);
1501 }
1502 
1503 static void
1504 test_nvmf_ns_reservation_report(void)
1505 {
1506 	struct spdk_nvmf_ns ns = {};
1507 	struct spdk_nvmf_ctrlr ctrlr = {};
1508 	struct spdk_nvmf_request req = {};
1509 	union nvmf_h2c_msg cmd = {};
1510 	union nvmf_c2h_msg rsp = {};
1511 	struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data;
1512 	struct spdk_nvme_reservation_status_extended_data *status_data;
1513 	struct spdk_nvmf_registrant *reg;
1514 	void *data;
1515 
1516 	data = calloc(1, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1517 	reg = calloc(2, sizeof(struct spdk_nvmf_registrant));
1518 	SPDK_CU_ASSERT_FATAL(data != NULL && reg != NULL);
1519 
1520 	req.length = sizeof(*status_data) + sizeof(*ctrlr_data) * 2;
1521 	spdk_iov_one(req.iov, &req.iovcnt, data, req.length);
1522 	req.data = req.iov[0].iov_base;
1523 
1524 	req.cmd = &cmd;
1525 	req.rsp = &rsp;
1526 	ns.gen = 1;
1527 	ns.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE;
1528 	ns.ptpl_activated = true;
1529 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1530 	cmd.nvme_cmd.cdw10 = 100;
1531 	reg[0].rkey = 0xa;
1532 	reg[1].rkey = 0xb;
1533 	spdk_uuid_generate(&reg[0].hostid);
1534 	spdk_uuid_generate(&reg[1].hostid);
1535 	TAILQ_INIT(&ns.registrants);
1536 	TAILQ_INSERT_TAIL(&ns.registrants, &reg[0], link);
1537 	TAILQ_INSERT_TAIL(&ns.registrants, &reg[1], link);
1538 
1539 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1540 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1541 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS);
1542 	/* Get ctrlr data and status data pointers */
1543 	ctrlr_data = (void *)((char *)req.iov[0].iov_base + sizeof(*status_data));
1544 	status_data = (void *)req.iov[0].iov_base;
1545 	SPDK_CU_ASSERT_FATAL(status_data != NULL && ctrlr_data != NULL);
1546 	CU_ASSERT(status_data->data.gen == 1);
1547 	CU_ASSERT(status_data->data.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1548 	CU_ASSERT(status_data->data.ptpls == true);
1549 	CU_ASSERT(status_data->data.regctl == 2);
1550 	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1551 	CU_ASSERT(ctrlr_data->rcsts.status == false);
1552 	CU_ASSERT(ctrlr_data->rkey ==  0xa);
1553 	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[0].hostid));
1554 	/* Check second ctrlr data */
1555 	ctrlr_data++;
1556 	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1557 	CU_ASSERT(ctrlr_data->rcsts.status == false);
1558 	CU_ASSERT(ctrlr_data->rkey ==  0xb);
1559 	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[1].hostid));
1560 
1561 	/* extended controller data structure */
1562 	spdk_iov_memset(req.iov, req.iovcnt, 0);
1563 	memset(req.rsp, 0, sizeof(*req.rsp));
1564 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = false;
1565 
1566 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1567 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT);
1568 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1569 
1570 	/* Transfer length invalid */
1571 	spdk_iov_memset(req.iov, req.iovcnt, 0);
1572 	memset(req.rsp, 0, sizeof(*req.rsp));
1573 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1574 	cmd.nvme_cmd.cdw10 = 0;
1575 
1576 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1577 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INTERNAL_DEVICE_ERROR);
1578 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1579 
1580 	free(req.iov[0].iov_base);
1581 	free(reg);
1582 }
1583 
1584 static void
1585 test_nvmf_valid_nqn(void)
1586 {
1587 	bool rc;
1588 	char uuid[SPDK_NVMF_UUID_STRING_LEN + 1] = {};
1589 	char nqn[SPDK_NVMF_NQN_MAX_LEN + 1] = {};
1590 	struct spdk_uuid s_uuid = {};
1591 
1592 	spdk_uuid_generate(&s_uuid);
1593 	spdk_uuid_fmt_lower(uuid, sizeof(uuid), &s_uuid);
1594 
1595 	/* discovery nqn */
1596 	snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
1597 
1598 	rc = nvmf_valid_nqn(nqn);
1599 	CU_ASSERT(rc == true);
1600 
1601 	/* nqn with uuid */
1602 	memset(nqn, 0xff, sizeof(nqn));
1603 	snprintf(nqn, sizeof(nqn), "%s%s", SPDK_NVMF_NQN_UUID_PRE, uuid);
1604 
1605 	rc = nvmf_valid_nqn(nqn);
1606 	CU_ASSERT(rc == true);
1607 
1608 	/* Check nqn valid reverse domain */
1609 	memset(nqn, 0xff, sizeof(nqn));
1610 	snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io.spdk:cnode1");
1611 
1612 	rc = nvmf_valid_nqn(nqn);
1613 	CU_ASSERT(rc == true);
1614 
1615 	/* Invalid nqn length */
1616 	memset(nqn, 0xff, sizeof(nqn));
1617 	snprintf(nqn, sizeof(nqn), "%s", "nqn.");
1618 
1619 	rc = nvmf_valid_nqn(nqn);
1620 	CU_ASSERT(rc == false);
1621 
1622 	/* Copy uuid to the nqn string, but omit the last character to make it invalid */
1623 	memset(nqn, 0, SPDK_NVMF_NQN_MAX_LEN + 1);
1624 	snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_NQN_UUID_PRE);
1625 	memcpy(&nqn[SPDK_NVMF_NQN_UUID_PRE_LEN], uuid, SPDK_NVMF_UUID_STRING_LEN - 1);
1626 
1627 	rc = nvmf_valid_nqn(nqn);
1628 	CU_ASSERT(rc == false);
1629 
1630 	/* Invalid domain */
1631 	memset(nqn, 0xff, SPDK_NVMF_NQN_MAX_LEN + 1);
1632 	snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io...spdk:cnode1");
1633 
1634 	rc = nvmf_valid_nqn(nqn);
1635 	CU_ASSERT(rc == false);
1636 }
1637 
1638 static void
1639 test_nvmf_ns_reservation_restore(void)
1640 {
1641 	struct spdk_nvmf_ns ns = {};
1642 	struct spdk_nvmf_reservation_info info = {};
1643 	struct spdk_bdev bdev = {};
1644 	struct spdk_uuid s_uuid = {};
1645 	struct spdk_nvmf_registrant *reg0, *reg1;
1646 	char uuid[SPDK_UUID_STRING_LEN] = {};
1647 	int rc;
1648 
1649 	ns.bdev = &bdev;
1650 	TAILQ_INIT(&ns.registrants);
1651 	info.ptpl_activated = true;
1652 	info.num_regs = 2;
1653 	info.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS;
1654 	info.registrants[0].rkey = 0xb;
1655 	info.registrants[1].rkey = 0xc;
1656 
1657 	/* Generate and prepare uuids, make sure bdev and info uuid are the same */
1658 	spdk_uuid_generate(&s_uuid);
1659 	spdk_uuid_fmt_lower(uuid, sizeof(uuid), &s_uuid);
1660 	snprintf(info.holder_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1661 	snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1662 	snprintf(info.registrants[0].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1663 	spdk_uuid_copy(&bdev.uuid, &s_uuid);
1664 	spdk_uuid_generate(&s_uuid);
1665 	spdk_uuid_fmt_lower(uuid, sizeof(uuid), &s_uuid);
1666 	snprintf(info.registrants[1].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1667 
1668 	/* info->rkey not exist in registrants */
1669 	info.crkey = 0xa;
1670 
1671 	rc = nvmf_ns_reservation_restore(&ns, &info);
1672 	CU_ASSERT(rc == -EINVAL);
1673 
1674 	/* info->rkey exists in registrants */
1675 	info.crkey = 0xb;
1676 
1677 	rc = nvmf_ns_reservation_restore(&ns, &info);
1678 	CU_ASSERT(rc == 0);
1679 	CU_ASSERT(ns.crkey == 0xb);
1680 	CU_ASSERT(ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1681 	CU_ASSERT(ns.ptpl_activated == true);
1682 	/* Check two registrant`s rkey */
1683 	reg0 = TAILQ_FIRST(&ns.registrants);
1684 	reg1 = TAILQ_NEXT(reg0, link);
1685 	CU_ASSERT(ns.holder == reg0);
1686 	CU_ASSERT(reg0->rkey = 0xb);
1687 	CU_ASSERT(reg1->rkey = 0xc);
1688 
1689 	rc = nvmf_ns_reservation_clear_all_registrants(&ns);
1690 	CU_ASSERT(rc == 2);
1691 	CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
1692 
1693 	/* Existing bdev UUID is different with configuration */
1694 	spdk_uuid_generate(&s_uuid);
1695 	spdk_uuid_fmt_lower(uuid, sizeof(uuid), &s_uuid);
1696 	snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1697 	spdk_uuid_generate(&s_uuid);
1698 	spdk_uuid_copy(&bdev.uuid, &s_uuid);
1699 
1700 	rc = nvmf_ns_reservation_restore(&ns, &info);
1701 	CU_ASSERT(rc == -EINVAL);
1702 }
1703 
1704 static void
1705 test_nvmf_subsystem_state_change(void)
1706 {
1707 	struct spdk_nvmf_tgt tgt = {};
1708 	struct spdk_nvmf_subsystem *subsystem, *discovery_subsystem;
1709 	int rc;
1710 
1711 	tgt.max_subsystems = 1024;
1712 	tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
1713 	RB_INIT(&tgt.subsystems);
1714 
1715 	discovery_subsystem = spdk_nvmf_subsystem_create(&tgt, SPDK_NVMF_DISCOVERY_NQN,
1716 			      SPDK_NVMF_SUBTYPE_DISCOVERY, 0);
1717 	SPDK_CU_ASSERT_FATAL(discovery_subsystem != NULL);
1718 	subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
1719 					       SPDK_NVMF_SUBTYPE_NVME, 0);
1720 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1721 
1722 	spdk_io_device_register(&tgt,
1723 				nvmf_tgt_create_poll_group,
1724 				nvmf_tgt_destroy_poll_group,
1725 				sizeof(struct spdk_nvmf_poll_group),
1726 				NULL);
1727 
1728 	rc = spdk_nvmf_subsystem_start(discovery_subsystem, NULL, NULL);
1729 	CU_ASSERT(rc == 0);
1730 	poll_threads();
1731 	CU_ASSERT(discovery_subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVE);
1732 	rc = spdk_nvmf_subsystem_start(subsystem, NULL, NULL);
1733 	CU_ASSERT(rc == 0);
1734 	poll_threads();
1735 	CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVE);
1736 
1737 	rc = spdk_nvmf_subsystem_pause(subsystem, SPDK_NVME_GLOBAL_NS_TAG, NULL, NULL);
1738 	CU_ASSERT(rc == 0);
1739 	rc = spdk_nvmf_subsystem_stop(subsystem, NULL, NULL);
1740 	CU_ASSERT(rc == -EBUSY);
1741 	poll_threads();
1742 	CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED);
1743 
1744 	rc = spdk_nvmf_subsystem_stop(discovery_subsystem, NULL, NULL);
1745 	CU_ASSERT(rc == 0);
1746 	poll_threads();
1747 	CU_ASSERT(discovery_subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
1748 	rc = spdk_nvmf_subsystem_stop(subsystem, NULL, NULL);
1749 	CU_ASSERT(rc == 0);
1750 	poll_threads();
1751 	CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
1752 
1753 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
1754 	CU_ASSERT(rc == 0);
1755 	rc = spdk_nvmf_subsystem_destroy(discovery_subsystem, NULL, NULL);
1756 	CU_ASSERT(rc == 0);
1757 
1758 	spdk_io_device_unregister(&tgt, NULL);
1759 	poll_threads();
1760 
1761 	spdk_bit_array_free(&tgt.subsystem_ids);
1762 }
1763 
1764 int
1765 main(int argc, char **argv)
1766 {
1767 	CU_pSuite	suite = NULL;
1768 	unsigned int	num_failures;
1769 
1770 	CU_set_error_action(CUEA_ABORT);
1771 	CU_initialize_registry();
1772 
1773 	suite = CU_add_suite("nvmf", NULL, NULL);
1774 
1775 	CU_ADD_TEST(suite, nvmf_test_create_subsystem);
1776 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns);
1777 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn);
1778 	CU_ADD_TEST(suite, test_reservation_register);
1779 	CU_ADD_TEST(suite, test_reservation_register_with_ptpl);
1780 	CU_ADD_TEST(suite, test_reservation_acquire_preempt_1);
1781 	CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl);
1782 	CU_ADD_TEST(suite, test_reservation_release);
1783 	CU_ADD_TEST(suite, test_reservation_unregister_notification);
1784 	CU_ADD_TEST(suite, test_reservation_release_notification);
1785 	CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive);
1786 	CU_ADD_TEST(suite, test_reservation_clear_notification);
1787 	CU_ADD_TEST(suite, test_reservation_preempt_notification);
1788 	CU_ADD_TEST(suite, test_spdk_nvmf_ns_event);
1789 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_add_remove_registrant);
1790 	CU_ADD_TEST(suite, test_nvmf_subsystem_add_ctrlr);
1791 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_host);
1792 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_report);
1793 	CU_ADD_TEST(suite, test_nvmf_valid_nqn);
1794 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_restore);
1795 	CU_ADD_TEST(suite, test_nvmf_subsystem_state_change);
1796 
1797 	allocate_threads(1);
1798 	set_thread(0);
1799 
1800 	CU_basic_set_mode(CU_BRM_VERBOSE);
1801 	CU_basic_run_tests();
1802 	num_failures = CU_get_number_of_failures();
1803 	CU_cleanup_registry();
1804 
1805 	free_threads();
1806 
1807 	return num_failures;
1808 }
1809