xref: /spdk/test/unit/lib/nvmf/subsystem.c/subsystem_ut.c (revision eb7506a1b4fb1589911dbb1ffb5ac60a048202be)
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 #include <uuid/uuid.h>
15 
16 SPDK_LOG_REGISTER_COMPONENT(nvmf)
17 
18 DEFINE_STUB(spdk_bdev_module_claim_bdev,
19 	    int,
20 	    (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
21 	     struct spdk_bdev_module *module), 0);
22 
23 DEFINE_STUB_V(spdk_bdev_module_release_bdev,
24 	      (struct spdk_bdev *bdev));
25 
26 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
27 	    (const struct spdk_bdev *bdev), 512);
28 
29 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
30 	    (const struct spdk_bdev *bdev), 0);
31 
32 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
33 	    (const struct spdk_bdev *bdev), false);
34 
35 DEFINE_STUB(spdk_bdev_io_type_supported, bool,
36 	    (struct spdk_bdev *bdev,
37 	     enum spdk_bdev_io_type io_type), false);
38 
39 DEFINE_STUB(spdk_nvmf_transport_stop_listen,
40 	    int,
41 	    (struct spdk_nvmf_transport *transport,
42 	     const struct spdk_nvme_transport_id *trid), 0);
43 
44 DEFINE_STUB_V(nvmf_update_discovery_log,
45 	      (struct spdk_nvmf_tgt *tgt, const char *hostnqn));
46 
47 DEFINE_STUB(spdk_nvmf_qpair_disconnect,
48 	    int,
49 	    (struct spdk_nvmf_qpair *qpair,
50 	     nvmf_qpair_disconnect_cb cb_fn, void *ctx), 0);
51 
52 DEFINE_STUB(nvmf_transport_find_listener,
53 	    struct spdk_nvmf_listener *,
54 	    (struct spdk_nvmf_transport *transport,
55 	     const struct spdk_nvme_transport_id *trid), NULL);
56 
57 DEFINE_STUB(spdk_nvmf_transport_get_first,
58 	    struct spdk_nvmf_transport *,
59 	    (struct spdk_nvmf_tgt *tgt), NULL);
60 
61 DEFINE_STUB(spdk_nvmf_transport_get_next,
62 	    struct spdk_nvmf_transport *,
63 	    (struct spdk_nvmf_transport *transport), NULL);
64 
65 DEFINE_STUB(spdk_nvmf_request_complete,
66 	    int,
67 	    (struct spdk_nvmf_request *req), 0);
68 
69 DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice,
70 	    int,
71 	    (struct spdk_nvmf_ctrlr *ctrlr), 0);
72 
73 DEFINE_STUB(spdk_nvme_transport_id_trtype_str,
74 	    const char *,
75 	    (enum spdk_nvme_transport_type trtype), NULL);
76 
77 DEFINE_STUB(spdk_bdev_is_zoned, bool,
78 	    (const struct spdk_bdev *bdev), false);
79 
80 DEFINE_STUB(spdk_bdev_get_max_zone_append_size, uint32_t,
81 	    (const struct spdk_bdev *bdev), 0);
82 
83 int
84 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
85 			   const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts)
86 {
87 	return 0;
88 }
89 
90 void
91 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
92 				 struct spdk_nvme_transport_id *trid,
93 				 struct spdk_nvmf_discovery_log_page_entry *entry)
94 {
95 	entry->trtype = 42;
96 }
97 
98 static struct spdk_nvmf_transport g_transport = {};
99 
100 struct spdk_nvmf_transport *
101 spdk_nvmf_transport_create(const char *transport_name,
102 			   struct spdk_nvmf_transport_opts *tprt_opts)
103 {
104 	if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) {
105 		return &g_transport;
106 	}
107 
108 	return NULL;
109 }
110 
111 struct spdk_nvmf_subsystem *
112 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
113 {
114 	return NULL;
115 }
116 
117 struct spdk_nvmf_transport *
118 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
119 {
120 	if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) {
121 		return &g_transport;
122 	}
123 
124 	return NULL;
125 }
126 
127 int
128 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
129 				 struct spdk_nvmf_subsystem *subsystem)
130 {
131 	return 0;
132 }
133 
134 int
135 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
136 			      struct spdk_nvmf_subsystem *subsystem,
137 			      spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
138 {
139 	return 0;
140 }
141 
142 void
143 nvmf_poll_group_remove_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 }
148 
149 void
150 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
151 				struct spdk_nvmf_subsystem *subsystem,
152 				uint32_t nsid,
153 				spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
154 {
155 }
156 
157 void
158 nvmf_poll_group_resume_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 int
165 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
166 {
167 	if (trtype == NULL || str == NULL) {
168 		return -EINVAL;
169 	}
170 
171 	if (strcasecmp(str, "PCIe") == 0) {
172 		*trtype = SPDK_NVME_TRANSPORT_PCIE;
173 	} else if (strcasecmp(str, "RDMA") == 0) {
174 		*trtype = SPDK_NVME_TRANSPORT_RDMA;
175 	} else {
176 		return -ENOENT;
177 	}
178 	return 0;
179 }
180 
181 int
182 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
183 			       const struct spdk_nvme_transport_id *trid2)
184 {
185 	return 0;
186 }
187 
188 int32_t
189 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr)
190 {
191 	return -1;
192 }
193 
194 int32_t
195 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
196 {
197 	return -1;
198 }
199 
200 int
201 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
202 {
203 	return -1;
204 }
205 
206 void
207 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
208 {
209 }
210 
211 static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL;
212 static uint32_t g_ns_changed_nsid = 0;
213 void
214 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
215 {
216 	g_ns_changed_ctrlr = ctrlr;
217 	g_ns_changed_nsid = nsid;
218 }
219 
220 static struct spdk_bdev g_bdevs[] = {
221 	{ .name = "bdev1" },
222 	{ .name = "bdev2" },
223 };
224 
225 struct spdk_bdev_desc {
226 	struct spdk_bdev	*bdev;
227 };
228 
229 int
230 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
231 		   void *event_ctx, struct spdk_bdev_desc **_desc)
232 {
233 	struct spdk_bdev_desc *desc;
234 	size_t i;
235 
236 	for (i = 0; i < sizeof(g_bdevs); i++) {
237 		if (strcmp(bdev_name, g_bdevs[i].name) == 0) {
238 
239 			desc = calloc(1, sizeof(*desc));
240 			SPDK_CU_ASSERT_FATAL(desc != NULL);
241 
242 			desc->bdev = &g_bdevs[i];
243 			*_desc = desc;
244 			return 0;
245 		}
246 	}
247 
248 	return -EINVAL;
249 }
250 
251 void
252 spdk_bdev_close(struct spdk_bdev_desc *desc)
253 {
254 	free(desc);
255 }
256 
257 struct spdk_bdev *
258 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
259 {
260 	return desc->bdev;
261 }
262 
263 const char *
264 spdk_bdev_get_name(const struct spdk_bdev *bdev)
265 {
266 	return "test";
267 }
268 
269 const struct spdk_uuid *
270 spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
271 {
272 	return &bdev->uuid;
273 }
274 
275 static void
276 test_spdk_nvmf_subsystem_add_ns(void)
277 {
278 	struct spdk_nvmf_tgt tgt = {};
279 	struct spdk_nvmf_subsystem subsystem = {
280 		.max_nsid = 1024,
281 		.ns = NULL,
282 		.tgt = &tgt,
283 	};
284 	struct spdk_nvmf_ns_opts ns_opts;
285 	uint32_t nsid;
286 	int rc;
287 
288 	subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
289 	SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
290 	subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
291 	SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
292 
293 	tgt.max_subsystems = 1024;
294 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
295 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
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 	free(tgt.subsystems);
326 }
327 
328 static void
329 nvmf_test_create_subsystem(void)
330 {
331 	struct spdk_nvmf_tgt tgt = {};
332 	char nqn[256];
333 	struct spdk_nvmf_subsystem *subsystem;
334 	int rc;
335 
336 	tgt.max_subsystems = 1024;
337 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
338 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
339 
340 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
341 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
342 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
343 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
344 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
345 	CU_ASSERT(rc == 0);
346 
347 	/* valid name with complex reverse domain */
348 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1");
349 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
350 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
351 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
352 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
353 	CU_ASSERT(rc == 0);
354 
355 	/* Valid name discovery controller */
356 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
357 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
358 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
359 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
360 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
361 	CU_ASSERT(rc == 0);
362 
363 	/* Invalid name, no user supplied string */
364 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
365 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
366 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
367 
368 	/* Valid name, only contains top-level domain name */
369 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
370 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
371 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
372 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
373 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
374 	CU_ASSERT(rc == 0);
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 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
411 	CU_ASSERT(rc == 0);
412 
413 	/* Invalid name, too long */
414 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
415 	memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn));
416 	nqn[224] = '\0';
417 	CU_ASSERT(strlen(nqn) == 224);
418 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
419 	CU_ASSERT(subsystem == NULL);
420 
421 	/* Valid name using uuid format */
422 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc");
423 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
424 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
425 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
426 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
427 	CU_ASSERT(rc == 0);
428 
429 	/* Invalid name user string contains an invalid utf-8 character */
430 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1");
431 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
432 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
433 
434 	/* Valid name with non-ascii but valid utf-8 characters */
435 	snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80");
436 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
437 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
438 	CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
439 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
440 	CU_ASSERT(rc == 0);
441 
442 	/* Invalid uuid (too long) */
443 	snprintf(nqn, sizeof(nqn),
444 		 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef");
445 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
446 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
447 
448 	/* Invalid uuid (dashes placed incorrectly) */
449 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc");
450 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
451 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
452 
453 	/* Invalid uuid (invalid characters in uuid) */
454 	snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc");
455 	subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
456 	SPDK_CU_ASSERT_FATAL(subsystem == NULL);
457 
458 	free(tgt.subsystems);
459 }
460 
461 static void
462 test_spdk_nvmf_subsystem_set_sn(void)
463 {
464 	struct spdk_nvmf_subsystem subsystem = {};
465 
466 	/* Basic valid serial number */
467 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0);
468 	CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0);
469 
470 	/* Exactly 20 characters (valid) */
471 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0);
472 	CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0);
473 
474 	/* 21 characters (too long, invalid) */
475 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0);
476 
477 	/* Non-ASCII characters (invalid) */
478 	CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0);
479 }
480 
481 /*
482  * Reservation Unit Test Configuration
483  *       --------             --------    --------
484  *      | Host A |           | Host B |  | Host C |
485  *       --------             --------    --------
486  *      /        \               |           |
487  *  --------   --------       -------     -------
488  * |Ctrlr1_A| |Ctrlr2_A|     |Ctrlr_B|   |Ctrlr_C|
489  *  --------   --------       -------     -------
490  *    \           \              /           /
491  *     \           \            /           /
492  *      \           \          /           /
493  *      --------------------------------------
494  *     |            NAMESPACE 1               |
495  *      --------------------------------------
496  */
497 static struct spdk_nvmf_subsystem g_subsystem;
498 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C;
499 static struct spdk_nvmf_ns g_ns;
500 static struct spdk_bdev g_bdev;
501 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info;
502 
503 void
504 nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr)
505 {
506 }
507 
508 static void
509 ut_reservation_init(void)
510 {
511 
512 	TAILQ_INIT(&g_subsystem.ctrlrs);
513 
514 	memset(&g_ns, 0, sizeof(g_ns));
515 	TAILQ_INIT(&g_ns.registrants);
516 	g_ns.subsystem = &g_subsystem;
517 	g_ns.ptpl_file = NULL;
518 	g_ns.ptpl_activated = false;
519 	spdk_uuid_generate(&g_bdev.uuid);
520 	g_ns.bdev = &g_bdev;
521 
522 	/* Host A has two controllers */
523 	spdk_uuid_generate(&g_ctrlr1_A.hostid);
524 	TAILQ_INIT(&g_ctrlr1_A.log_head);
525 	g_ctrlr1_A.subsys = &g_subsystem;
526 	g_ctrlr1_A.num_avail_log_pages = 0;
527 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link);
528 	spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid);
529 	TAILQ_INIT(&g_ctrlr2_A.log_head);
530 	g_ctrlr2_A.subsys = &g_subsystem;
531 	g_ctrlr2_A.num_avail_log_pages = 0;
532 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link);
533 
534 	/* Host B has 1 controller */
535 	spdk_uuid_generate(&g_ctrlr_B.hostid);
536 	TAILQ_INIT(&g_ctrlr_B.log_head);
537 	g_ctrlr_B.subsys = &g_subsystem;
538 	g_ctrlr_B.num_avail_log_pages = 0;
539 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link);
540 
541 	/* Host C has 1 controller */
542 	spdk_uuid_generate(&g_ctrlr_C.hostid);
543 	TAILQ_INIT(&g_ctrlr_C.log_head);
544 	g_ctrlr_C.subsys = &g_subsystem;
545 	g_ctrlr_C.num_avail_log_pages = 0;
546 	TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link);
547 }
548 
549 static void
550 ut_reservation_deinit(void)
551 {
552 	struct spdk_nvmf_registrant *reg, *tmp;
553 	struct spdk_nvmf_reservation_log *log, *log_tmp;
554 	struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
555 
556 	TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) {
557 		TAILQ_REMOVE(&g_ns.registrants, reg, link);
558 		free(reg);
559 	}
560 	TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) {
561 		TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link);
562 		free(log);
563 	}
564 	g_ctrlr1_A.num_avail_log_pages = 0;
565 	TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) {
566 		TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link);
567 		free(log);
568 	}
569 	g_ctrlr2_A.num_avail_log_pages = 0;
570 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) {
571 		TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link);
572 		free(log);
573 	}
574 	g_ctrlr_B.num_avail_log_pages = 0;
575 	TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) {
576 		TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link);
577 		free(log);
578 	}
579 	g_ctrlr_C.num_avail_log_pages = 0;
580 
581 	TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) {
582 		TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link);
583 	}
584 }
585 
586 static struct spdk_nvmf_request *
587 ut_reservation_build_req(uint32_t length)
588 {
589 	struct spdk_nvmf_request *req;
590 
591 	req = calloc(1, sizeof(*req));
592 	assert(req != NULL);
593 
594 	req->data = calloc(1, length);
595 	assert(req->data != NULL);
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->data);
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->data, &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->data, &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->data, &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.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1349 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
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 	free(tgt.subsystems);
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.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1446 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
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 	free(tgt.subsystems);
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.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1477 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
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 	free(tgt.subsystems);
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 
1515 	req.data = calloc(1, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1516 	reg = calloc(2, sizeof(struct spdk_nvmf_registrant));
1517 	SPDK_CU_ASSERT_FATAL(req.data != NULL && reg != NULL);
1518 
1519 	req.cmd = &cmd;
1520 	req.rsp = &rsp;
1521 	ns.gen = 1;
1522 	ns.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE;
1523 	ns.ptpl_activated = true;
1524 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1525 	cmd.nvme_cmd.cdw10 = 100;
1526 	reg[0].rkey = 0xa;
1527 	reg[1].rkey = 0xb;
1528 	spdk_uuid_generate(&reg[0].hostid);
1529 	spdk_uuid_generate(&reg[1].hostid);
1530 	TAILQ_INIT(&ns.registrants);
1531 	TAILQ_INSERT_TAIL(&ns.registrants, &reg[0], link);
1532 	TAILQ_INSERT_TAIL(&ns.registrants, &reg[1], link);
1533 
1534 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1535 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1536 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS);
1537 	/* Get ctrlr data and status data pointers */
1538 	ctrlr_data = (void *)((uint64_t)req.data + sizeof(*status_data));
1539 	status_data = (void *)req.data;
1540 	SPDK_CU_ASSERT_FATAL(status_data != NULL && ctrlr_data != NULL);
1541 	CU_ASSERT(status_data->data.gen == 1);
1542 	CU_ASSERT(status_data->data.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1543 	CU_ASSERT(status_data->data.ptpls == true);
1544 	CU_ASSERT(status_data->data.regctl == 2);
1545 	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1546 	CU_ASSERT(ctrlr_data->rcsts.status == false);
1547 	CU_ASSERT(ctrlr_data->rkey ==  0xa);
1548 	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[0].hostid));
1549 	/* Check second ctrlr data */
1550 	ctrlr_data++;
1551 	CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1552 	CU_ASSERT(ctrlr_data->rcsts.status == false);
1553 	CU_ASSERT(ctrlr_data->rkey ==  0xb);
1554 	CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, &reg[1].hostid));
1555 
1556 	/* extended controller data structure */
1557 	memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1558 	memset(req.rsp, 0, sizeof(*req.rsp));
1559 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = false;
1560 
1561 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1562 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT);
1563 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1564 
1565 	/* Transfer length invalid */
1566 	memset(req.data, 0, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1567 	memset(req.rsp, 0, sizeof(*req.rsp));
1568 	cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1569 	cmd.nvme_cmd.cdw10 = 0;
1570 
1571 	nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1572 	CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INTERNAL_DEVICE_ERROR);
1573 	CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1574 
1575 	free(req.data);
1576 	free(reg);
1577 }
1578 
1579 static void
1580 test_nvmf_valid_nqn(void)
1581 {
1582 	bool rc;
1583 	char uuid[SPDK_NVMF_UUID_STRING_LEN + 1] = {};
1584 	char nqn[SPDK_NVMF_NQN_MAX_LEN + 1] = {};
1585 	struct spdk_uuid s_uuid = {};
1586 
1587 	spdk_uuid_generate(&s_uuid);
1588 	uuid_unparse((void *)&s_uuid, uuid);
1589 
1590 	/* discovery nqn */
1591 	snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
1592 
1593 	rc = nvmf_valid_nqn(nqn);
1594 	CU_ASSERT(rc == true);
1595 
1596 	/* nqn with uuid */
1597 	memset(nqn, 0xff, sizeof(nqn));
1598 	snprintf(nqn, sizeof(nqn), "%s%s", SPDK_NVMF_NQN_UUID_PRE, uuid);
1599 
1600 	rc = nvmf_valid_nqn(nqn);
1601 	CU_ASSERT(rc == true);
1602 
1603 	/* Check nqn valid reverse domain */
1604 	memset(nqn, 0xff, sizeof(nqn));
1605 	snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io.spdk:cnode1");
1606 
1607 	rc = nvmf_valid_nqn(nqn);
1608 	CU_ASSERT(rc == true);
1609 
1610 	/* Invalid nqn length */
1611 	memset(nqn, 0xff, sizeof(nqn));
1612 	snprintf(nqn, sizeof(nqn), "%s", "nqn.");
1613 
1614 	rc = nvmf_valid_nqn(nqn);
1615 	CU_ASSERT(rc == false);
1616 
1617 	/* Copy uuid to the nqn string, but omit the last character to make it invalid */
1618 	memset(nqn, 0, SPDK_NVMF_NQN_MAX_LEN + 1);
1619 	snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_NQN_UUID_PRE);
1620 	memcpy(&nqn[SPDK_NVMF_NQN_UUID_PRE_LEN], uuid, SPDK_NVMF_UUID_STRING_LEN - 1);
1621 
1622 	rc = nvmf_valid_nqn(nqn);
1623 	CU_ASSERT(rc == false);
1624 
1625 	/* Invalid domain */
1626 	memset(nqn, 0xff, SPDK_NVMF_NQN_MAX_LEN + 1);
1627 	snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io...spdk:cnode1");
1628 
1629 	rc = nvmf_valid_nqn(nqn);
1630 	CU_ASSERT(rc == false);
1631 }
1632 
1633 static void
1634 test_nvmf_ns_reservation_restore(void)
1635 {
1636 	struct spdk_nvmf_ns ns = {};
1637 	struct spdk_nvmf_reservation_info info = {};
1638 	struct spdk_bdev bdev = {};
1639 	struct spdk_uuid s_uuid = {};
1640 	struct spdk_nvmf_registrant *reg0, *reg1;
1641 	char uuid[SPDK_UUID_STRING_LEN] = {};
1642 	int rc;
1643 
1644 	ns.bdev = &bdev;
1645 	TAILQ_INIT(&ns.registrants);
1646 	info.ptpl_activated = true;
1647 	info.num_regs = 2;
1648 	info.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS;
1649 	info.registrants[0].rkey = 0xb;
1650 	info.registrants[1].rkey = 0xc;
1651 
1652 	/* Generate and prepare uuids, make sure bdev and info uuid are the same */
1653 	spdk_uuid_generate(&s_uuid);
1654 	uuid_unparse((void *)&s_uuid, uuid);
1655 	snprintf(info.holder_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1656 	snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1657 	snprintf(info.registrants[0].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1658 	spdk_uuid_copy(&bdev.uuid, &s_uuid);
1659 	spdk_uuid_generate(&s_uuid);
1660 	uuid_unparse((void *)&s_uuid, uuid);
1661 	snprintf(info.registrants[1].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1662 
1663 	/* info->rkey not exist in registrants */
1664 	info.crkey = 0xa;
1665 
1666 	rc = nvmf_ns_reservation_restore(&ns, &info);
1667 	CU_ASSERT(rc == -EINVAL);
1668 
1669 	/* info->rkey exists in registrants */
1670 	info.crkey = 0xb;
1671 
1672 	rc = nvmf_ns_reservation_restore(&ns, &info);
1673 	CU_ASSERT(rc == 0);
1674 	CU_ASSERT(ns.crkey == 0xb);
1675 	CU_ASSERT(ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1676 	CU_ASSERT(ns.ptpl_activated == true);
1677 	/* Check two registrant`s rkey */
1678 	reg0 = TAILQ_FIRST(&ns.registrants);
1679 	reg1 = TAILQ_NEXT(reg0, link);
1680 	CU_ASSERT(ns.holder == reg0);
1681 	CU_ASSERT(reg0->rkey = 0xb);
1682 	CU_ASSERT(reg1->rkey = 0xc);
1683 
1684 	rc = nvmf_ns_reservation_clear_all_registrants(&ns);
1685 	CU_ASSERT(rc == 2);
1686 	CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
1687 
1688 	/* Existing bdev UUID is different with configuration */
1689 	spdk_uuid_generate(&s_uuid);
1690 	uuid_unparse((void *)&s_uuid, uuid);
1691 	snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1692 	spdk_uuid_generate(&s_uuid);
1693 	spdk_uuid_copy(&bdev.uuid, &s_uuid);
1694 
1695 	rc = nvmf_ns_reservation_restore(&ns, &info);
1696 	CU_ASSERT(rc == -EINVAL);
1697 }
1698 
1699 static void
1700 test_nvmf_subsystem_state_change(void)
1701 {
1702 	struct spdk_nvmf_tgt tgt = {};
1703 	struct spdk_nvmf_subsystem *subsystem, *discovery_subsystem;
1704 	int rc;
1705 
1706 	tgt.max_subsystems = 1024;
1707 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
1708 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
1709 
1710 	discovery_subsystem = spdk_nvmf_subsystem_create(&tgt, SPDK_NVMF_DISCOVERY_NQN,
1711 			      SPDK_NVMF_SUBTYPE_DISCOVERY, 0);
1712 	SPDK_CU_ASSERT_FATAL(discovery_subsystem != NULL);
1713 	subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
1714 					       SPDK_NVMF_SUBTYPE_NVME, 0);
1715 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1716 
1717 	spdk_io_device_register(&tgt,
1718 				nvmf_tgt_create_poll_group,
1719 				nvmf_tgt_destroy_poll_group,
1720 				sizeof(struct spdk_nvmf_poll_group),
1721 				NULL);
1722 
1723 	rc = spdk_nvmf_subsystem_start(discovery_subsystem, NULL, NULL);
1724 	CU_ASSERT(rc == 0);
1725 	poll_threads();
1726 	CU_ASSERT(discovery_subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVE);
1727 	rc = spdk_nvmf_subsystem_start(subsystem, NULL, NULL);
1728 	CU_ASSERT(rc == 0);
1729 	poll_threads();
1730 	CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVE);
1731 
1732 	rc = spdk_nvmf_subsystem_pause(subsystem, SPDK_NVME_GLOBAL_NS_TAG, NULL, NULL);
1733 	CU_ASSERT(rc == 0);
1734 	rc = spdk_nvmf_subsystem_stop(subsystem, NULL, NULL);
1735 	CU_ASSERT(rc == -EBUSY);
1736 	poll_threads();
1737 	CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_PAUSED);
1738 
1739 	rc = spdk_nvmf_subsystem_stop(discovery_subsystem, NULL, NULL);
1740 	CU_ASSERT(rc == 0);
1741 	poll_threads();
1742 	CU_ASSERT(discovery_subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
1743 	rc = spdk_nvmf_subsystem_stop(subsystem, NULL, NULL);
1744 	CU_ASSERT(rc == 0);
1745 	poll_threads();
1746 	CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
1747 
1748 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
1749 	CU_ASSERT(rc == 0);
1750 	rc = spdk_nvmf_subsystem_destroy(discovery_subsystem, NULL, NULL);
1751 	CU_ASSERT(rc == 0);
1752 
1753 	spdk_io_device_unregister(&tgt, NULL);
1754 	poll_threads();
1755 
1756 	free(tgt.subsystems);
1757 }
1758 
1759 int
1760 main(int argc, char **argv)
1761 {
1762 	CU_pSuite	suite = NULL;
1763 	unsigned int	num_failures;
1764 
1765 	CU_set_error_action(CUEA_ABORT);
1766 	CU_initialize_registry();
1767 
1768 	suite = CU_add_suite("nvmf", NULL, NULL);
1769 
1770 	CU_ADD_TEST(suite, nvmf_test_create_subsystem);
1771 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns);
1772 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn);
1773 	CU_ADD_TEST(suite, test_reservation_register);
1774 	CU_ADD_TEST(suite, test_reservation_register_with_ptpl);
1775 	CU_ADD_TEST(suite, test_reservation_acquire_preempt_1);
1776 	CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl);
1777 	CU_ADD_TEST(suite, test_reservation_release);
1778 	CU_ADD_TEST(suite, test_reservation_unregister_notification);
1779 	CU_ADD_TEST(suite, test_reservation_release_notification);
1780 	CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive);
1781 	CU_ADD_TEST(suite, test_reservation_clear_notification);
1782 	CU_ADD_TEST(suite, test_reservation_preempt_notification);
1783 	CU_ADD_TEST(suite, test_spdk_nvmf_ns_event);
1784 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_add_remove_registrant);
1785 	CU_ADD_TEST(suite, test_nvmf_subsystem_add_ctrlr);
1786 	CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_host);
1787 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_report);
1788 	CU_ADD_TEST(suite, test_nvmf_valid_nqn);
1789 	CU_ADD_TEST(suite, test_nvmf_ns_reservation_restore);
1790 	CU_ADD_TEST(suite, test_nvmf_subsystem_state_change);
1791 
1792 	allocate_threads(1);
1793 	set_thread(0);
1794 
1795 	CU_basic_set_mode(CU_BRM_VERBOSE);
1796 	CU_basic_run_tests();
1797 	num_failures = CU_get_number_of_failures();
1798 	CU_cleanup_registry();
1799 
1800 	free_threads();
1801 
1802 	return num_failures;
1803 }
1804