4 * Copyright (c) Intel Corporation. All rights reserved.
5 * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "spdk/stdinc.h"
36 #include "common/lib/ut_multithread.c"
37 #include "spdk_cunit.h"
38 #include "spdk_internal/mock.h"
39 #include "spdk_internal/thread.h"
41 #include "nvmf/subsystem.c"
43 SPDK_LOG_REGISTER_COMPONENT("nvmf", SPDK_LOG_NVMF
)
45 DEFINE_STUB(spdk_bdev_module_claim_bdev
,
47 (struct spdk_bdev
*bdev
, struct spdk_bdev_desc
*desc
,
48 struct spdk_bdev_module
*module
), 0);
50 DEFINE_STUB_V(spdk_bdev_module_release_bdev
,
51 (struct spdk_bdev
*bdev
));
53 DEFINE_STUB(spdk_bdev_get_block_size
, uint32_t,
54 (const struct spdk_bdev
*bdev
), 512);
56 DEFINE_STUB(spdk_bdev_get_md_size
, uint32_t,
57 (const struct spdk_bdev
*bdev
), 0);
59 DEFINE_STUB(spdk_bdev_is_md_interleaved
, bool,
60 (const struct spdk_bdev
*bdev
), false);
62 DEFINE_STUB(spdk_nvmf_transport_stop_listen
,
64 (struct spdk_nvmf_transport
*transport
,
65 const struct spdk_nvme_transport_id
*trid
), 0);
68 spdk_nvmf_transport_listen(struct spdk_nvmf_transport
*transport
,
69 const struct spdk_nvme_transport_id
*trid
)
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
)
82 static struct spdk_nvmf_transport g_transport
= {};
84 struct spdk_nvmf_transport
*
85 spdk_nvmf_transport_create(const char *transport_name
,
86 struct spdk_nvmf_transport_opts
*tprt_opts
)
88 if (strcasecmp(transport_name
, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA
))) {
95 struct spdk_nvmf_subsystem
*
96 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt
*tgt
, const char *subnqn
)
101 struct spdk_nvmf_transport
*
102 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt
*tgt
, const char *transport_name
)
104 if (strncmp(transport_name
, SPDK_NVME_TRANSPORT_NAME_RDMA
, SPDK_NVMF_TRSTRING_MAX_LEN
)) {
112 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group
*group
,
113 struct spdk_nvmf_subsystem
*subsystem
)
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
)
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
)
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
)
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
)
148 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type
*trtype
, const char *str
)
150 if (trtype
== NULL
|| str
== NULL
) {
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
;
165 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id
*trid1
,
166 const struct spdk_nvme_transport_id
*trid2
)
172 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr
*ctrlr
)
178 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair
*qpair
, uint32_t max_completions
)
184 spdk_nvme_detach(struct spdk_nvme_ctrlr
*ctrlr
)
190 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr
*ctrlr
)
194 static struct spdk_nvmf_ctrlr
*g_ns_changed_ctrlr
= NULL
;
195 static uint32_t g_ns_changed_nsid
= 0;
197 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr
*ctrlr
, uint32_t nsid
)
199 g_ns_changed_ctrlr
= ctrlr
;
200 g_ns_changed_nsid
= nsid
;
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
)
211 spdk_bdev_close(struct spdk_bdev_desc
*desc
)
216 spdk_bdev_get_name(const struct spdk_bdev
*bdev
)
221 const struct spdk_uuid
*
222 spdk_bdev_get_uuid(const struct spdk_bdev
*bdev
)
228 test_spdk_nvmf_subsystem_add_ns(void)
230 struct spdk_nvmf_tgt tgt
= {};
231 struct spdk_nvmf_subsystem subsystem
= {
236 struct spdk_bdev bdev1
= {}, bdev2
= {};
237 struct spdk_nvmf_ns_opts ns_opts
;
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
);
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
);
255 /* Request a specific NSID */
256 spdk_nvmf_ns_opts_get_defaults(&ns_opts
, sizeof(ns_opts
));
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
);
264 /* Request an NSID that is already in use */
265 spdk_nvmf_ns_opts_get_defaults(&ns_opts
, sizeof(ns_opts
));
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);
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);
278 rc
= spdk_nvmf_subsystem_remove_ns(&subsystem
, 1);
280 rc
= spdk_nvmf_subsystem_remove_ns(&subsystem
, 5);
284 free(tgt
.subsystems
);
288 nvmf_test_create_subsystem(void)
290 struct spdk_nvmf_tgt tgt
= {};
292 struct spdk_nvmf_subsystem
*subsystem
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
357 /* Longest valid name */
358 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:");
359 memset(nqn
+ strlen(nqn
), 'a', 223 - strlen(nqn
));
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
);
367 /* Invalid name, too long */
368 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:");
369 memset(nqn
+ strlen(nqn
), 'a', 224 - strlen(nqn
));
371 CU_ASSERT(strlen(nqn
) == 224);
372 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
373 CU_ASSERT(subsystem
== NULL
);
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
);
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
);
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
);
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
);
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
);
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
);
410 free(tgt
.subsystems
);
414 test_spdk_nvmf_subsystem_set_sn(void)
416 struct spdk_nvmf_subsystem subsystem
= {};
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);
422 /* Exactly 20 characters (valid) */
423 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem
, "12345678901234567890") == 0);
424 CU_ASSERT(strcmp(subsystem
.sn
, "12345678901234567890") == 0);
426 /* 21 characters (too long, invalid) */
427 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem
, "123456789012345678901") < 0);
429 /* Non-ASCII characters (invalid) */
430 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem
, "abcd\txyz") < 0);
434 * Reservation Unit Test Configuration
435 * -------- -------- --------
436 * | Host A | | Host B | | Host C |
437 * -------- -------- --------
439 * -------- -------- ------- -------
440 * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C|
441 * -------- -------- ------- -------
445 * --------------------------------------
447 * --------------------------------------
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
;
456 nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr
*ctrlr
)
461 ut_reservation_init(void)
464 TAILQ_INIT(&g_subsystem
.ctrlrs
);
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
);
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
);
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
);
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
);
502 ut_reservation_deinit(void)
504 struct spdk_nvmf_registrant
*reg
, *tmp
;
505 struct spdk_nvmf_reservation_log
*log
, *log_tmp
;
506 struct spdk_nvmf_ctrlr
*ctrlr
, *ctrlr_tmp
;
508 TAILQ_FOREACH_SAFE(reg
, &g_ns
.registrants
, link
, tmp
) {
509 TAILQ_REMOVE(&g_ns
.registrants
, reg
, link
);
512 TAILQ_FOREACH_SAFE(log
, &g_ctrlr1_A
.log_head
, link
, log_tmp
) {
513 TAILQ_REMOVE(&g_ctrlr1_A
.log_head
, log
, link
);
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
);
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
);
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
);
531 g_ctrlr_C
.num_avail_log_pages
= 0;
533 TAILQ_FOREACH_SAFE(ctrlr
, &g_subsystem
.ctrlrs
, link
, ctrlr_tmp
) {
534 TAILQ_REMOVE(&g_subsystem
.ctrlrs
, ctrlr
, link
);
538 static struct spdk_nvmf_request
*
539 ut_reservation_build_req(uint32_t length
)
541 struct spdk_nvmf_request
*req
;
543 req
= calloc(1, sizeof(*req
));
546 req
->data
= calloc(1, length
);
547 assert(req
->data
!= NULL
);
548 req
->length
= length
;
550 req
->cmd
= (union nvmf_h2c_msg
*)calloc(1, sizeof(union nvmf_h2c_msg
));
551 assert(req
->cmd
!= NULL
);
553 req
->rsp
= (union nvmf_c2h_msg
*)calloc(1, sizeof(union nvmf_c2h_msg
));
554 assert(req
->rsp
!= NULL
);
560 ut_reservation_free_req(struct spdk_nvmf_request
*req
)
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
,
574 struct spdk_nvme_reservation_register_data key
;
575 struct spdk_nvme_cmd
*cmd
= &req
->cmd
->nvme_cmd
;
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
));
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
,
592 struct spdk_nvme_reservation_acquire_data key
;
593 struct spdk_nvme_cmd
*cmd
= &req
->cmd
->nvme_cmd
;
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
));
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
)
609 struct spdk_nvme_cmd
*cmd
= &req
->cmd
->nvme_cmd
;
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
));
619 * Construct four registrants for other test cases.
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.
627 ut_reservation_build_registrants(void)
629 struct spdk_nvmf_request
*req
;
630 struct spdk_nvme_cpl
*rsp
;
631 struct spdk_nvmf_registrant
*reg
;
634 req
= ut_reservation_build_req(16);
635 rsp
= &req
->rsp
->nvme_cpl
;
636 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
639 /* TEST CASE: g_ctrlr1_A register with a new key */
640 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REGISTER_KEY
,
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);
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.
651 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REGISTER_KEY
,
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
);
657 /* g_ctrlr_B register with a new key */
658 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REGISTER_KEY
,
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);
666 /* g_ctrlr_C register with a new key */
667 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REGISTER_KEY
,
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);
675 ut_reservation_free_req(req
);
679 test_reservation_register(void)
681 struct spdk_nvmf_request
*req
;
682 struct spdk_nvme_cpl
*rsp
;
683 struct spdk_nvmf_registrant
*reg
;
686 ut_reservation_init();
688 req
= ut_reservation_build_req(16);
689 rsp
= &req
->rsp
->nvme_cpl
;
690 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
692 ut_reservation_build_registrants();
694 /* TEST CASE: Replace g_ctrlr1_A with a new key */
695 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REPLACE_KEY
,
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);
702 /* TEST CASE: Host A with g_ctrlr1_A get reservation with
703 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
705 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_ACQUIRE
, 0,
706 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
, 0xa11, 0x0);
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
);
716 /* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
717 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_UNREGISTER_KEY
,
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
);
724 /* TEST CASE: g_ctrlr_B unregister with correct key */
725 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_UNREGISTER_KEY
,
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
);
732 /* TEST CASE: g_ctrlr1_A unregister with correct key,
733 * reservation should be removed as well.
735 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_UNREGISTER_KEY
,
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
);
745 ut_reservation_free_req(req
);
746 ut_reservation_deinit();
750 test_reservation_register_with_ptpl(void)
752 struct spdk_nvmf_request
*req
;
753 struct spdk_nvme_cpl
*rsp
;
754 struct spdk_nvmf_registrant
*reg
;
755 bool update_sgroup
= false;
757 struct spdk_nvmf_reservation_info info
;
759 ut_reservation_init();
761 req
= ut_reservation_build_req(16);
762 rsp
= &req
->rsp
->nvme_cpl
;
763 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
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
);
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
, ®
->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);
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
);
804 ut_reservation_free_req(req
);
805 ut_reservation_deinit();
809 test_reservation_acquire_preempt_1(void)
811 struct spdk_nvmf_request
*req
;
812 struct spdk_nvme_cpl
*rsp
;
813 struct spdk_nvmf_registrant
*reg
;
816 ut_reservation_init();
818 req
= ut_reservation_build_req(16);
819 rsp
= &req
->rsp
->nvme_cpl
;
820 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
822 ut_reservation_build_registrants();
825 /* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
826 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
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
);
838 /* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
839 * g_ctrl1_A registrant is unregistred.
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
);
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.
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
);
875 ut_reservation_free_req(req
);
876 ut_reservation_deinit();
880 test_reservation_acquire_release_with_ptpl(void)
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
;
888 struct spdk_nvmf_reservation_info info
;
890 ut_reservation_init();
892 req
= ut_reservation_build_req(16);
893 rsp
= &req
->rsp
->nvme_cpl
;
894 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
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
, ®
->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);
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
));
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
);
944 ut_reservation_free_req(req
);
945 ut_reservation_deinit();
949 test_reservation_release(void)
951 struct spdk_nvmf_request
*req
;
952 struct spdk_nvme_cpl
*rsp
;
953 struct spdk_nvmf_registrant
*reg
;
955 ut_reservation_init();
957 req
= ut_reservation_build_req(16);
958 rsp
= &req
->rsp
->nvme_cpl
;
959 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
961 ut_reservation_build_registrants();
963 /* ACQUIRE: Host A with g_ctrlr1_A get reservation with
964 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
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
);
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
);
983 /* Test Case: Host C clear the registrants */
984 ut_reservation_build_release_request(req
, SPDK_NVME_RESERVE_CLEAR
, 0,
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
);
997 ut_reservation_free_req(req
);
998 ut_reservation_deinit();
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
)
1006 ctrlr
->num_avail_log_pages
++;
1010 test_reservation_unregister_notification(void)
1012 struct spdk_nvmf_request
*req
;
1013 struct spdk_nvme_cpl
*rsp
;
1015 ut_reservation_init();
1017 req
= ut_reservation_build_req(16);
1018 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
1019 rsp
= &req
->rsp
->nvme_cpl
;
1021 ut_reservation_build_registrants();
1023 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1024 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
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
);
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
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
,
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
);
1053 ut_reservation_free_req(req
);
1054 ut_reservation_deinit();
1058 test_reservation_release_notification(void)
1060 struct spdk_nvmf_request
*req
;
1061 struct spdk_nvme_cpl
*rsp
;
1063 ut_reservation_init();
1065 req
= ut_reservation_build_req(16);
1066 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
1067 rsp
= &req
->rsp
->nvme_cpl
;
1069 ut_reservation_build_registrants();
1071 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1072 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
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
);
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.
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
);
1099 ut_reservation_free_req(req
);
1100 ut_reservation_deinit();
1104 test_reservation_release_notification_write_exclusive(void)
1106 struct spdk_nvmf_request
*req
;
1107 struct spdk_nvme_cpl
*rsp
;
1109 ut_reservation_init();
1111 req
= ut_reservation_build_req(16);
1112 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
1113 rsp
= &req
->rsp
->nvme_cpl
;
1115 ut_reservation_build_registrants();
1117 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1118 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
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
);
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.
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
);
1146 ut_reservation_free_req(req
);
1147 ut_reservation_deinit();
1151 test_reservation_clear_notification(void)
1153 struct spdk_nvmf_request
*req
;
1154 struct spdk_nvme_cpl
*rsp
;
1156 ut_reservation_init();
1158 req
= ut_reservation_build_req(16);
1159 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
1160 rsp
= &req
->rsp
->nvme_cpl
;
1162 ut_reservation_build_registrants();
1164 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1165 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
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
);
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.
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,
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
);
1192 ut_reservation_free_req(req
);
1193 ut_reservation_deinit();
1197 test_reservation_preempt_notification(void)
1199 struct spdk_nvmf_request
*req
;
1200 struct spdk_nvme_cpl
*rsp
;
1202 ut_reservation_init();
1204 req
= ut_reservation_build_req(16);
1205 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
1206 rsp
= &req
->rsp
->nvme_cpl
;
1208 ut_reservation_build_registrants();
1210 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1211 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
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
);
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.
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
);
1240 ut_reservation_free_req(req
);
1241 ut_reservation_deinit();
1245 test_spdk_nvmf_ns_event(void)
1247 struct spdk_nvmf_tgt tgt
= {};
1248 struct spdk_nvmf_subsystem subsystem
= {
1253 struct spdk_nvmf_ctrlr ctrlr
= {
1254 .subsys
= &subsystem
1256 struct spdk_bdev bdev1
= {};
1257 struct spdk_nvmf_ns_opts ns_opts
;
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
);
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]);
1270 /* Add one controller */
1271 TAILQ_INIT(&subsystem
.ctrlrs
);
1272 TAILQ_INSERT_TAIL(&subsystem
.ctrlrs
, &ctrlr
, link
);
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
);
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
);
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
);
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
);
1302 free(tgt
.subsystems
);
1306 int main(int argc
, char **argv
)
1308 CU_pSuite suite
= NULL
;
1309 unsigned int num_failures
;
1311 CU_set_error_action(CUEA_ABORT
);
1312 CU_initialize_registry();
1314 suite
= CU_add_suite("nvmf", NULL
, NULL
);
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
);
1331 allocate_threads(1);
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();
1341 return num_failures
;