4 * Copyright (c) Intel Corporation.
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_nvmf_transport_stop_listen
,
58 (struct spdk_nvmf_transport
*transport
,
59 const struct spdk_nvme_transport_id
*trid
), 0);
62 subsystem_ns_remove_cb(struct spdk_nvmf_subsystem
*subsystem
, void *cb_arg
, int status
)
67 spdk_env_get_current_core(void)
73 spdk_event_allocate(uint32_t core
, spdk_event_fn fn
, void *arg1
, void *arg2
)
79 spdk_event_call(struct spdk_event
*event
)
85 spdk_nvmf_transport_listen(struct spdk_nvmf_transport
*transport
,
86 const struct spdk_nvme_transport_id
*trid
)
92 spdk_nvmf_transport_listener_discover(struct spdk_nvmf_transport
*transport
,
93 struct spdk_nvme_transport_id
*trid
,
94 struct spdk_nvmf_discovery_log_page_entry
*entry
)
99 static struct spdk_nvmf_transport g_transport
= {};
101 struct spdk_nvmf_transport
*
102 spdk_nvmf_transport_create(enum spdk_nvme_transport_type type
,
103 struct spdk_nvmf_transport_opts
*tprt_opts
)
105 if (type
== SPDK_NVME_TRANSPORT_RDMA
) {
112 struct spdk_nvmf_subsystem
*
113 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt
*tgt
, const char *subnqn
)
118 struct spdk_nvmf_transport
*
119 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt
*tgt
, enum spdk_nvme_transport_type trtype
)
121 if (trtype
== SPDK_NVME_TRANSPORT_RDMA
) {
129 spdk_nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group
*group
,
130 struct spdk_nvmf_subsystem
*subsystem
)
136 spdk_nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group
*group
,
137 struct spdk_nvmf_subsystem
*subsystem
,
138 spdk_nvmf_poll_group_mod_done cb_fn
, void *cb_arg
)
144 spdk_nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group
*group
,
145 struct spdk_nvmf_subsystem
*subsystem
,
146 spdk_nvmf_poll_group_mod_done cb_fn
, void *cb_arg
)
151 spdk_nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group
*group
,
152 struct spdk_nvmf_subsystem
*subsystem
,
153 spdk_nvmf_poll_group_mod_done cb_fn
, void *cb_arg
)
158 spdk_nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group
*group
,
159 struct spdk_nvmf_subsystem
*subsystem
,
160 spdk_nvmf_poll_group_mod_done cb_fn
, void *cb_arg
)
165 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type
*trtype
, const char *str
)
167 if (trtype
== NULL
|| str
== NULL
) {
171 if (strcasecmp(str
, "PCIe") == 0) {
172 *trtype
= SPDK_NVME_TRANSPORT_PCIE
;
173 } else if (strcasecmp(str
, "RDMA") == 0) {
174 *trtype
= SPDK_NVME_TRANSPORT_RDMA
;
182 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id
*trid1
,
183 const struct spdk_nvme_transport_id
*trid2
)
189 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr
*ctrlr
)
195 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair
*qpair
, uint32_t max_completions
)
201 spdk_nvme_detach(struct spdk_nvme_ctrlr
*ctrlr
)
207 spdk_nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr
*ctrlr
)
212 spdk_nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr
*ctrlr
, uint32_t nsid
)
217 spdk_bdev_open(struct spdk_bdev
*bdev
, bool write
, spdk_bdev_remove_cb_t remove_cb
,
218 void *remove_ctx
, struct spdk_bdev_desc
**desc
)
224 spdk_bdev_close(struct spdk_bdev_desc
*desc
)
229 spdk_bdev_get_name(const struct spdk_bdev
*bdev
)
234 const struct spdk_uuid
*
235 spdk_bdev_get_uuid(const struct spdk_bdev
*bdev
)
241 test_spdk_nvmf_subsystem_add_ns(void)
243 struct spdk_nvmf_tgt tgt
= {};
244 struct spdk_nvmf_subsystem subsystem
= {
249 struct spdk_bdev bdev1
= {}, bdev2
= {};
250 struct spdk_nvmf_ns_opts ns_opts
;
253 tgt
.max_subsystems
= 1024;
254 tgt
.subsystems
= calloc(tgt
.max_subsystems
, sizeof(struct spdk_nvmf_subsystem
*));
255 SPDK_CU_ASSERT_FATAL(tgt
.subsystems
!= NULL
);
257 /* Allow NSID to be assigned automatically */
258 spdk_nvmf_ns_opts_get_defaults(&ns_opts
, sizeof(ns_opts
));
259 nsid
= spdk_nvmf_subsystem_add_ns(&subsystem
, &bdev1
, &ns_opts
, sizeof(ns_opts
), NULL
);
260 /* NSID 1 is the first unused ID */
261 CU_ASSERT(nsid
== 1);
262 CU_ASSERT(subsystem
.max_nsid
== 1);
263 SPDK_CU_ASSERT_FATAL(subsystem
.ns
!= NULL
);
264 SPDK_CU_ASSERT_FATAL(subsystem
.ns
[nsid
- 1] != NULL
);
265 CU_ASSERT(subsystem
.ns
[nsid
- 1]->bdev
== &bdev1
);
267 /* Request a specific NSID */
268 spdk_nvmf_ns_opts_get_defaults(&ns_opts
, sizeof(ns_opts
));
270 nsid
= spdk_nvmf_subsystem_add_ns(&subsystem
, &bdev2
, &ns_opts
, sizeof(ns_opts
), NULL
);
271 CU_ASSERT(nsid
== 5);
272 CU_ASSERT(subsystem
.max_nsid
== 5);
273 SPDK_CU_ASSERT_FATAL(subsystem
.ns
[nsid
- 1] != NULL
);
274 CU_ASSERT(subsystem
.ns
[nsid
- 1]->bdev
== &bdev2
);
276 /* Request an NSID that is already in use */
277 spdk_nvmf_ns_opts_get_defaults(&ns_opts
, sizeof(ns_opts
));
279 nsid
= spdk_nvmf_subsystem_add_ns(&subsystem
, &bdev2
, &ns_opts
, sizeof(ns_opts
), NULL
);
280 CU_ASSERT(nsid
== 0);
281 CU_ASSERT(subsystem
.max_nsid
== 5);
283 /* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */
284 spdk_nvmf_ns_opts_get_defaults(&ns_opts
, sizeof(ns_opts
));
285 ns_opts
.nsid
= 0xFFFFFFFF;
286 nsid
= spdk_nvmf_subsystem_add_ns(&subsystem
, &bdev2
, &ns_opts
, sizeof(ns_opts
), NULL
);
287 CU_ASSERT(nsid
== 0);
288 CU_ASSERT(subsystem
.max_nsid
== 5);
290 spdk_nvmf_subsystem_remove_ns(&subsystem
, 1, subsystem_ns_remove_cb
, NULL
);
292 spdk_nvmf_subsystem_remove_ns(&subsystem
, 5, subsystem_ns_remove_cb
, NULL
);
296 free(tgt
.subsystems
);
300 nvmf_test_create_subsystem(void)
302 struct spdk_nvmf_tgt tgt
= {};
304 struct spdk_nvmf_subsystem
*subsystem
;
306 tgt
.max_subsystems
= 1024;
307 tgt
.subsystems
= calloc(tgt
.max_subsystems
, sizeof(struct spdk_nvmf_subsystem
*));
308 SPDK_CU_ASSERT_FATAL(tgt
.subsystems
!= NULL
);
310 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:subsystem1");
311 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
312 SPDK_CU_ASSERT_FATAL(subsystem
!= NULL
);
313 CU_ASSERT_STRING_EQUAL(subsystem
->subnqn
, nqn
);
314 spdk_nvmf_subsystem_destroy(subsystem
);
316 /* valid name with complex reverse domain */
317 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1");
318 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
319 SPDK_CU_ASSERT_FATAL(subsystem
!= NULL
);
320 CU_ASSERT_STRING_EQUAL(subsystem
->subnqn
, nqn
);
321 spdk_nvmf_subsystem_destroy(subsystem
);
323 /* Valid name discovery controller */
324 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:subsystem1");
325 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
326 SPDK_CU_ASSERT_FATAL(subsystem
!= NULL
);
327 CU_ASSERT_STRING_EQUAL(subsystem
->subnqn
, nqn
);
328 spdk_nvmf_subsystem_destroy(subsystem
);
331 /* Invalid name, no user supplied string */
332 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:");
333 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
334 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
336 /* Valid name, only contains top-level domain name */
337 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:subsystem1");
338 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
339 SPDK_CU_ASSERT_FATAL(subsystem
!= NULL
);
340 CU_ASSERT_STRING_EQUAL(subsystem
->subnqn
, nqn
);
341 spdk_nvmf_subsystem_destroy(subsystem
);
343 /* Invalid name, domain label > 63 characters */
344 snprintf(nqn
, sizeof(nqn
),
345 "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub");
346 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
347 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
349 /* Invalid name, domain label starts with digit */
350 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.3spdk:sub");
351 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
352 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
354 /* Invalid name, domain label starts with - */
355 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.-spdk:subsystem1");
356 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
357 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
359 /* Invalid name, domain label ends with - */
360 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk-:subsystem1");
361 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
362 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
364 /* Invalid name, domain label with multiple consecutive periods */
365 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io..spdk:subsystem1");
366 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
367 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
369 /* Longest valid name */
370 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:");
371 memset(nqn
+ strlen(nqn
), 'a', 223 - strlen(nqn
));
373 CU_ASSERT(strlen(nqn
) == 223);
374 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
375 SPDK_CU_ASSERT_FATAL(subsystem
!= NULL
);
376 CU_ASSERT_STRING_EQUAL(subsystem
->subnqn
, nqn
);
377 spdk_nvmf_subsystem_destroy(subsystem
);
379 /* Invalid name, too long */
380 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:");
381 memset(nqn
+ strlen(nqn
), 'a', 224 - strlen(nqn
));
383 CU_ASSERT(strlen(nqn
) == 224);
384 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
385 CU_ASSERT(subsystem
== NULL
);
387 /* Valid name using uuid format */
388 snprintf(nqn
, sizeof(nqn
), "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abc");
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 name user string contains an invalid utf-8 character */
395 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:\xFFsubsystem1");
396 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
397 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
399 /* Valid name with non-ascii but valid utf-8 characters */
400 snprintf(nqn
, sizeof(nqn
), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80");
401 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
402 SPDK_CU_ASSERT_FATAL(subsystem
!= NULL
);
403 CU_ASSERT_STRING_EQUAL(subsystem
->subnqn
, nqn
);
404 spdk_nvmf_subsystem_destroy(subsystem
);
406 /* Invalid uuid (too long) */
407 snprintf(nqn
, sizeof(nqn
),
408 "nqn.2014-08.org.nvmexpress:uuid:11111111-aaaa-bbdd-FFEE-123456789abcdef");
409 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
410 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
412 /* Invalid uuid (dashes placed incorrectly) */
413 snprintf(nqn
, sizeof(nqn
), "nqn.2014-08.org.nvmexpress:uuid:111111-11aaaa-bbdd-FFEE-123456789abc");
414 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
415 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
417 /* Invalid uuid (invalid characters in uuid) */
418 snprintf(nqn
, sizeof(nqn
), "nqn.2014-08.org.nvmexpress:uuid:111hg111-aaaa-bbdd-FFEE-123456789abc");
419 subsystem
= spdk_nvmf_subsystem_create(&tgt
, nqn
, SPDK_NVMF_SUBTYPE_NVME
, 0);
420 SPDK_CU_ASSERT_FATAL(subsystem
== NULL
);
422 free(tgt
.subsystems
);
426 test_spdk_nvmf_subsystem_set_sn(void)
428 struct spdk_nvmf_subsystem subsystem
= {};
430 /* Basic valid serial number */
431 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem
, "abcd xyz") == 0);
432 CU_ASSERT(strcmp(subsystem
.sn
, "abcd xyz") == 0);
434 /* Exactly 20 characters (valid) */
435 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem
, "12345678901234567890") == 0);
436 CU_ASSERT(strcmp(subsystem
.sn
, "12345678901234567890") == 0);
438 /* 21 characters (too long, invalid) */
439 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem
, "123456789012345678901") < 0);
441 /* Non-ASCII characters (invalid) */
442 CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem
, "abcd\txyz") < 0);
446 * Reservation Unit Test Configuration
447 * -------- -------- --------
448 * | Host A | | Host B | | Host C |
449 * -------- -------- --------
451 * -------- -------- ------- -------
452 * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C|
453 * -------- -------- ------- -------
457 * --------------------------------------
459 * --------------------------------------
461 static struct spdk_nvmf_subsystem g_subsystem
;
462 static struct spdk_nvmf_ctrlr g_ctrlr1_A
, g_ctrlr2_A
, g_ctrlr_B
, g_ctrlr_C
;
463 static struct spdk_nvmf_ns g_ns
;
464 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info
;
467 spdk_nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr
*ctrlr
)
472 ut_reservation_init(void)
475 TAILQ_INIT(&g_subsystem
.ctrlrs
);
477 memset(&g_ns
, 0, sizeof(g_ns
));
478 TAILQ_INIT(&g_ns
.registrants
);
479 g_ns
.subsystem
= &g_subsystem
;
481 /* Host A has two controllers */
482 spdk_uuid_generate(&g_ctrlr1_A
.hostid
);
483 TAILQ_INIT(&g_ctrlr1_A
.log_head
);
484 g_ctrlr1_A
.subsys
= &g_subsystem
;
485 g_ctrlr1_A
.num_avail_log_pages
= 0;
486 TAILQ_INSERT_TAIL(&g_subsystem
.ctrlrs
, &g_ctrlr1_A
, link
);
487 spdk_uuid_copy(&g_ctrlr2_A
.hostid
, &g_ctrlr1_A
.hostid
);
488 TAILQ_INIT(&g_ctrlr2_A
.log_head
);
489 g_ctrlr2_A
.subsys
= &g_subsystem
;
490 g_ctrlr2_A
.num_avail_log_pages
= 0;
491 TAILQ_INSERT_TAIL(&g_subsystem
.ctrlrs
, &g_ctrlr2_A
, link
);
493 /* Host B has 1 controller */
494 spdk_uuid_generate(&g_ctrlr_B
.hostid
);
495 TAILQ_INIT(&g_ctrlr_B
.log_head
);
496 g_ctrlr_B
.subsys
= &g_subsystem
;
497 g_ctrlr_B
.num_avail_log_pages
= 0;
498 TAILQ_INSERT_TAIL(&g_subsystem
.ctrlrs
, &g_ctrlr_B
, link
);
500 /* Host C has 1 controller */
501 spdk_uuid_generate(&g_ctrlr_C
.hostid
);
502 TAILQ_INIT(&g_ctrlr_C
.log_head
);
503 g_ctrlr_C
.subsys
= &g_subsystem
;
504 g_ctrlr_C
.num_avail_log_pages
= 0;
505 TAILQ_INSERT_TAIL(&g_subsystem
.ctrlrs
, &g_ctrlr_C
, link
);
509 ut_reservation_deinit(void)
511 struct spdk_nvmf_registrant
*reg
, *tmp
;
512 struct spdk_nvmf_reservation_log
*log
, *log_tmp
;
513 struct spdk_nvmf_ctrlr
*ctrlr
, *ctrlr_tmp
;
515 TAILQ_FOREACH_SAFE(reg
, &g_ns
.registrants
, link
, tmp
) {
516 TAILQ_REMOVE(&g_ns
.registrants
, reg
, link
);
519 TAILQ_FOREACH_SAFE(log
, &g_ctrlr1_A
.log_head
, link
, log_tmp
) {
520 TAILQ_REMOVE(&g_ctrlr1_A
.log_head
, log
, link
);
523 g_ctrlr1_A
.num_avail_log_pages
= 0;
524 TAILQ_FOREACH_SAFE(log
, &g_ctrlr2_A
.log_head
, link
, log_tmp
) {
525 TAILQ_REMOVE(&g_ctrlr2_A
.log_head
, log
, link
);
528 g_ctrlr2_A
.num_avail_log_pages
= 0;
529 TAILQ_FOREACH_SAFE(log
, &g_ctrlr_B
.log_head
, link
, log_tmp
) {
530 TAILQ_REMOVE(&g_ctrlr_B
.log_head
, log
, link
);
533 g_ctrlr_B
.num_avail_log_pages
= 0;
534 TAILQ_FOREACH_SAFE(log
, &g_ctrlr_C
.log_head
, link
, log_tmp
) {
535 TAILQ_REMOVE(&g_ctrlr_C
.log_head
, log
, link
);
538 g_ctrlr_C
.num_avail_log_pages
= 0;
540 TAILQ_FOREACH_SAFE(ctrlr
, &g_subsystem
.ctrlrs
, link
, ctrlr_tmp
) {
541 TAILQ_REMOVE(&g_subsystem
.ctrlrs
, ctrlr
, link
);
545 static struct spdk_nvmf_request
*
546 ut_reservation_build_req(uint32_t length
)
548 struct spdk_nvmf_request
*req
;
550 req
= calloc(1, sizeof(*req
));
553 req
->data
= calloc(1, length
);
554 assert(req
->data
!= NULL
);
555 req
->length
= length
;
557 req
->cmd
= (union nvmf_h2c_msg
*)calloc(1, sizeof(union nvmf_h2c_msg
));
558 assert(req
->cmd
!= NULL
);
560 req
->rsp
= (union nvmf_c2h_msg
*)calloc(1, sizeof(union nvmf_c2h_msg
));
561 assert(req
->rsp
!= NULL
);
567 ut_reservation_free_req(struct spdk_nvmf_request
*req
)
576 ut_reservation_build_register_request(struct spdk_nvmf_request
*req
,
577 uint8_t rrega
, uint8_t iekey
,
578 uint8_t cptpl
, uint64_t crkey
,
582 struct spdk_nvme_reservation_register_data key
;
583 struct spdk_nvme_cmd
*cmd
= &req
->cmd
->nvme_cmd
;
585 cdw10
= ((cptpl
<< 30) | (iekey
<< 3) | rrega
);
589 memcpy(req
->data
, &key
, sizeof(key
));
593 ut_reservation_build_acquire_request(struct spdk_nvmf_request
*req
,
594 uint8_t racqa
, uint8_t iekey
,
595 uint8_t rtype
, uint64_t crkey
,
599 struct spdk_nvme_reservation_acquire_data key
;
600 struct spdk_nvme_cmd
*cmd
= &req
->cmd
->nvme_cmd
;
602 cdw10
= ((rtype
<< 8) | (iekey
<< 3) | racqa
);
606 memcpy(req
->data
, &key
, sizeof(key
));
610 ut_reservation_build_release_request(struct spdk_nvmf_request
*req
,
611 uint8_t rrela
, uint8_t iekey
,
612 uint8_t rtype
, uint64_t crkey
)
615 struct spdk_nvme_cmd
*cmd
= &req
->cmd
->nvme_cmd
;
617 cdw10
= ((rtype
<< 8) | (iekey
<< 3) | rrela
);
619 memcpy(req
->data
, &crkey
, sizeof(crkey
));
623 * Construct four registrants for other test cases.
625 * g_ctrlr1_A register with key 0xa1.
626 * g_ctrlr2_A register with key 0xa1.
627 * g_ctrlr_B register with key 0xb1.
628 * g_ctrlr_C register with key 0xc1.
631 ut_reservation_build_registrants(void)
633 struct spdk_nvmf_request
*req
;
634 struct spdk_nvme_cpl
*rsp
;
635 struct spdk_nvmf_registrant
*reg
;
638 req
= ut_reservation_build_req(16);
639 rsp
= &req
->rsp
->nvme_cpl
;
640 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
643 /* TEST CASE: g_ctrlr1_A register with a new key */
644 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REGISTER_KEY
,
646 nvmf_ns_reservation_register(&g_ns
, &g_ctrlr1_A
, req
);
647 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
648 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr1_A
.hostid
);
649 SPDK_CU_ASSERT_FATAL(reg
->rkey
== 0xa1);
650 SPDK_CU_ASSERT_FATAL(g_ns
.gen
== gen
+ 1);
652 /* TEST CASE: g_ctrlr2_A register with a new key, because it has same
653 * Host Identifier with g_ctrlr1_A, so the register key should same.
655 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REGISTER_KEY
,
657 nvmf_ns_reservation_register(&g_ns
, &g_ctrlr2_A
, req
);
658 /* Reservation conflict for other key than 0xa1 */
659 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_RESERVATION_CONFLICT
);
661 /* g_ctrlr_B register with a new key */
662 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REGISTER_KEY
,
664 nvmf_ns_reservation_register(&g_ns
, &g_ctrlr_B
, req
);
665 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
666 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_B
.hostid
);
667 SPDK_CU_ASSERT_FATAL(reg
->rkey
== 0xb1);
668 SPDK_CU_ASSERT_FATAL(g_ns
.gen
== gen
+ 2);
670 /* g_ctrlr_C register with a new key */
671 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REGISTER_KEY
,
673 nvmf_ns_reservation_register(&g_ns
, &g_ctrlr_C
, req
);
674 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
675 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_C
.hostid
);
676 SPDK_CU_ASSERT_FATAL(reg
->rkey
== 0xc1);
677 SPDK_CU_ASSERT_FATAL(g_ns
.gen
== gen
+ 3);
679 ut_reservation_free_req(req
);
683 test_reservation_register(void)
685 struct spdk_nvmf_request
*req
;
686 struct spdk_nvme_cpl
*rsp
;
687 struct spdk_nvmf_registrant
*reg
;
690 ut_reservation_init();
692 req
= ut_reservation_build_req(16);
693 rsp
= &req
->rsp
->nvme_cpl
;
694 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
696 ut_reservation_build_registrants();
698 /* TEST CASE: Replace g_ctrlr1_A with a new key */
699 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_REPLACE_KEY
,
701 nvmf_ns_reservation_register(&g_ns
, &g_ctrlr1_A
, req
);
702 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
703 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr1_A
.hostid
);
704 SPDK_CU_ASSERT_FATAL(reg
->rkey
== 0xa11);
706 /* TEST CASE: Host A with g_ctrlr1_A get reservation with
707 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
709 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_ACQUIRE
, 0,
710 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
, 0xa11, 0x0);
712 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr1_A
, req
);
713 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
714 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr1_A
.hostid
);
715 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
);
716 SPDK_CU_ASSERT_FATAL(g_ns
.crkey
== 0xa11);
717 SPDK_CU_ASSERT_FATAL(g_ns
.holder
== reg
);
718 SPDK_CU_ASSERT_FATAL(g_ns
.gen
== gen
);
720 /* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
721 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_UNREGISTER_KEY
,
723 nvmf_ns_reservation_register(&g_ns
, &g_ctrlr_C
, req
);
724 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
725 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_C
.hostid
);
726 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
728 /* TEST CASE: g_ctrlr_B unregister with correct key */
729 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_UNREGISTER_KEY
,
731 nvmf_ns_reservation_register(&g_ns
, &g_ctrlr_B
, req
);
732 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
733 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_B
.hostid
);
734 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
736 /* TEST CASE: g_ctrlr1_A unregister with correct key,
737 * reservation should be removed as well.
739 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_UNREGISTER_KEY
,
741 nvmf_ns_reservation_register(&g_ns
, &g_ctrlr1_A
, req
);
742 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
743 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr1_A
.hostid
);
744 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
745 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== 0);
746 SPDK_CU_ASSERT_FATAL(g_ns
.crkey
== 0);
747 SPDK_CU_ASSERT_FATAL(g_ns
.holder
== NULL
);
749 ut_reservation_free_req(req
);
750 ut_reservation_deinit();
754 test_reservation_acquire_preempt_1(void)
756 struct spdk_nvmf_request
*req
;
757 struct spdk_nvme_cpl
*rsp
;
758 struct spdk_nvmf_registrant
*reg
;
761 ut_reservation_init();
763 req
= ut_reservation_build_req(16);
764 rsp
= &req
->rsp
->nvme_cpl
;
765 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
767 ut_reservation_build_registrants();
770 /* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
771 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
773 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_ACQUIRE
, 0,
774 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
, 0xa1, 0x0);
775 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr1_A
, req
);
776 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
777 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr1_A
.hostid
);
778 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
);
779 SPDK_CU_ASSERT_FATAL(g_ns
.crkey
== 0xa1);
780 SPDK_CU_ASSERT_FATAL(g_ns
.holder
== reg
);
781 SPDK_CU_ASSERT_FATAL(g_ns
.gen
== gen
);
783 /* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
784 * g_ctrl1_A registrant is unregistred.
787 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_PREEMPT
, 0,
788 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
, 0xb1, 0xa1);
789 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr_B
, req
);
790 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
791 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr1_A
.hostid
);
792 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
793 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_B
.hostid
);
794 SPDK_CU_ASSERT_FATAL(reg
!= NULL
);
795 SPDK_CU_ASSERT_FATAL(g_ns
.holder
== reg
);
796 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_C
.hostid
);
797 SPDK_CU_ASSERT_FATAL(reg
!= NULL
);
798 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
);
799 SPDK_CU_ASSERT_FATAL(g_ns
.gen
> gen
);
801 /* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B
802 * with valid key and PRKEY set to 0, all registrants other the host that issued
803 * the command are unregistered.
806 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_PREEMPT
, 0,
807 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
, 0xc1, 0x0);
808 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr_C
, req
);
809 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
810 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr2_A
.hostid
);
811 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
812 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_B
.hostid
);
813 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
814 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_C
.hostid
);
815 SPDK_CU_ASSERT_FATAL(reg
!= NULL
);
816 SPDK_CU_ASSERT_FATAL(g_ns
.holder
== reg
);
817 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
);
818 SPDK_CU_ASSERT_FATAL(g_ns
.gen
> gen
);
820 ut_reservation_free_req(req
);
821 ut_reservation_deinit();
825 test_reservation_release(void)
827 struct spdk_nvmf_request
*req
;
828 struct spdk_nvme_cpl
*rsp
;
829 struct spdk_nvmf_registrant
*reg
;
831 ut_reservation_init();
833 req
= ut_reservation_build_req(16);
834 rsp
= &req
->rsp
->nvme_cpl
;
835 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
837 ut_reservation_build_registrants();
839 /* ACQUIRE: Host A with g_ctrlr1_A get reservation with
840 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
842 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_ACQUIRE
, 0,
843 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
, 0xa1, 0x0);
844 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr1_A
, 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(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
);
848 SPDK_CU_ASSERT_FATAL(g_ns
.holder
== reg
);
850 /* Test Case: Host B release the reservation */
851 ut_reservation_build_release_request(req
, SPDK_NVME_RESERVE_RELEASE
, 0,
852 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
, 0xb1);
853 nvmf_ns_reservation_release(&g_ns
, &g_ctrlr_B
, req
);
854 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
855 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== 0);
856 SPDK_CU_ASSERT_FATAL(g_ns
.crkey
== 0);
857 SPDK_CU_ASSERT_FATAL(g_ns
.holder
== NULL
);
859 /* Test Case: Host C clear the registrants */
860 ut_reservation_build_release_request(req
, SPDK_NVME_RESERVE_CLEAR
, 0,
862 nvmf_ns_reservation_release(&g_ns
, &g_ctrlr_C
, req
);
863 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
864 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr1_A
.hostid
);
865 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
866 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr2_A
.hostid
);
867 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
868 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_B
.hostid
);
869 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
870 reg
= nvmf_ns_reservation_get_registrant(&g_ns
, &g_ctrlr_C
.hostid
);
871 SPDK_CU_ASSERT_FATAL(reg
== NULL
);
873 ut_reservation_free_req(req
);
874 ut_reservation_deinit();
878 spdk_nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr
*ctrlr
,
879 struct spdk_nvmf_ns
*ns
,
880 enum spdk_nvme_reservation_notification_log_page_type type
)
882 ctrlr
->num_avail_log_pages
++;
886 test_reservation_unregister_notification(void)
888 struct spdk_nvmf_request
*req
;
889 struct spdk_nvme_cpl
*rsp
;
891 ut_reservation_init();
893 req
= ut_reservation_build_req(16);
894 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
895 rsp
= &req
->rsp
->nvme_cpl
;
897 ut_reservation_build_registrants();
899 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
900 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
902 rsp
->status
.sc
= 0xff;
903 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_ACQUIRE
, 0,
904 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
, 0xb1, 0x0);
905 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr_B
, req
);
906 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
907 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
);
909 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration.
910 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for
911 * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY
914 rsp
->status
.sc
= 0xff;
915 g_ctrlr1_A
.num_avail_log_pages
= 0;
916 g_ctrlr2_A
.num_avail_log_pages
= 0;
917 g_ctrlr_B
.num_avail_log_pages
= 5;
918 g_ctrlr_C
.num_avail_log_pages
= 0;
919 ut_reservation_build_register_request(req
, SPDK_NVME_RESERVE_UNREGISTER_KEY
,
921 nvmf_ns_reservation_register(&g_ns
, &g_ctrlr_B
, req
);
922 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
923 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== 0);
924 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A
.num_avail_log_pages
);
925 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A
.num_avail_log_pages
);
926 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B
.num_avail_log_pages
);
927 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C
.num_avail_log_pages
);
929 ut_reservation_free_req(req
);
930 ut_reservation_deinit();
934 test_reservation_release_notification(void)
936 struct spdk_nvmf_request
*req
;
937 struct spdk_nvme_cpl
*rsp
;
939 ut_reservation_init();
941 req
= ut_reservation_build_req(16);
942 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
943 rsp
= &req
->rsp
->nvme_cpl
;
945 ut_reservation_build_registrants();
947 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
948 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
950 rsp
->status
.sc
= 0xff;
951 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_ACQUIRE
, 0,
952 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
, 0xb1, 0x0);
953 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr_B
, req
);
954 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
955 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
);
957 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
958 * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
960 rsp
->status
.sc
= 0xff;
961 g_ctrlr1_A
.num_avail_log_pages
= 0;
962 g_ctrlr2_A
.num_avail_log_pages
= 0;
963 g_ctrlr_B
.num_avail_log_pages
= 5;
964 g_ctrlr_C
.num_avail_log_pages
= 0;
965 ut_reservation_build_release_request(req
, SPDK_NVME_RESERVE_RELEASE
, 0,
966 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
, 0xb1);
967 nvmf_ns_reservation_release(&g_ns
, &g_ctrlr_B
, req
);
968 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
969 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== 0);
970 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A
.num_avail_log_pages
);
971 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A
.num_avail_log_pages
);
972 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B
.num_avail_log_pages
);
973 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C
.num_avail_log_pages
);
975 ut_reservation_free_req(req
);
976 ut_reservation_deinit();
980 test_reservation_release_notification_write_exclusive(void)
982 struct spdk_nvmf_request
*req
;
983 struct spdk_nvme_cpl
*rsp
;
985 ut_reservation_init();
987 req
= ut_reservation_build_req(16);
988 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
989 rsp
= &req
->rsp
->nvme_cpl
;
991 ut_reservation_build_registrants();
993 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
994 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
996 rsp
->status
.sc
= 0xff;
997 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_ACQUIRE
, 0,
998 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
, 0xb1, 0x0);
999 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr_B
, req
);
1000 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
1001 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
);
1003 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1004 * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
1005 * no reservation notification occurs.
1007 rsp
->status
.sc
= 0xff;
1008 g_ctrlr1_A
.num_avail_log_pages
= 5;
1009 g_ctrlr2_A
.num_avail_log_pages
= 5;
1010 g_ctrlr_B
.num_avail_log_pages
= 5;
1011 g_ctrlr_C
.num_avail_log_pages
= 5;
1012 ut_reservation_build_release_request(req
, SPDK_NVME_RESERVE_RELEASE
, 0,
1013 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
, 0xb1);
1014 nvmf_ns_reservation_release(&g_ns
, &g_ctrlr_B
, req
);
1015 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
1016 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== 0);
1017 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A
.num_avail_log_pages
);
1018 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A
.num_avail_log_pages
);
1019 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B
.num_avail_log_pages
);
1020 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C
.num_avail_log_pages
);
1022 ut_reservation_free_req(req
);
1023 ut_reservation_deinit();
1027 test_reservation_clear_notification(void)
1029 struct spdk_nvmf_request
*req
;
1030 struct spdk_nvme_cpl
*rsp
;
1032 ut_reservation_init();
1034 req
= ut_reservation_build_req(16);
1035 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
1036 rsp
= &req
->rsp
->nvme_cpl
;
1038 ut_reservation_build_registrants();
1040 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1041 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1043 rsp
->status
.sc
= 0xff;
1044 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_ACQUIRE
, 0,
1045 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
, 0xb1, 0x0);
1046 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr_B
, req
);
1047 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
1048 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
);
1050 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation.
1051 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1053 rsp
->status
.sc
= 0xff;
1054 g_ctrlr1_A
.num_avail_log_pages
= 0;
1055 g_ctrlr2_A
.num_avail_log_pages
= 0;
1056 g_ctrlr_B
.num_avail_log_pages
= 5;
1057 g_ctrlr_C
.num_avail_log_pages
= 0;
1058 ut_reservation_build_release_request(req
, SPDK_NVME_RESERVE_CLEAR
, 0,
1060 nvmf_ns_reservation_release(&g_ns
, &g_ctrlr_B
, req
);
1061 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
1062 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== 0);
1063 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A
.num_avail_log_pages
);
1064 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A
.num_avail_log_pages
);
1065 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B
.num_avail_log_pages
);
1066 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C
.num_avail_log_pages
);
1068 ut_reservation_free_req(req
);
1069 ut_reservation_deinit();
1073 test_reservation_preempt_notification(void)
1075 struct spdk_nvmf_request
*req
;
1076 struct spdk_nvme_cpl
*rsp
;
1078 ut_reservation_init();
1080 req
= ut_reservation_build_req(16);
1081 SPDK_CU_ASSERT_FATAL(req
!= NULL
);
1082 rsp
= &req
->rsp
->nvme_cpl
;
1084 ut_reservation_build_registrants();
1086 /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1087 * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1089 rsp
->status
.sc
= 0xff;
1090 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_ACQUIRE
, 0,
1091 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
, 0xb1, 0x0);
1092 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr_B
, req
);
1093 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
1094 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
);
1096 /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B,
1097 * g_ctrlr_B registrant is unregistred, and reservation is preempted.
1098 * Registration Preempted notification sends to g_ctrlr_B.
1099 * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A.
1101 rsp
->status
.sc
= 0xff;
1102 g_ctrlr1_A
.num_avail_log_pages
= 0;
1103 g_ctrlr2_A
.num_avail_log_pages
= 0;
1104 g_ctrlr_B
.num_avail_log_pages
= 0;
1105 g_ctrlr_C
.num_avail_log_pages
= 5;
1106 ut_reservation_build_acquire_request(req
, SPDK_NVME_RESERVE_PREEMPT
, 0,
1107 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
, 0xc1, 0xb1);
1108 nvmf_ns_reservation_acquire(&g_ns
, &g_ctrlr_C
, req
);
1109 SPDK_CU_ASSERT_FATAL(rsp
->status
.sc
== SPDK_NVME_SC_SUCCESS
);
1110 SPDK_CU_ASSERT_FATAL(g_ns
.rtype
== SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
);
1111 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A
.num_avail_log_pages
);
1112 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A
.num_avail_log_pages
);
1113 SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B
.num_avail_log_pages
);
1114 SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C
.num_avail_log_pages
);
1116 ut_reservation_free_req(req
);
1117 ut_reservation_deinit();
1120 int main(int argc
, char **argv
)
1122 CU_pSuite suite
= NULL
;
1123 unsigned int num_failures
;
1125 if (CU_initialize_registry() != CUE_SUCCESS
) {
1126 return CU_get_error();
1129 suite
= CU_add_suite("nvmf", NULL
, NULL
);
1130 if (suite
== NULL
) {
1131 CU_cleanup_registry();
1132 return CU_get_error();
1136 CU_add_test(suite
, "create_subsystem", nvmf_test_create_subsystem
) == NULL
||
1137 CU_add_test(suite
, "nvmf_subsystem_add_ns", test_spdk_nvmf_subsystem_add_ns
) == NULL
||
1138 CU_add_test(suite
, "nvmf_subsystem_set_sn", test_spdk_nvmf_subsystem_set_sn
) == NULL
||
1139 CU_add_test(suite
, "reservation_register", test_reservation_register
) == NULL
||
1140 CU_add_test(suite
, "reservation_acquire_preempt_1", test_reservation_acquire_preempt_1
) == NULL
||
1141 CU_add_test(suite
, "reservation_release", test_reservation_release
) == NULL
||
1142 CU_add_test(suite
, "reservation_unregister_notification",
1143 test_reservation_unregister_notification
) == NULL
||
1144 CU_add_test(suite
, "reservation_release_notification",
1145 test_reservation_release_notification
) == NULL
||
1146 CU_add_test(suite
, "reservation_release_notification_write_exclusive",
1147 test_reservation_release_notification_write_exclusive
) == NULL
||
1148 CU_add_test(suite
, "reservation_clear_notification", test_reservation_clear_notification
) == NULL
||
1149 CU_add_test(suite
, "reservation_preempt_notification",
1150 test_reservation_preempt_notification
) == NULL
1152 CU_cleanup_registry();
1153 return CU_get_error();
1156 allocate_threads(1);
1159 CU_basic_set_mode(CU_BRM_VERBOSE
);
1160 CU_basic_run_tests();
1161 num_failures
= CU_get_number_of_failures();
1162 CU_cleanup_registry();
1166 return num_failures
;