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