Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation. All rights reserved.
3 : : * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : :
8 : : #include "common/lib/ut_multithread.c"
9 : : #include "spdk_internal/cunit.h"
10 : : #include "spdk/nvmf.h"
11 : : #include "spdk_internal/mock.h"
12 : :
13 : : #include "spdk/bdev_module.h"
14 : : #include "nvmf/subsystem.c"
15 : : #include "nvmf/transport.c"
16 : :
17 : 3 : SPDK_LOG_REGISTER_COMPONENT(nvmf)
18 : :
19 [ - + # # ]: 15 : DEFINE_STUB(spdk_bdev_module_claim_bdev,
20 : : int,
21 : : (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
22 : : struct spdk_bdev_module *module), 0);
23 : :
24 : 18 : DEFINE_STUB_V(spdk_bdev_module_release_bdev,
25 : : (struct spdk_bdev *bdev));
26 : :
27 [ # # # # ]: 0 : DEFINE_STUB(spdk_bdev_desc_get_block_size, uint32_t,
28 : : (struct spdk_bdev_desc *desc), 512);
29 : :
30 [ - + # # ]: 15 : DEFINE_STUB(spdk_bdev_desc_get_md_size, uint32_t,
31 : : (struct spdk_bdev_desc *desc), 0);
32 : :
33 [ # # # # ]: 0 : DEFINE_STUB(spdk_bdev_desc_is_md_interleaved, bool,
34 : : (struct spdk_bdev_desc *desc), false);
35 : :
36 [ - + - + ]: 15 : DEFINE_STUB(spdk_bdev_io_type_supported, bool,
37 : : (struct spdk_bdev *bdev,
38 : : enum spdk_bdev_io_type io_type), false);
39 : :
40 : 0 : DEFINE_STUB_V(spdk_nvmf_send_discovery_log_notice,
41 : : (struct spdk_nvmf_tgt *tgt, const char *hostnqn));
42 [ # # # # ]: 0 : DEFINE_STUB(spdk_nvmf_qpair_disconnect, int, (struct spdk_nvmf_qpair *qpair), 0);
43 : :
44 [ # # # # ]: 0 : DEFINE_STUB(spdk_nvmf_request_complete,
45 : : int,
46 : : (struct spdk_nvmf_request *req), 0);
47 : :
48 [ # # # # ]: 0 : DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice,
49 : : int,
50 : : (struct spdk_nvmf_ctrlr *ctrlr), 0);
51 : :
52 [ # # # # ]: 0 : DEFINE_STUB(spdk_nvme_transport_id_trtype_str,
53 : : const char *,
54 : : (enum spdk_nvme_transport_type trtype), NULL);
55 : :
56 [ - + - + ]: 15 : DEFINE_STUB(spdk_bdev_is_zoned, bool,
57 : : (const struct spdk_bdev *bdev), false);
58 : :
59 [ # # # # ]: 0 : DEFINE_STUB(spdk_bdev_get_max_zone_append_size, uint32_t,
60 : : (const struct spdk_bdev *bdev), 0);
61 : :
62 [ # # # # ]: 0 : DEFINE_STUB(spdk_mempool_lookup, struct spdk_mempool *,
63 : : (const char *name), NULL);
64 : :
65 [ # # # # ]: 0 : DEFINE_STUB(spdk_nvme_transport_id_adrfam_str, const char *,
66 : : (enum spdk_nvmf_adrfam adrfam), NULL);
67 : :
68 [ # # # # ]: 0 : DEFINE_STUB(spdk_nvmf_qpair_get_listen_trid, int,
69 : : (struct spdk_nvmf_qpair *qpair,
70 : : struct spdk_nvme_transport_id *trid), 0);
71 [ # # # # ]: 0 : DEFINE_STUB(spdk_key_dup, struct spdk_key *, (struct spdk_key *k), NULL);
72 [ # # # # ]: 0 : DEFINE_STUB(spdk_key_get_name, const char *, (struct spdk_key *k), NULL);
73 : 12 : DEFINE_STUB_V(spdk_keyring_put_key, (struct spdk_key *k));
74 [ # # # # ]: 0 : DEFINE_STUB(nvmf_auth_is_supported, bool, (void), false);
75 [ # # # # ]: 0 : DEFINE_STUB(nvmf_tgt_update_mdns_prr, int, (struct spdk_nvmf_tgt *tgt), 0);
76 : :
77 [ # # # # ]: 0 : DEFINE_STUB(spdk_bdev_get_module_name, const char *, (const struct spdk_bdev *bdev), "nvme");
78 [ # # # # ]: 0 : DEFINE_STUB(spdk_bdev_get_module_ctx, void *, (struct spdk_bdev_desc *desc), NULL);
79 [ - + # # ]: 15 : DEFINE_STUB(spdk_bdev_get_nvme_nsid, uint32_t, (struct spdk_bdev *bdev), 0);
80 : :
81 : : static struct spdk_nvmf_transport g_transport = {};
82 : :
83 : : struct spdk_nvmf_subsystem *
84 : 66 : spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
85 : : {
86 : 66 : return NULL;
87 : : }
88 : :
89 : : struct spdk_nvmf_transport *
90 : 0 : spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
91 : : {
92 [ # # # # ]: 0 : if (strncmp(transport_name, SPDK_NVME_TRANSPORT_NAME_RDMA, SPDK_NVMF_TRSTRING_MAX_LEN)) {
93 : 0 : return &g_transport;
94 : : }
95 : :
96 : 0 : return NULL;
97 : 0 : }
98 : :
99 : : int
100 : 0 : nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
101 : : struct spdk_nvmf_subsystem *subsystem)
102 : : {
103 : 0 : return 0;
104 : : }
105 : :
106 : : int
107 : 0 : nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
108 : : struct spdk_nvmf_subsystem *subsystem,
109 : : spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
110 : : {
111 : 0 : return 0;
112 : : }
113 : :
114 : : void
115 : 0 : nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group,
116 : : struct spdk_nvmf_subsystem *subsystem,
117 : : spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
118 : : {
119 : 0 : }
120 : :
121 : : void
122 : 0 : nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
123 : : struct spdk_nvmf_subsystem *subsystem,
124 : : uint32_t nsid,
125 : : spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
126 : : {
127 : 0 : }
128 : :
129 : : void
130 : 0 : nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
131 : : struct spdk_nvmf_subsystem *subsystem,
132 : : spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
133 : : {
134 : 0 : }
135 : :
136 : : int
137 : 0 : spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
138 : : {
139 [ # # # # ]: 0 : if (trtype == NULL || str == NULL) {
140 : 0 : return -EINVAL;
141 : : }
142 : :
143 [ # # # # ]: 0 : if (strcasecmp(str, "PCIe") == 0) {
144 : 0 : *trtype = SPDK_NVME_TRANSPORT_PCIE;
145 [ # # # # ]: 0 : } else if (strcasecmp(str, "RDMA") == 0) {
146 : 0 : *trtype = SPDK_NVME_TRANSPORT_RDMA;
147 : 0 : } else {
148 : 0 : return -ENOENT;
149 : : }
150 : 0 : return 0;
151 : 0 : }
152 : :
153 : : int
154 : 0 : spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
155 : : const struct spdk_nvme_transport_id *trid2)
156 : : {
157 : 0 : return 0;
158 : : }
159 : :
160 : : int32_t
161 : 0 : spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr)
162 : : {
163 : 0 : return -1;
164 : : }
165 : :
166 : : int32_t
167 : 0 : spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
168 : : {
169 : 0 : return -1;
170 : : }
171 : :
172 : : int
173 : 0 : spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
174 : : {
175 : 0 : return -1;
176 : : }
177 : :
178 : : void
179 : 0 : nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
180 : : {
181 : 0 : }
182 : :
183 : : static struct spdk_nvmf_ctrlr *g_ns_changed_ctrlr = NULL;
184 : : static uint32_t g_ns_changed_nsid = 0;
185 : : void
186 : 18 : nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
187 : : {
188 : 18 : g_ns_changed_ctrlr = ctrlr;
189 : 18 : g_ns_changed_nsid = nsid;
190 : 18 : }
191 : :
192 : :
193 : : static struct spdk_nvmf_ctrlr *g_async_event_ctrlr = NULL;
194 : : int
195 : 9 : nvmf_ctrlr_async_event_ns_notice(struct spdk_nvmf_ctrlr *ctrlr)
196 : : {
197 : 9 : g_async_event_ctrlr = ctrlr;
198 : 9 : return 0;
199 : : }
200 : :
201 : : static struct spdk_bdev g_bdevs[] = {
202 : : { .name = "bdev1" },
203 : : { .name = "bdev2" },
204 : : { .name = "bdev3", .ctratt.raw = 0x80000 },
205 : : };
206 : :
207 : : struct spdk_bdev_desc {
208 : : struct spdk_bdev *bdev;
209 : : };
210 : :
211 : : int
212 : 15 : spdk_bdev_open_ext_v2(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
213 : : void *event_ctx, struct spdk_bdev_open_opts *opts,
214 : : struct spdk_bdev_desc **_desc)
215 : : {
216 : : struct spdk_bdev_desc *desc;
217 : : size_t i;
218 : :
219 [ + - ]: 27 : for (i = 0; i < sizeof(g_bdevs); i++) {
220 [ + + - + : 27 : if (strcmp(bdev_name, g_bdevs[i].name) == 0) {
+ + ]
221 : :
222 : 15 : desc = calloc(1, sizeof(*desc));
223 [ - + ]: 15 : SPDK_CU_ASSERT_FATAL(desc != NULL);
224 : :
225 : 15 : desc->bdev = &g_bdevs[i];
226 : 15 : *_desc = desc;
227 : 15 : return 0;
228 : : }
229 : 4 : }
230 : :
231 : 0 : return -EINVAL;
232 : 5 : }
233 : :
234 : : void
235 : 15 : spdk_bdev_open_opts_init(struct spdk_bdev_open_opts *opts, size_t opts_size)
236 : : {
237 [ - + ]: 15 : memset(opts, 0, opts_size);
238 : 15 : }
239 : :
240 : : void
241 : 18 : spdk_bdev_close(struct spdk_bdev_desc *desc)
242 : : {
243 : 18 : free(desc);
244 : 18 : }
245 : :
246 : : struct spdk_bdev *
247 : 15 : spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
248 : : {
249 : 15 : return desc->bdev;
250 : : }
251 : :
252 : : const char *
253 : 0 : spdk_bdev_get_name(const struct spdk_bdev *bdev)
254 : : {
255 : 0 : return "test";
256 : : }
257 : :
258 : : const struct spdk_uuid *
259 : 63 : spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
260 : : {
261 : 63 : return &bdev->uuid;
262 : : }
263 : :
264 : 21 : union spdk_bdev_nvme_ctratt spdk_bdev_get_nvme_ctratt(struct spdk_bdev *bdev)
265 : : {
266 : 21 : return bdev->ctratt;
267 : : }
268 : :
269 : : static void
270 : 3 : test_spdk_nvmf_subsystem_add_ns(void)
271 : : {
272 : 3 : struct spdk_nvmf_tgt tgt = {};
273 : 3 : struct spdk_nvmf_subsystem subsystem = {
274 : : .max_nsid = 1024,
275 : : .ns = NULL,
276 : : .tgt = &tgt,
277 : : };
278 : 2 : struct spdk_nvmf_ns_opts ns_opts;
279 : : uint32_t nsid;
280 : : int rc;
281 : :
282 : 3 : subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
283 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
284 : 3 : subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
285 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
286 : :
287 : 3 : tgt.max_subsystems = 1024;
288 : 3 : RB_INIT(&tgt.subsystems);
289 : :
290 : : /* Request a specific NSID */
291 : 3 : spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
292 : 3 : ns_opts.nsid = 5;
293 : 3 : nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
294 : 3 : CU_ASSERT(nsid == 5);
295 : 3 : CU_ASSERT(subsystem.max_nsid == 1024);
296 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
297 : 3 : CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[1]);
298 : :
299 : : /* Request an NSID that is already in use */
300 : 3 : spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
301 : 3 : ns_opts.nsid = 5;
302 : 3 : nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
303 : 3 : CU_ASSERT(nsid == 0);
304 : 3 : CU_ASSERT(subsystem.max_nsid == 1024);
305 : :
306 : : /* Request 0xFFFFFFFF (invalid NSID, reserved for broadcast) */
307 : 3 : spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
308 : 3 : ns_opts.nsid = 0xFFFFFFFF;
309 : 3 : nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
310 : 3 : CU_ASSERT(nsid == 0);
311 : 3 : CU_ASSERT(subsystem.max_nsid == 1024);
312 : :
313 : 3 : rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 5);
314 : 3 : CU_ASSERT(rc == 0);
315 : :
316 : 3 : free(subsystem.ns);
317 : 3 : free(subsystem.ana_group);
318 : 3 : }
319 : :
320 : : static void
321 : 3 : test_spdk_nvmf_subsystem_add_fdp_ns(void)
322 : : {
323 : 3 : struct spdk_nvmf_tgt tgt = {};
324 : 3 : struct spdk_nvmf_subsystem subsystem = {
325 : : .max_nsid = 1024,
326 : : .ns = NULL,
327 : : .tgt = &tgt,
328 : : };
329 : 2 : struct spdk_nvmf_ns_opts ns_opts;
330 : : uint32_t nsid;
331 : : int rc;
332 : :
333 : 3 : subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
334 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
335 : 3 : subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
336 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
337 : :
338 : 3 : tgt.max_subsystems = 1024;
339 : 3 : RB_INIT(&tgt.subsystems);
340 : :
341 [ - + ]: 3 : CU_ASSERT(subsystem.fdp_supported == false);
342 : :
343 : : /* Add a FDP supported namespace to the subsystem */
344 : 3 : spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
345 : 3 : ns_opts.nsid = 3;
346 : 3 : nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev3", &ns_opts, sizeof(ns_opts), NULL);
347 : 3 : CU_ASSERT(nsid == 3);
348 : 3 : CU_ASSERT(subsystem.max_nsid == 1024);
349 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ns[nsid - 1] != NULL);
350 : 3 : CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[2]);
351 [ - + ]: 3 : CU_ASSERT(subsystem.fdp_supported == true);
352 : :
353 : : /* Try to add a non FDP supported namespace to the subsystem */
354 : 3 : spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
355 : 3 : ns_opts.nsid = 5;
356 : 3 : nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev2", &ns_opts, sizeof(ns_opts), NULL);
357 : 3 : CU_ASSERT(nsid == 0);
358 : 3 : CU_ASSERT(subsystem.max_nsid == 1024);
359 [ - + ]: 3 : CU_ASSERT(subsystem.fdp_supported == true);
360 : :
361 : : /* Remove last FDP namespace from the subsystem */
362 : 3 : rc = spdk_nvmf_subsystem_remove_ns(&subsystem, 3);
363 : 3 : CU_ASSERT(rc == 0);
364 [ - + ]: 3 : CU_ASSERT(subsystem.fdp_supported == false);
365 : :
366 : 3 : free(subsystem.ns);
367 : 3 : free(subsystem.ana_group);
368 : 3 : }
369 : :
370 : : static void
371 : 3 : nvmf_test_create_subsystem(void)
372 : : {
373 : 3 : struct spdk_nvmf_tgt tgt = {};
374 : 2 : char nqn[256];
375 : : struct spdk_nvmf_subsystem *subsystem;
376 : : int rc;
377 : :
378 : 3 : tgt.max_subsystems = 1024;
379 : 3 : tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
380 : 3 : RB_INIT(&tgt.subsystems);
381 : :
382 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
383 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
384 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
385 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
386 : 3 : rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
387 : 3 : CU_ASSERT(rc == 0);
388 : :
389 : : /* valid name with complex reverse domain */
390 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-full--rev-domain.name:subsystem1");
391 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
392 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
393 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
394 : 3 : rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
395 : 3 : CU_ASSERT(rc == 0);
396 : :
397 : : /* Valid name discovery controller */
398 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
399 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
400 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
401 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
402 : 3 : rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
403 : 3 : CU_ASSERT(rc == 0);
404 : :
405 : : /* Invalid name, no user supplied string */
406 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
407 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
408 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
409 : :
410 : : /* Valid name, only contains top-level domain name */
411 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:subsystem1");
412 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
413 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
414 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
415 : 3 : rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
416 : 3 : CU_ASSERT(rc == 0);
417 : :
418 : : /* Invalid name, domain label > 63 characters */
419 : 3 : snprintf(nqn, sizeof(nqn),
420 : : "nqn.2016-06.io.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz:sub");
421 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
422 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
423 : :
424 : : /* Invalid name, domain label starts with digit */
425 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.3spdk:sub");
426 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
427 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
428 : :
429 : : /* Invalid name, domain label starts with - */
430 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.-spdk:subsystem1");
431 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
432 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
433 : :
434 : : /* Invalid name, domain label ends with - */
435 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk-:subsystem1");
436 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
437 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
438 : :
439 : : /* Invalid name, domain label with multiple consecutive periods */
440 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io..spdk:subsystem1");
441 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
442 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
443 : :
444 : : /* Longest valid name */
445 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
446 [ - + ]: 3 : memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn));
447 : 3 : nqn[223] = '\0';
448 : 3 : CU_ASSERT(strlen(nqn) == 223);
449 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
450 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
451 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
452 : 3 : rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
453 : 3 : CU_ASSERT(rc == 0);
454 : :
455 : : /* Invalid name, too long */
456 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:");
457 [ - + ]: 3 : memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn));
458 : 3 : nqn[224] = '\0';
459 : 3 : CU_ASSERT(strlen(nqn) == 224);
460 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
461 : 3 : CU_ASSERT(subsystem == NULL);
462 : :
463 : : /* Valid name using uuid format */
464 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:ff9b6406-0fc8-4779-80ca-4dca14bda0d2");
465 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
466 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
467 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
468 : 3 : rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
469 : 3 : CU_ASSERT(rc == 0);
470 : :
471 : : /* Invalid name user string contains an invalid utf-8 character */
472 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xFFsubsystem1");
473 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
474 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
475 : :
476 : : /* Valid name with non-ascii but valid utf-8 characters */
477 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2016-06.io.spdk:\xe1\x8a\x88subsystem1\xca\x80");
478 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
479 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
480 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn);
481 : 3 : rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
482 : 3 : CU_ASSERT(rc == 0);
483 : :
484 : : /* Invalid uuid (too long) */
485 : 3 : snprintf(nqn, sizeof(nqn),
486 : : "nqn.2014-08.org.nvmexpress:uuid:ff9b6406-0fc8-4779-80ca-4dca14bda0d2aaaa");
487 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
488 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
489 : :
490 : : /* Invalid uuid (dashes placed incorrectly) */
491 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:ff9b64-060fc8-4779-80ca-4dca14bda0d2");
492 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
493 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
494 : :
495 : : /* Invalid uuid (invalid characters in uuid) */
496 : 3 : snprintf(nqn, sizeof(nqn), "nqn.2014-08.org.nvmexpress:uuid:ff9hg406-0fc8-4779-80ca-4dca14bda0d2");
497 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
498 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem == NULL);
499 : :
500 : 3 : spdk_bit_array_free(&tgt.subsystem_ids);
501 : 3 : }
502 : :
503 : : static void
504 : 3 : test_spdk_nvmf_subsystem_set_sn(void)
505 : : {
506 : 3 : struct spdk_nvmf_subsystem subsystem = {};
507 : :
508 : : /* Basic valid serial number */
509 : 3 : CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd xyz") == 0);
510 : 3 : CU_ASSERT(strcmp(subsystem.sn, "abcd xyz") == 0);
511 : :
512 : : /* Exactly 20 characters (valid) */
513 : 3 : CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "12345678901234567890") == 0);
514 : 3 : CU_ASSERT(strcmp(subsystem.sn, "12345678901234567890") == 0);
515 : :
516 : : /* 21 characters (too long, invalid) */
517 : 3 : CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "123456789012345678901") < 0);
518 : :
519 : : /* Non-ASCII characters (invalid) */
520 : 3 : CU_ASSERT(spdk_nvmf_subsystem_set_sn(&subsystem, "abcd\txyz") < 0);
521 : 3 : }
522 : :
523 : : static void
524 : 3 : test_spdk_nvmf_ns_visible(void)
525 : : {
526 : 3 : struct spdk_nvmf_subsystem subsystem = {};
527 : 3 : struct spdk_nvmf_ns ns1 = {
528 : : .nsid = 1,
529 : : .anagrpid = 1,
530 : : .always_visible = false
531 : : };
532 : 3 : struct spdk_nvmf_ns ns2 = {
533 : : .nsid = 2,
534 : : .anagrpid = 2,
535 : : .always_visible = false
536 : : };
537 : : struct spdk_nvmf_ns *ns3;
538 : 3 : struct spdk_nvmf_ctrlr ctrlrA = {
539 : : .subsys = &subsystem
540 : : };
541 : 3 : struct spdk_nvmf_ctrlr ctrlrB = {
542 : : .subsys = &subsystem
543 : : };
544 : : struct spdk_thread *thread;
545 : 3 : struct spdk_nvmf_tgt tgt = {};
546 : : uint32_t nsid;
547 : : int rc;
548 : :
549 : 3 : thread = spdk_get_thread();
550 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(thread != NULL);
551 : 3 : ctrlrA.thread = thread;
552 : 3 : ctrlrB.thread = thread;
553 : :
554 : 3 : subsystem.max_nsid = 1024;
555 : 3 : subsystem.ns = calloc(subsystem.max_nsid, sizeof(subsystem.ns));
556 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
557 : 3 : subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
558 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
559 : 3 : TAILQ_INIT(&tgt.transports);
560 : 3 : subsystem.tgt = &tgt;
561 : :
562 : 3 : subsystem.ns[1] = &ns1;
563 : 3 : subsystem.ns[2] = &ns2;
564 : 3 : ns3 = calloc(1, sizeof(*ns3));
565 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(ns3 != NULL);
566 : 3 : ns3->nsid = 3;
567 : 3 : ns3->anagrpid = 3;
568 : 3 : subsystem.ana_group[ns3->anagrpid - 1] = 1;
569 : 3 : subsystem.ns[3] = ns3;
570 : :
571 [ - + ]: 3 : snprintf(ctrlrA.hostnqn, sizeof(ctrlrA.hostnqn), "nqn.2016-06.io.spdk:host1");
572 : 3 : ctrlrA.visible_ns = spdk_bit_array_create(subsystem.max_nsid);
573 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlrA.visible_ns != NULL);
574 [ - + ]: 3 : snprintf(ctrlrB.hostnqn, sizeof(ctrlrB.hostnqn), "nqn.2016-06.io.spdk:host2");
575 : 3 : ctrlrB.visible_ns = spdk_bit_array_create(subsystem.max_nsid);
576 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ctrlrB.visible_ns != NULL);
577 : :
578 : : /* Add two controllers ctrlrA and ctrlrB */
579 : 3 : TAILQ_INIT(&subsystem.ctrlrs);
580 : 3 : TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlrA, link);
581 : 3 : TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlrB, link);
582 : :
583 : : /* Invalid host nqn */
584 : 3 : nsid = 1;
585 : 3 : rc = spdk_nvmf_ns_add_host(&subsystem, nsid, "", 0);
586 : 3 : CU_ASSERT(rc == -EINVAL);
587 : 3 : rc = spdk_nvmf_ns_add_host(&subsystem, nsid, NULL, 0);
588 : 3 : CU_ASSERT(rc == -EINVAL);
589 : 3 : rc = spdk_nvmf_ns_remove_host(&subsystem, nsid, NULL, 0);
590 : 3 : CU_ASSERT(rc == -EINVAL);
591 : :
592 : : /* Invalid nsid */
593 : 3 : nsid = 0;
594 : 3 : rc = spdk_nvmf_ns_add_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
595 : 3 : CU_ASSERT(rc == -EINVAL);
596 : 3 : rc = spdk_nvmf_ns_remove_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
597 : 3 : CU_ASSERT(rc == -EINVAL);
598 : :
599 : : /* Unallocated ns */
600 : 3 : nsid = 1;
601 : 3 : rc = spdk_nvmf_ns_add_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
602 : 3 : CU_ASSERT(rc == -ENOENT);
603 : 3 : rc = spdk_nvmf_ns_remove_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
604 : 3 : CU_ASSERT(rc == -ENOENT);
605 : :
606 : : /* Attach any is active => do not allow individual host control */
607 : 3 : ns1.always_visible = true;
608 : 3 : nsid = 2;
609 : 3 : rc = spdk_nvmf_ns_add_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
610 : 3 : CU_ASSERT(rc == -EPERM);
611 : 3 : rc = spdk_nvmf_ns_remove_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
612 : 3 : CU_ASSERT(rc == -EPERM);
613 : 3 : ns1.always_visible = false;
614 : :
615 : : /* Attach ctrlrA to namespace 2 hot + cold */
616 : 3 : nsid = 2;
617 : 3 : g_async_event_ctrlr = NULL;
618 : 3 : g_ns_changed_ctrlr = NULL;
619 : 3 : g_ns_changed_nsid = 0;
620 : 3 : rc = spdk_nvmf_ns_add_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
621 : 3 : CU_ASSERT(rc == 0);
622 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns1, ctrlrA.hostnqn) != NULL);
623 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns1, ctrlrB.hostnqn) == NULL);
624 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns2, ctrlrA.hostnqn) == NULL);
625 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns2, ctrlrB.hostnqn) == NULL);
626 : 3 : CU_ASSERT(nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid));
627 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid));
628 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid + 1));
629 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid + 1));
630 : : /* check last ns_changed */
631 : 3 : CU_ASSERT(g_ns_changed_ctrlr == &ctrlrA);
632 : 3 : CU_ASSERT(g_ns_changed_nsid == nsid);
633 : : /* check async_event */
634 : 3 : poll_threads();
635 : 3 : CU_ASSERT(g_async_event_ctrlr == &ctrlrA);
636 : :
637 : : /* Attach ctrlrA to namespace 2 again => should not create any ns change/async event */
638 : 3 : g_async_event_ctrlr = NULL;
639 : 3 : g_ns_changed_ctrlr = NULL;
640 : 3 : g_ns_changed_nsid = 0;
641 : 3 : rc = spdk_nvmf_ns_add_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
642 : 3 : CU_ASSERT(rc == 0);
643 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns1, ctrlrA.hostnqn) != NULL);
644 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns1, ctrlrB.hostnqn) == NULL);
645 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns2, ctrlrA.hostnqn) == NULL);
646 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns2, ctrlrB.hostnqn) == NULL);
647 : 3 : CU_ASSERT(nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid));
648 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid));
649 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid + 1));
650 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid + 1));
651 : : /* check last ns_changed */
652 : 3 : CU_ASSERT(g_ns_changed_ctrlr == NULL);
653 : 3 : CU_ASSERT(g_ns_changed_nsid == 0);
654 : : /* check async_event */
655 : 3 : poll_threads();
656 : 3 : CU_ASSERT(g_async_event_ctrlr == NULL);
657 : :
658 : : /* Detach ctrlrA from namespace 2 hot + cold */
659 : 3 : g_async_event_ctrlr = NULL;
660 : 3 : g_ns_changed_ctrlr = NULL;
661 : 3 : g_ns_changed_nsid = 0;
662 : 3 : rc = spdk_nvmf_ns_remove_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
663 : 3 : CU_ASSERT(rc == 0);
664 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns1, ctrlrA.hostnqn) == NULL);
665 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns1, ctrlrB.hostnqn) == NULL);
666 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns2, ctrlrA.hostnqn) == NULL);
667 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns2, ctrlrB.hostnqn) == NULL);
668 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid));
669 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid));
670 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid + 1));
671 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid + 1));
672 : : /* check last ns_changed */
673 : 3 : CU_ASSERT(g_ns_changed_ctrlr == &ctrlrA);
674 : 3 : CU_ASSERT(g_ns_changed_nsid == nsid);
675 : : /* check async_event */
676 : 3 : poll_threads();
677 : 3 : CU_ASSERT(g_async_event_ctrlr == &ctrlrA);
678 : :
679 : : /* Detach ctrlrA from namespace 2 again hot + cold */
680 : 3 : g_async_event_ctrlr = NULL;
681 : 3 : g_ns_changed_ctrlr = NULL;
682 : 3 : g_ns_changed_nsid = 0;
683 : 3 : rc = spdk_nvmf_ns_remove_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
684 : 3 : CU_ASSERT(rc == 0);
685 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns1, ctrlrA.hostnqn) == NULL);
686 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns1, ctrlrB.hostnqn) == NULL);
687 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns2, ctrlrA.hostnqn) == NULL);
688 : 3 : CU_ASSERT(nvmf_ns_find_host(&ns2, ctrlrB.hostnqn) == NULL);
689 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid));
690 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid));
691 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid + 1));
692 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid + 1));
693 : : /* check last ns_changed */
694 : 3 : CU_ASSERT(g_ns_changed_ctrlr == NULL);
695 : 3 : CU_ASSERT(g_ns_changed_nsid == 0);
696 : : /* check async_event */
697 : 3 : poll_threads();
698 : 3 : CU_ASSERT(g_async_event_ctrlr == NULL);
699 : :
700 : : /* Attach ctrlrA to namespace 4 hot + cold => remove ns */
701 : 3 : nsid = 4;
702 : 3 : g_async_event_ctrlr = NULL;
703 : 3 : g_ns_changed_ctrlr = NULL;
704 : 3 : g_ns_changed_nsid = 0;
705 : 3 : rc = spdk_nvmf_ns_add_host(&subsystem, nsid, ctrlrA.hostnqn, 0);
706 : 3 : CU_ASSERT(rc == 0);
707 : 3 : CU_ASSERT(nvmf_ns_find_host(ns3, ctrlrA.hostnqn) != NULL);
708 : 3 : CU_ASSERT(nvmf_ns_find_host(ns3, ctrlrB.hostnqn) == NULL);
709 : 3 : CU_ASSERT(nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid));
710 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid));
711 : : /* check last ns_changed */
712 : 3 : CU_ASSERT(g_ns_changed_ctrlr == &ctrlrA);
713 : 3 : CU_ASSERT(g_ns_changed_nsid == nsid);
714 : : /* check async_event */
715 : 3 : poll_threads();
716 : 3 : CU_ASSERT(g_async_event_ctrlr == &ctrlrA);
717 : :
718 : 3 : g_async_event_ctrlr = NULL;
719 : 3 : g_ns_changed_ctrlr = NULL;
720 : 3 : g_ns_changed_nsid = 0;
721 : 3 : rc = spdk_nvmf_subsystem_remove_ns(&subsystem, nsid);
722 : 3 : CU_ASSERT(rc == 0);
723 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrA, nsid));
724 : 3 : CU_ASSERT(!nvmf_ctrlr_ns_is_visible(&ctrlrB, nsid));
725 : : /* check last ns_changed */
726 : 3 : CU_ASSERT(g_ns_changed_ctrlr == &ctrlrA);
727 : 3 : CU_ASSERT(g_ns_changed_nsid == nsid);
728 : :
729 : 3 : free(ctrlrA.visible_ns);
730 : 3 : free(ctrlrB.visible_ns);
731 : 3 : free(subsystem.ana_group);
732 : 3 : free(subsystem.ns);
733 : 3 : }
734 : :
735 : : /*
736 : : * Reservation Unit Test Configuration
737 : : * -------- -------- --------
738 : : * | Host A | | Host B | | Host C |
739 : : * -------- -------- --------
740 : : * / \ | |
741 : : * -------- -------- ------- -------
742 : : * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C|
743 : : * -------- -------- ------- -------
744 : : * \ \ / /
745 : : * \ \ / /
746 : : * \ \ / /
747 : : * --------------------------------------
748 : : * | NAMESPACE 1 |
749 : : * --------------------------------------
750 : : */
751 : : static struct spdk_nvmf_subsystem g_subsystem;
752 : : static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C;
753 : : static struct spdk_nvmf_ns g_ns;
754 : : struct spdk_nvmf_subsystem_pg_ns_info g_ns_info;
755 : :
756 : : void
757 : 0 : nvmf_ctrlr_async_event_reservation_notification(struct spdk_nvmf_ctrlr *ctrlr)
758 : : {
759 : 0 : }
760 : :
761 : : static void
762 : 33 : ut_reservation_init(void)
763 : : {
764 : :
765 : 33 : TAILQ_INIT(&g_subsystem.ctrlrs);
766 : :
767 [ - + ]: 33 : memset(&g_ns, 0, sizeof(g_ns));
768 : 33 : TAILQ_INIT(&g_ns.registrants);
769 : 33 : g_ns.subsystem = &g_subsystem;
770 : 33 : g_ns.ptpl_file = NULL;
771 : 33 : g_ns.ptpl_activated = false;
772 : 33 : spdk_uuid_generate(&g_bdevs[0].uuid);
773 : 33 : g_ns.bdev = &g_bdevs[0];
774 : :
775 : : /* Host A has two controllers */
776 : 33 : spdk_uuid_generate(&g_ctrlr1_A.hostid);
777 : 33 : TAILQ_INIT(&g_ctrlr1_A.log_head);
778 : 33 : g_ctrlr1_A.subsys = &g_subsystem;
779 : 33 : g_ctrlr1_A.num_avail_log_pages = 0;
780 : 33 : TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr1_A, link);
781 : 33 : spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid);
782 : 33 : TAILQ_INIT(&g_ctrlr2_A.log_head);
783 : 33 : g_ctrlr2_A.subsys = &g_subsystem;
784 : 33 : g_ctrlr2_A.num_avail_log_pages = 0;
785 : 33 : TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr2_A, link);
786 : :
787 : : /* Host B has 1 controller */
788 : 33 : spdk_uuid_generate(&g_ctrlr_B.hostid);
789 : 33 : TAILQ_INIT(&g_ctrlr_B.log_head);
790 : 33 : g_ctrlr_B.subsys = &g_subsystem;
791 : 33 : g_ctrlr_B.num_avail_log_pages = 0;
792 : 33 : TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_B, link);
793 : :
794 : : /* Host C has 1 controller */
795 : 33 : spdk_uuid_generate(&g_ctrlr_C.hostid);
796 : 33 : TAILQ_INIT(&g_ctrlr_C.log_head);
797 : 33 : g_ctrlr_C.subsys = &g_subsystem;
798 : 33 : g_ctrlr_C.num_avail_log_pages = 0;
799 : 33 : TAILQ_INSERT_TAIL(&g_subsystem.ctrlrs, &g_ctrlr_C, link);
800 : 33 : }
801 : :
802 : : static void
803 : 33 : ut_reservation_deinit(void)
804 : : {
805 : : struct spdk_nvmf_registrant *reg, *tmp;
806 : : struct spdk_nvmf_reservation_log *log, *log_tmp;
807 : : struct spdk_nvmf_ctrlr *ctrlr, *ctrlr_tmp;
808 : :
809 [ + + + + ]: 78 : TAILQ_FOREACH_SAFE(reg, &g_ns.registrants, link, tmp) {
810 [ + + ]: 45 : TAILQ_REMOVE(&g_ns.registrants, reg, link);
811 : 45 : free(reg);
812 : 15 : }
813 [ + + - + ]: 33 : TAILQ_FOREACH_SAFE(log, &g_ctrlr1_A.log_head, link, log_tmp) {
814 [ # # ]: 0 : TAILQ_REMOVE(&g_ctrlr1_A.log_head, log, link);
815 : 0 : free(log);
816 : 0 : }
817 : 33 : g_ctrlr1_A.num_avail_log_pages = 0;
818 [ + + - + ]: 33 : TAILQ_FOREACH_SAFE(log, &g_ctrlr2_A.log_head, link, log_tmp) {
819 [ # # ]: 0 : TAILQ_REMOVE(&g_ctrlr2_A.log_head, log, link);
820 : 0 : free(log);
821 : 0 : }
822 : 33 : g_ctrlr2_A.num_avail_log_pages = 0;
823 [ + + - + ]: 33 : TAILQ_FOREACH_SAFE(log, &g_ctrlr_B.log_head, link, log_tmp) {
824 [ # # ]: 0 : TAILQ_REMOVE(&g_ctrlr_B.log_head, log, link);
825 : 0 : free(log);
826 : 0 : }
827 : 33 : g_ctrlr_B.num_avail_log_pages = 0;
828 [ + + - + ]: 33 : TAILQ_FOREACH_SAFE(log, &g_ctrlr_C.log_head, link, log_tmp) {
829 [ # # ]: 0 : TAILQ_REMOVE(&g_ctrlr_C.log_head, log, link);
830 : 0 : free(log);
831 : 0 : }
832 : 33 : g_ctrlr_C.num_avail_log_pages = 0;
833 : :
834 [ + + + + ]: 165 : TAILQ_FOREACH_SAFE(ctrlr, &g_subsystem.ctrlrs, link, ctrlr_tmp) {
835 [ + + ]: 132 : TAILQ_REMOVE(&g_subsystem.ctrlrs, ctrlr, link);
836 : 44 : }
837 : 33 : }
838 : :
839 : : static struct spdk_nvmf_request *
840 : 57 : ut_reservation_build_req(uint32_t length)
841 : : {
842 : : struct spdk_nvmf_request *req;
843 : :
844 : 57 : req = calloc(1, sizeof(*req));
845 [ + + ]: 57 : assert(req != NULL);
846 : :
847 : 57 : SPDK_IOV_ONE(req->iov, &req->iovcnt, calloc(1, length), length);
848 [ + + ]: 57 : assert(req->iov[0].iov_base != NULL);
849 : 57 : req->length = length;
850 : :
851 : 57 : req->cmd = (union nvmf_h2c_msg *)calloc(1, sizeof(union nvmf_h2c_msg));
852 [ + + ]: 57 : assert(req->cmd != NULL);
853 : :
854 : 57 : req->rsp = (union nvmf_c2h_msg *)calloc(1, sizeof(union nvmf_c2h_msg));
855 [ + + ]: 57 : assert(req->rsp != NULL);
856 : :
857 : 57 : return req;
858 : : }
859 : :
860 : : static void
861 : 57 : ut_reservation_free_req(struct spdk_nvmf_request *req)
862 : : {
863 : 57 : free(req->cmd);
864 : 57 : free(req->rsp);
865 : 57 : free(req->iov[0].iov_base);
866 : 57 : free(req);
867 : 57 : }
868 : :
869 : : static void
870 : 135 : ut_reservation_build_register_request(struct spdk_nvmf_request *req,
871 : : uint8_t rrega, uint8_t iekey,
872 : : uint8_t cptpl, uint64_t crkey,
873 : : uint64_t nrkey)
874 : : {
875 : 90 : struct spdk_nvme_reservation_register_data key;
876 : 135 : struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
877 : :
878 : 135 : key.crkey = crkey;
879 : 135 : key.nrkey = nrkey;
880 : 135 : cmd->cdw10 = 0;
881 : 135 : cmd->cdw10_bits.resv_register.rrega = rrega;
882 : 135 : cmd->cdw10_bits.resv_register.iekey = iekey;
883 : 135 : cmd->cdw10_bits.resv_register.cptpl = cptpl;
884 : 135 : memcpy(req->iov[0].iov_base, &key, sizeof(key));
885 : 135 : }
886 : :
887 : : static void
888 : 39 : ut_reservation_build_acquire_request(struct spdk_nvmf_request *req,
889 : : uint8_t racqa, uint8_t iekey,
890 : : uint8_t rtype, uint64_t crkey,
891 : : uint64_t prkey)
892 : : {
893 : 26 : struct spdk_nvme_reservation_acquire_data key;
894 : 39 : struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
895 : :
896 : 39 : key.crkey = crkey;
897 : 39 : key.prkey = prkey;
898 : 39 : cmd->cdw10 = 0;
899 : 39 : cmd->cdw10_bits.resv_acquire.racqa = racqa;
900 : 39 : cmd->cdw10_bits.resv_acquire.iekey = iekey;
901 : 39 : cmd->cdw10_bits.resv_acquire.rtype = rtype;
902 : 39 : memcpy(req->iov[0].iov_base, &key, sizeof(key));
903 : 39 : }
904 : :
905 : : static void
906 : 18 : ut_reservation_build_release_request(struct spdk_nvmf_request *req,
907 : : uint8_t rrela, uint8_t iekey,
908 : : uint8_t rtype, uint64_t crkey)
909 : : {
910 : 18 : struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
911 : :
912 : 18 : cmd->cdw10 = 0;
913 : 18 : cmd->cdw10_bits.resv_release.rrela = rrela;
914 : 18 : cmd->cdw10_bits.resv_release.iekey = iekey;
915 : 18 : cmd->cdw10_bits.resv_release.rtype = rtype;
916 : 18 : memcpy(req->iov[0].iov_base, &crkey, sizeof(crkey));
917 : 18 : }
918 : :
919 : : /*
920 : : * Construct four registrants for other test cases.
921 : : *
922 : : * g_ctrlr1_A register with key 0xa1.
923 : : * g_ctrlr2_A register with key 0xa1.
924 : : * g_ctrlr_B register with key 0xb1.
925 : : * g_ctrlr_C register with key 0xc1.
926 : : * */
927 : : static void
928 : 24 : ut_reservation_build_registrants(void)
929 : : {
930 : : struct spdk_nvmf_request *req;
931 : : struct spdk_nvme_cpl *rsp;
932 : : struct spdk_nvmf_registrant *reg;
933 : : uint32_t gen;
934 : :
935 : 24 : req = ut_reservation_build_req(16);
936 : 24 : rsp = &req->rsp->nvme_cpl;
937 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(req != NULL);
938 : 24 : gen = g_ns.gen;
939 : :
940 : : /* TEST CASE: g_ctrlr1_A register with a new key */
941 : 24 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
942 : : 0, 0, 0, 0xa1);
943 : 24 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
944 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
945 : 24 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
946 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa1);
947 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 1);
948 : :
949 : : /* TEST CASE: g_ctrlr2_A register with a new key, because it has same
950 : : * Host Identifier with g_ctrlr1_A, so the register key should same.
951 : : */
952 : 24 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
953 : : 0, 0, 0, 0xa2);
954 : 24 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr2_A, req);
955 : : /* Reservation conflict for other key than 0xa1 */
956 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT);
957 : :
958 : : /* g_ctrlr_B register with a new key */
959 : 24 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
960 : : 0, 0, 0, 0xb1);
961 : 24 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
962 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
963 : 24 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
964 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb1);
965 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 2);
966 : :
967 : : /* g_ctrlr_C register with a new key */
968 : 24 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY,
969 : : 0, 0, 0, 0xc1);
970 : 24 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
971 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
972 : 24 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
973 [ + + ]: 24 : SPDK_CU_ASSERT_FATAL(reg->rkey == 0xc1);
974 [ - + ]: 24 : SPDK_CU_ASSERT_FATAL(g_ns.gen == gen + 3);
975 : :
976 : 24 : ut_reservation_free_req(req);
977 : 24 : }
978 : :
979 : : static void
980 : 3 : test_reservation_register(void)
981 : : {
982 : : struct spdk_nvmf_request *req;
983 : : struct spdk_nvme_cpl *rsp;
984 : : struct spdk_nvmf_registrant *reg;
985 : : uint32_t gen;
986 : :
987 : 3 : ut_reservation_init();
988 : :
989 : 3 : req = ut_reservation_build_req(16);
990 : 3 : rsp = &req->rsp->nvme_cpl;
991 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
992 : :
993 : 3 : ut_reservation_build_registrants();
994 : :
995 : : /* TEST CASE: Replace g_ctrlr1_A with a new key */
996 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
997 : : 0, 0, 0xa1, 0xa11);
998 : 3 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
999 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1000 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1001 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg->rkey == 0xa11);
1002 : :
1003 : : /* TEST CASE: Host A with g_ctrlr1_A get reservation with
1004 : : * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
1005 : : */
1006 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1007 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xa11, 0x0);
1008 : 3 : gen = g_ns.gen;
1009 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
1010 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1011 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1012 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1013 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa11);
1014 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1015 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
1016 : :
1017 : : /* TEST CASE: g_ctrlr_C unregister with IEKEY enabled */
1018 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1019 : : 1, 0, 0, 0);
1020 : 3 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr_C, req);
1021 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1022 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
1023 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1024 : :
1025 : : /* TEST CASE: g_ctrlr_B unregister with correct key */
1026 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1027 : : 0, 0, 0xb1, 0);
1028 : 3 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1029 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1030 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1031 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1032 : :
1033 : : /* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY disabled */
1034 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
1035 : : 0, 0, 0, 0xb1);
1036 : 3 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1037 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
1038 : :
1039 : : /* TEST CASE: No registrant now, g_ctrlr_B replace new key with IEKEY enabled */
1040 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
1041 : : 1, 0, 0, 0xb1);
1042 : 3 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1043 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1044 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1045 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg != NULL);
1046 : :
1047 : : /* TEST CASE: g_ctrlr_B replace new key with IEKEY enabled and wrong crkey */
1048 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REPLACE_KEY,
1049 : : 1, 0, 0xff, 0xb2);
1050 : 3 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1051 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1052 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1053 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg != NULL);
1054 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg->rkey == 0xb2);
1055 : :
1056 : : /* TEST CASE: g_ctrlr1_A unregister with correct key,
1057 : : * reservation should be removed as well.
1058 : : */
1059 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1060 : : 0, 0, 0xa11, 0);
1061 : 3 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
1062 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1063 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1064 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1065 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1066 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
1067 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
1068 : :
1069 : 3 : ut_reservation_free_req(req);
1070 : 3 : ut_reservation_deinit();
1071 : 3 : }
1072 : :
1073 : : static void
1074 : 3 : test_reservation_register_with_ptpl(void)
1075 : : {
1076 : : struct spdk_nvmf_request *req;
1077 : : struct spdk_nvme_cpl *rsp;
1078 : : struct spdk_nvmf_registrant *reg;
1079 : 3 : bool update_sgroup = false;
1080 : : int rc;
1081 : 2 : struct spdk_nvmf_reservation_info info;
1082 : :
1083 : 3 : ut_reservation_init();
1084 : :
1085 : 3 : req = ut_reservation_build_req(16);
1086 : 3 : rsp = &req->rsp->nvme_cpl;
1087 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1088 : :
1089 : : /* TEST CASE: No persistent file, register with PTPL enabled will fail */
1090 : 3 : g_ns.ptpl_file = NULL;
1091 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
1092 : : SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
1093 : 3 : update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
1094 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(update_sgroup == false);
1095 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc != SPDK_NVME_SC_SUCCESS);
1096 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1097 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1098 : :
1099 : : /* TEST CASE: Enable PTPL */
1100 : 3 : g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
1101 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
1102 : : SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
1103 : 3 : update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
1104 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1105 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1106 [ + + - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
1107 : 3 : rc = nvmf_ns_update_reservation_info(&g_ns);
1108 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
1109 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1110 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg != NULL);
1111 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid));
1112 : : /* Load reservation information from configuration file */
1113 [ - + ]: 3 : memset(&info, 0, sizeof(info));
1114 : 3 : rc = nvmf_ns_reservation_load(&g_ns, &info);
1115 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
1116 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1117 : :
1118 : : /* TEST CASE: Disable PTPL */
1119 : 3 : rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
1120 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
1121 : : SPDK_NVME_RESERVE_PTPL_CLEAR_POWER_ON, 0, 0xa1);
1122 : 3 : update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
1123 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1124 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1125 [ + + - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == false);
1126 : 3 : rc = nvmf_ns_update_reservation_info(&g_ns);
1127 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
1128 : 3 : rc = nvmf_ns_reservation_load(&g_ns, &info);
1129 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc < 0);
1130 [ - + ]: 3 : unlink(g_ns.ptpl_file);
1131 : :
1132 : 3 : ut_reservation_free_req(req);
1133 : 3 : ut_reservation_deinit();
1134 : 3 : }
1135 : :
1136 : : static void
1137 : 3 : test_reservation_acquire_preempt_1(void)
1138 : : {
1139 : : struct spdk_nvmf_request *req;
1140 : : struct spdk_nvme_cpl *rsp;
1141 : : struct spdk_nvmf_registrant *reg;
1142 : : uint32_t gen;
1143 : :
1144 : 3 : ut_reservation_init();
1145 : :
1146 : 3 : req = ut_reservation_build_req(16);
1147 : 3 : rsp = &req->rsp->nvme_cpl;
1148 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1149 : :
1150 : 3 : ut_reservation_build_registrants();
1151 : :
1152 : 3 : gen = g_ns.gen;
1153 : : /* ACQUIRE: Host A with g_ctrlr1_A acquire reservation with
1154 : : * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE.
1155 : : */
1156 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1157 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
1158 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
1159 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1160 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1161 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1162 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0xa1);
1163 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1164 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.gen == gen);
1165 : :
1166 : : /* TEST CASE: g_ctrlr1_A holds the reservation, g_ctrlr_B preempt g_ctrl1_A,
1167 : : * g_ctrl1_A registrant is unregistered.
1168 : : */
1169 : 3 : gen = g_ns.gen;
1170 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1171 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1, 0xa1);
1172 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1173 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1174 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1175 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1176 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1177 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg != NULL);
1178 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1179 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
1180 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg != NULL);
1181 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1182 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
1183 : :
1184 : : /* TEST CASE: g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B
1185 : : * with valid key and PRKEY set to 0, all registrants other the host that issued
1186 : : * the command are unregistered.
1187 : : */
1188 : 3 : gen = g_ns.gen;
1189 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1190 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0x0);
1191 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
1192 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1193 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
1194 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1195 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1196 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1197 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
1198 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg != NULL);
1199 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1200 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1201 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.gen > gen);
1202 : :
1203 : 3 : ut_reservation_free_req(req);
1204 : 3 : ut_reservation_deinit();
1205 : 3 : }
1206 : :
1207 : : static void
1208 : 3 : test_reservation_acquire_release_with_ptpl(void)
1209 : : {
1210 : : struct spdk_nvmf_request *req;
1211 : : struct spdk_nvme_cpl *rsp;
1212 : : struct spdk_nvmf_registrant *reg;
1213 : 3 : bool update_sgroup = false;
1214 : 2 : struct spdk_uuid holder_uuid;
1215 : : int rc;
1216 : 2 : struct spdk_nvmf_reservation_info info;
1217 : :
1218 : 3 : ut_reservation_init();
1219 : :
1220 : 3 : req = ut_reservation_build_req(16);
1221 : 3 : rsp = &req->rsp->nvme_cpl;
1222 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1223 : :
1224 : : /* TEST CASE: Enable PTPL */
1225 : 3 : g_ns.ptpl_file = "/tmp/Ns1PR.cfg";
1226 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
1227 : : SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
1228 : 3 : update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
1229 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1230 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1231 [ + + - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
1232 : 3 : rc = nvmf_ns_update_reservation_info(&g_ns);
1233 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
1234 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1235 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg != NULL);
1236 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid));
1237 : : /* Load reservation information from configuration file */
1238 [ - + ]: 3 : memset(&info, 0, sizeof(info));
1239 : 3 : rc = nvmf_ns_reservation_load(&g_ns, &info);
1240 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
1241 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1242 : :
1243 : : /* TEST CASE: Acquire the reservation */
1244 : 3 : rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
1245 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1246 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
1247 : 3 : update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
1248 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1249 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1250 : 3 : rc = nvmf_ns_update_reservation_info(&g_ns);
1251 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
1252 [ - + ]: 3 : memset(&info, 0, sizeof(info));
1253 : 3 : rc = nvmf_ns_reservation_load(&g_ns, &info);
1254 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
1255 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1256 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(info.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1257 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(info.crkey == 0xa1);
1258 : 3 : spdk_uuid_parse(&holder_uuid, info.holder_uuid);
1259 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, &holder_uuid));
1260 : :
1261 : : /* TEST CASE: Release the reservation */
1262 : 3 : rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
1263 : 3 : ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1264 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1);
1265 : 3 : update_sgroup = nvmf_ns_reservation_release(&g_ns, &g_ctrlr1_A, req);
1266 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(update_sgroup == true);
1267 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1268 : 3 : rc = nvmf_ns_update_reservation_info(&g_ns);
1269 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
1270 [ - + ]: 3 : memset(&info, 0, sizeof(info));
1271 : 3 : rc = nvmf_ns_reservation_load(&g_ns, &info);
1272 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
1273 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(info.rtype == 0);
1274 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(info.crkey == 0);
1275 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(info.ptpl_activated == true);
1276 [ - + ]: 3 : unlink(g_ns.ptpl_file);
1277 : :
1278 : 3 : ut_reservation_free_req(req);
1279 : 3 : ut_reservation_deinit();
1280 : 3 : }
1281 : :
1282 : : static void
1283 : 3 : test_reservation_release(void)
1284 : : {
1285 : : struct spdk_nvmf_request *req;
1286 : : struct spdk_nvme_cpl *rsp;
1287 : : struct spdk_nvmf_registrant *reg;
1288 : :
1289 : 3 : ut_reservation_init();
1290 : :
1291 : 3 : req = ut_reservation_build_req(16);
1292 : 3 : rsp = &req->rsp->nvme_cpl;
1293 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1294 : :
1295 : 3 : ut_reservation_build_registrants();
1296 : :
1297 : : /* ACQUIRE: Host A with g_ctrlr1_A get reservation with
1298 : : * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS
1299 : : */
1300 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1301 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xa1, 0x0);
1302 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
1303 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1304 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1305 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1306 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.holder == reg);
1307 : :
1308 : : /* Test Case: Host B release the reservation */
1309 : 3 : ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1310 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xb1);
1311 : 3 : nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1312 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1313 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1314 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.crkey == 0);
1315 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.holder == NULL);
1316 : :
1317 : : /* Test Case: Host C clear the registrants */
1318 : 3 : ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1319 : : 0, 0xc1);
1320 : 3 : nvmf_ns_reservation_release(&g_ns, &g_ctrlr_C, req);
1321 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1322 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr1_A.hostid);
1323 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1324 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr2_A.hostid);
1325 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1326 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_B.hostid);
1327 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1328 : 3 : reg = nvmf_ns_reservation_get_registrant(&g_ns, &g_ctrlr_C.hostid);
1329 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(reg == NULL);
1330 : :
1331 : 3 : ut_reservation_free_req(req);
1332 : 3 : ut_reservation_deinit();
1333 : 3 : }
1334 : :
1335 : : void
1336 : 66 : nvmf_ctrlr_reservation_notice_log(struct spdk_nvmf_ctrlr *ctrlr,
1337 : : struct spdk_nvmf_ns *ns,
1338 : : enum spdk_nvme_reservation_notification_log_page_type type)
1339 : : {
1340 : 66 : ctrlr->num_avail_log_pages++;
1341 : 66 : }
1342 : :
1343 : : static void
1344 : 3 : test_reservation_unregister_notification(void)
1345 : : {
1346 : : struct spdk_nvmf_request *req;
1347 : : struct spdk_nvme_cpl *rsp;
1348 : :
1349 : 3 : ut_reservation_init();
1350 : :
1351 : 3 : req = ut_reservation_build_req(16);
1352 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1353 : 3 : rsp = &req->rsp->nvme_cpl;
1354 : :
1355 : 3 : ut_reservation_build_registrants();
1356 : :
1357 : : /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1358 : : * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1359 : : */
1360 : 3 : rsp->status.sc = 0xff;
1361 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1362 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1363 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1364 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1365 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1366 : :
1367 : : /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B unregister the registration.
1368 : : * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C only for
1369 : : * SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY or SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY
1370 : : * type.
1371 : : */
1372 : 3 : rsp->status.sc = 0xff;
1373 : 3 : g_ctrlr1_A.num_avail_log_pages = 0;
1374 : 3 : g_ctrlr2_A.num_avail_log_pages = 0;
1375 : 3 : g_ctrlr_B.num_avail_log_pages = 5;
1376 : 3 : g_ctrlr_C.num_avail_log_pages = 0;
1377 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_UNREGISTER_KEY,
1378 : : 0, 0, 0xb1, 0);
1379 : 3 : nvmf_ns_reservation_register(&g_ns, &g_ctrlr_B, req);
1380 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1381 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1382 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1383 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1384 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1385 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1386 : :
1387 : 3 : ut_reservation_free_req(req);
1388 : 3 : ut_reservation_deinit();
1389 : 3 : }
1390 : :
1391 : : static void
1392 : 3 : test_reservation_release_notification(void)
1393 : : {
1394 : : struct spdk_nvmf_request *req;
1395 : : struct spdk_nvme_cpl *rsp;
1396 : :
1397 : 3 : ut_reservation_init();
1398 : :
1399 : 3 : req = ut_reservation_build_req(16);
1400 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1401 : 3 : rsp = &req->rsp->nvme_cpl;
1402 : :
1403 : 3 : ut_reservation_build_registrants();
1404 : :
1405 : : /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1406 : : * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1407 : : */
1408 : 3 : rsp->status.sc = 0xff;
1409 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1410 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1411 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1412 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1413 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1414 : :
1415 : : /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1416 : : * Reservation release notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1417 : : */
1418 : 3 : rsp->status.sc = 0xff;
1419 : 3 : g_ctrlr1_A.num_avail_log_pages = 0;
1420 : 3 : g_ctrlr2_A.num_avail_log_pages = 0;
1421 : 3 : g_ctrlr_B.num_avail_log_pages = 5;
1422 : 3 : g_ctrlr_C.num_avail_log_pages = 0;
1423 : 3 : ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1424 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1);
1425 : 3 : nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1426 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1427 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1428 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1429 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1430 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1431 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1432 : :
1433 : 3 : ut_reservation_free_req(req);
1434 : 3 : ut_reservation_deinit();
1435 : 3 : }
1436 : :
1437 : : static void
1438 : 3 : test_reservation_release_notification_write_exclusive(void)
1439 : : {
1440 : : struct spdk_nvmf_request *req;
1441 : : struct spdk_nvme_cpl *rsp;
1442 : :
1443 : 3 : ut_reservation_init();
1444 : :
1445 : 3 : req = ut_reservation_build_req(16);
1446 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1447 : 3 : rsp = &req->rsp->nvme_cpl;
1448 : :
1449 : 3 : ut_reservation_build_registrants();
1450 : :
1451 : : /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1452 : : * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE
1453 : : */
1454 : 3 : rsp->status.sc = 0xff;
1455 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1456 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1, 0x0);
1457 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1458 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1459 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1460 : :
1461 : : /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B release the reservation.
1462 : : * Because the reservation type is SPDK_NVME_RESERVE_WRITE_EXCLUSIVE,
1463 : : * no reservation notification occurs.
1464 : : */
1465 : 3 : rsp->status.sc = 0xff;
1466 : 3 : g_ctrlr1_A.num_avail_log_pages = 5;
1467 : 3 : g_ctrlr2_A.num_avail_log_pages = 5;
1468 : 3 : g_ctrlr_B.num_avail_log_pages = 5;
1469 : 3 : g_ctrlr_C.num_avail_log_pages = 5;
1470 : 3 : ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_RELEASE, 0,
1471 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE, 0xb1);
1472 : 3 : nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1473 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1474 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1475 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(5 == g_ctrlr1_A.num_avail_log_pages);
1476 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(5 == g_ctrlr2_A.num_avail_log_pages);
1477 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1478 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1479 : :
1480 : 3 : ut_reservation_free_req(req);
1481 : 3 : ut_reservation_deinit();
1482 : 3 : }
1483 : :
1484 : : static void
1485 : 3 : test_reservation_clear_notification(void)
1486 : : {
1487 : : struct spdk_nvmf_request *req;
1488 : : struct spdk_nvme_cpl *rsp;
1489 : :
1490 : 3 : ut_reservation_init();
1491 : :
1492 : 3 : req = ut_reservation_build_req(16);
1493 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1494 : 3 : rsp = &req->rsp->nvme_cpl;
1495 : :
1496 : 3 : ut_reservation_build_registrants();
1497 : :
1498 : : /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1499 : : * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1500 : : */
1501 : 3 : rsp->status.sc = 0xff;
1502 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1503 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1504 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1505 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1506 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1507 : :
1508 : : /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_B clear the reservation.
1509 : : * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A/g_ctrlr_C.
1510 : : */
1511 : 3 : rsp->status.sc = 0xff;
1512 : 3 : g_ctrlr1_A.num_avail_log_pages = 0;
1513 : 3 : g_ctrlr2_A.num_avail_log_pages = 0;
1514 : 3 : g_ctrlr_B.num_avail_log_pages = 5;
1515 : 3 : g_ctrlr_C.num_avail_log_pages = 0;
1516 : 3 : ut_reservation_build_release_request(req, SPDK_NVME_RESERVE_CLEAR, 0,
1517 : : 0, 0xb1);
1518 : 3 : nvmf_ns_reservation_release(&g_ns, &g_ctrlr_B, req);
1519 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1520 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == 0);
1521 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1522 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1523 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_B.num_avail_log_pages);
1524 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_C.num_avail_log_pages);
1525 : :
1526 : 3 : ut_reservation_free_req(req);
1527 : 3 : ut_reservation_deinit();
1528 : 3 : }
1529 : :
1530 : : static void
1531 : 3 : test_reservation_preempt_notification(void)
1532 : : {
1533 : : struct spdk_nvmf_request *req;
1534 : : struct spdk_nvme_cpl *rsp;
1535 : :
1536 : 3 : ut_reservation_init();
1537 : :
1538 : 3 : req = ut_reservation_build_req(16);
1539 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
1540 : 3 : rsp = &req->rsp->nvme_cpl;
1541 : :
1542 : 3 : ut_reservation_build_registrants();
1543 : :
1544 : : /* ACQUIRE: Host B with g_ctrlr_B get reservation with
1545 : : * type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY
1546 : : */
1547 : 3 : rsp->status.sc = 0xff;
1548 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
1549 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xb1, 0x0);
1550 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_B, req);
1551 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1552 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
1553 : :
1554 : : /* Test Case : g_ctrlr_B holds the reservation, g_ctrlr_C preempt g_ctrlr_B,
1555 : : * g_ctrlr_B registrant is unregistered, and reservation is preempted.
1556 : : * Registration Preempted notification sends to g_ctrlr_B.
1557 : : * Reservation Preempted notification sends to g_ctrlr1_A/g_ctrlr2_A.
1558 : : */
1559 : 3 : rsp->status.sc = 0xff;
1560 : 3 : g_ctrlr1_A.num_avail_log_pages = 0;
1561 : 3 : g_ctrlr2_A.num_avail_log_pages = 0;
1562 : 3 : g_ctrlr_B.num_avail_log_pages = 0;
1563 : 3 : g_ctrlr_C.num_avail_log_pages = 5;
1564 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_PREEMPT, 0,
1565 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS, 0xc1, 0xb1);
1566 : 3 : nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr_C, req);
1567 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
1568 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
1569 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr1_A.num_avail_log_pages);
1570 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr2_A.num_avail_log_pages);
1571 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(1 == g_ctrlr_B.num_avail_log_pages);
1572 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(5 == g_ctrlr_C.num_avail_log_pages);
1573 : :
1574 : 3 : ut_reservation_free_req(req);
1575 : 3 : ut_reservation_deinit();
1576 : 3 : }
1577 : :
1578 : : static int
1579 : 0 : nvmf_tgt_create_poll_group(void *io_device, void *ctx_buf)
1580 : : {
1581 : 0 : return 0;
1582 : : }
1583 : :
1584 : : static void
1585 : 0 : nvmf_tgt_destroy_poll_group(void *io_device, void *ctx_buf)
1586 : : {
1587 : 0 : }
1588 : :
1589 : : static void
1590 : 3 : test_spdk_nvmf_ns_event(void)
1591 : : {
1592 : 3 : struct spdk_nvmf_tgt tgt = {};
1593 : 3 : struct spdk_nvmf_subsystem subsystem = {
1594 : : .max_nsid = 1024,
1595 : : .ns = NULL,
1596 : : .tgt = &tgt,
1597 : 1 : .state_changes = TAILQ_HEAD_INITIALIZER(subsystem.state_changes),
1598 : : };
1599 : 3 : struct spdk_nvmf_ctrlr ctrlr = {
1600 : : .subsys = &subsystem
1601 : : };
1602 : 2 : struct spdk_nvmf_ns_opts ns_opts;
1603 : : uint32_t nsid;
1604 : : struct spdk_bdev *bdev;
1605 : : struct spdk_thread *thread;
1606 : :
1607 : 3 : ctrlr.visible_ns = spdk_bit_array_create(1);
1608 : 3 : spdk_bit_array_set(ctrlr.visible_ns, 0);
1609 : :
1610 : 3 : thread = spdk_get_thread();
1611 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(thread != NULL);
1612 : :
1613 : 3 : subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
1614 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
1615 : 3 : subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
1616 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
1617 : :
1618 : 3 : tgt.max_subsystems = 1024;
1619 : 3 : tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
1620 : 3 : RB_INIT(&tgt.subsystems);
1621 : :
1622 : 3 : spdk_io_device_register(&tgt,
1623 : : nvmf_tgt_create_poll_group,
1624 : : nvmf_tgt_destroy_poll_group,
1625 : : sizeof(struct spdk_nvmf_poll_group),
1626 : : NULL);
1627 : :
1628 : : /* Add one namespace */
1629 : 3 : spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1630 : 3 : nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, "bdev1", &ns_opts, sizeof(ns_opts), NULL);
1631 : 3 : CU_ASSERT(nsid == 1);
1632 : 3 : CU_ASSERT(NULL != subsystem.ns[0]);
1633 : 3 : CU_ASSERT(subsystem.ns[nsid - 1]->bdev == &g_bdevs[nsid - 1]);
1634 : :
1635 : 3 : bdev = subsystem.ns[nsid - 1]->bdev;
1636 : :
1637 : : /* Add one controller */
1638 : 3 : TAILQ_INIT(&subsystem.ctrlrs);
1639 : 3 : TAILQ_INSERT_TAIL(&subsystem.ctrlrs, &ctrlr, link);
1640 : :
1641 : : /* Namespace resize event */
1642 : 3 : subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1643 : 3 : g_ns_changed_nsid = 0xFFFFFFFF;
1644 : 3 : g_ns_changed_ctrlr = NULL;
1645 : 3 : nvmf_ns_event(SPDK_BDEV_EVENT_RESIZE, bdev, subsystem.ns[0]);
1646 : 3 : CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1647 : :
1648 : 3 : poll_threads();
1649 : 3 : CU_ASSERT(1 == g_ns_changed_nsid);
1650 : 3 : CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1651 : 3 : CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1652 : :
1653 : : /* Namespace remove event */
1654 : 3 : subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
1655 : 3 : g_ns_changed_nsid = 0xFFFFFFFF;
1656 : 3 : g_ns_changed_ctrlr = NULL;
1657 : 3 : nvmf_ns_event(SPDK_BDEV_EVENT_REMOVE, bdev, subsystem.ns[0]);
1658 : 3 : CU_ASSERT(SPDK_NVMF_SUBSYSTEM_PAUSING == subsystem.state);
1659 : 3 : CU_ASSERT(0xFFFFFFFF == g_ns_changed_nsid);
1660 : 3 : CU_ASSERT(NULL == g_ns_changed_ctrlr);
1661 : :
1662 : 3 : poll_threads();
1663 : 3 : CU_ASSERT(1 == g_ns_changed_nsid);
1664 : 3 : CU_ASSERT(&ctrlr == g_ns_changed_ctrlr);
1665 : 3 : CU_ASSERT(NULL == subsystem.ns[0]);
1666 : 3 : CU_ASSERT(SPDK_NVMF_SUBSYSTEM_ACTIVE == subsystem.state);
1667 : :
1668 : 3 : spdk_io_device_unregister(&tgt, NULL);
1669 : :
1670 : 3 : poll_threads();
1671 : :
1672 : 3 : free(subsystem.ns);
1673 : 3 : free(subsystem.ana_group);
1674 : 3 : spdk_bit_array_free(&ctrlr.visible_ns);
1675 : 3 : spdk_bit_array_free(&tgt.subsystem_ids);
1676 : 3 : }
1677 : :
1678 : : static void
1679 : 3 : test_nvmf_ns_reservation_add_remove_registrant(void)
1680 : : {
1681 : 3 : struct spdk_nvmf_ns ns = {};
1682 : 3 : struct spdk_nvmf_ctrlr ctrlr = {};
1683 : 3 : struct spdk_nvmf_registrant *reg = NULL;
1684 : : int rc;
1685 : :
1686 : 3 : TAILQ_INIT(&ns.registrants);
1687 : 3 : spdk_uuid_generate(&ctrlr.hostid);
1688 : :
1689 : 3 : rc = nvmf_ns_reservation_add_registrant(&ns, &ctrlr, 0xa11);
1690 : 3 : CU_ASSERT(rc == 0);
1691 : 3 : reg = TAILQ_FIRST(&ns.registrants);
1692 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg != NULL);
1693 : 3 : CU_ASSERT(ns.gen == 1);
1694 : 3 : CU_ASSERT(reg->rkey == 0xa11);
1695 [ - + ]: 3 : CU_ASSERT(!strncmp((uint8_t *)®->hostid, (uint8_t *)&ctrlr.hostid, sizeof(ctrlr.hostid)));
1696 : :
1697 : 3 : nvmf_ns_reservation_remove_registrant(&ns, reg);
1698 : 3 : CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
1699 : 3 : CU_ASSERT(ns.gen == 2);
1700 : 3 : }
1701 : :
1702 : : static void
1703 : 0 : test_nvmf_subsystem_destroy_cb(void *cb_arg)
1704 : : {
1705 : 0 : }
1706 : :
1707 : : static void
1708 : 3 : test_nvmf_subsystem_add_ctrlr(void)
1709 : : {
1710 : : int rc;
1711 : 3 : struct spdk_nvmf_ctrlr ctrlr = {};
1712 : 3 : struct spdk_nvmf_tgt tgt = {};
1713 : 3 : char nqn[256] = "nqn.2016-06.io.spdk:subsystem1";
1714 : 3 : struct spdk_nvmf_subsystem *subsystem = NULL;
1715 : :
1716 : 3 : tgt.max_subsystems = 1024;
1717 : 3 : tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
1718 : 3 : RB_INIT(&tgt.subsystems);
1719 : :
1720 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, nqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1721 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1722 : 3 : ctrlr.subsys = subsystem;
1723 : :
1724 : 3 : ctrlr.dynamic_ctrlr = true;
1725 : 3 : rc = nvmf_subsystem_add_ctrlr(subsystem, &ctrlr);
1726 : 3 : CU_ASSERT(rc == 0);
1727 : 3 : CU_ASSERT(!TAILQ_EMPTY(&subsystem->ctrlrs));
1728 : 3 : CU_ASSERT(ctrlr.cntlid == 1);
1729 : 3 : CU_ASSERT(nvmf_subsystem_get_ctrlr(subsystem, 1) == &ctrlr);
1730 : :
1731 : 3 : nvmf_subsystem_remove_ctrlr(subsystem, &ctrlr);
1732 : 3 : CU_ASSERT(TAILQ_EMPTY(&subsystem->ctrlrs));
1733 : 3 : rc = spdk_nvmf_subsystem_destroy(subsystem, test_nvmf_subsystem_destroy_cb, NULL);
1734 : 3 : CU_ASSERT(rc == 0);
1735 : 3 : spdk_bit_array_free(&tgt.subsystem_ids);
1736 : 3 : }
1737 : :
1738 : : static void
1739 : 0 : _add_transport_cb(void *arg, int status)
1740 : : {
1741 : 0 : CU_ASSERT(status == 0);
1742 : 0 : }
1743 : :
1744 : : static int
1745 : 3 : transport_subsystem_add_host_err(struct spdk_nvmf_transport *transport,
1746 : : const struct spdk_nvmf_subsystem *subsystem,
1747 : : const char *hostnqn,
1748 : : const struct spdk_json_val *transport_specific)
1749 : : {
1750 : 3 : return -1;
1751 : : }
1752 : :
1753 : : void
1754 : 3 : spdk_nvmf_tgt_add_transport(struct spdk_nvmf_tgt *tgt,
1755 : : struct spdk_nvmf_transport *transport,
1756 : : spdk_nvmf_tgt_add_transport_done_fn cb_fn,
1757 : : void *cb_arg)
1758 : : {
1759 : 3 : TAILQ_INSERT_TAIL(&tgt->transports, transport, link);
1760 : 3 : }
1761 : :
1762 : : static struct spdk_nvmf_transport *
1763 : 3 : transport_create(struct spdk_nvmf_transport_opts *opts)
1764 : : {
1765 : 3 : return &g_transport;
1766 : : }
1767 : :
1768 : : static void
1769 : 3 : test_spdk_nvmf_subsystem_add_host(void)
1770 : : {
1771 : 3 : struct spdk_nvmf_tgt tgt = {};
1772 : 3 : struct spdk_nvmf_subsystem *subsystem = NULL;
1773 : : int rc;
1774 : 3 : const char hostnqn[] = "nqn.2016-06.io.spdk:host1";
1775 : 3 : const char subsystemnqn[] = "nqn.2016-06.io.spdk:subsystem1";
1776 : 3 : struct spdk_nvmf_transport_opts opts = {
1777 : : .opts_size = sizeof(struct spdk_nvmf_transport_opts),
1778 : : .io_unit_size = 8192
1779 : : };
1780 : 3 : const struct spdk_nvmf_transport_ops test_ops = {
1781 : : .name = "transport_ut",
1782 : : .create = transport_create,
1783 : : .subsystem_add_host = transport_subsystem_add_host_err,
1784 : : };
1785 : : struct spdk_nvmf_transport *transport;
1786 : :
1787 : 3 : tgt.max_subsystems = 1024;
1788 : 3 : tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
1789 : 3 : RB_INIT(&tgt.subsystems);
1790 : :
1791 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, subsystemnqn, SPDK_NVMF_SUBTYPE_NVME, 0);
1792 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
1793 [ - + ]: 3 : CU_ASSERT_STRING_EQUAL(subsystem->subnqn, subsystemnqn);
1794 : :
1795 : 3 : rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn, NULL);
1796 : 3 : CU_ASSERT(rc == 0);
1797 : 3 : CU_ASSERT(!TAILQ_EMPTY(&subsystem->hosts));
1798 : :
1799 : : /* Add existing nqn, this function isn't allowed to be called if the nqn was previously added. */
1800 : 3 : rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn, NULL);
1801 : 3 : CU_ASSERT(rc == -EINVAL);
1802 : :
1803 : 3 : rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1804 : 3 : CU_ASSERT(rc == 0);
1805 : 3 : CU_ASSERT(TAILQ_EMPTY(&subsystem->hosts));
1806 : :
1807 : : /* No available nqn */
1808 : 3 : rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
1809 : 3 : CU_ASSERT(rc == -ENOENT);
1810 : :
1811 : : /* Ensure hostnqn list remains empty after transport callback fails */
1812 : 3 : spdk_nvmf_transport_register(&test_ops);
1813 : 3 : transport = spdk_nvmf_transport_create("transport_ut", &opts);
1814 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(transport != NULL);
1815 : :
1816 : 3 : TAILQ_INIT(&tgt.transports);
1817 : 3 : spdk_nvmf_tgt_add_transport(&tgt, transport, _add_transport_cb, 0);
1818 : :
1819 : 3 : rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn, NULL);
1820 : 3 : CU_ASSERT(rc != 0);
1821 : 3 : CU_ASSERT(TAILQ_EMPTY(&subsystem->hosts));
1822 : :
1823 : 3 : spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
1824 : 3 : spdk_bit_array_free(&tgt.subsystem_ids);
1825 : 3 : }
1826 : :
1827 : : static void
1828 : 3 : test_nvmf_ns_reservation_report(void)
1829 : : {
1830 : 3 : struct spdk_nvmf_ns ns = {};
1831 : 3 : struct spdk_nvmf_ctrlr ctrlr = {};
1832 : 3 : struct spdk_nvmf_request req = {};
1833 : 3 : union nvmf_h2c_msg cmd = {};
1834 : 3 : union nvmf_c2h_msg rsp = {};
1835 : : struct spdk_nvme_registered_ctrlr_extended_data *ctrlr_data;
1836 : : struct spdk_nvme_reservation_status_extended_data *status_data;
1837 : : struct spdk_nvmf_registrant *reg;
1838 : : void *data;
1839 : :
1840 : 3 : data = calloc(1, sizeof(*status_data) + sizeof(*ctrlr_data) * 2);
1841 : 3 : reg = calloc(2, sizeof(struct spdk_nvmf_registrant));
1842 [ + + + - : 3 : SPDK_CU_ASSERT_FATAL(data != NULL && reg != NULL);
- + ]
1843 : :
1844 : 3 : req.length = sizeof(*status_data) + sizeof(*ctrlr_data) * 2;
1845 : 3 : SPDK_IOV_ONE(req.iov, &req.iovcnt, data, req.length);
1846 : :
1847 : 3 : req.cmd = &cmd;
1848 : 3 : req.rsp = &rsp;
1849 : 3 : ns.gen = 1;
1850 : 3 : ns.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE;
1851 : 3 : ns.ptpl_activated = true;
1852 : 3 : cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1853 : 3 : cmd.nvme_cmd.cdw10 = 100;
1854 : 3 : reg[0].rkey = 0xa;
1855 : 3 : reg[1].rkey = 0xb;
1856 : 3 : spdk_uuid_generate(®[0].hostid);
1857 : 3 : spdk_uuid_generate(®[1].hostid);
1858 : 3 : TAILQ_INIT(&ns.registrants);
1859 : 3 : TAILQ_INSERT_TAIL(&ns.registrants, ®[0], link);
1860 : 3 : TAILQ_INSERT_TAIL(&ns.registrants, ®[1], link);
1861 : :
1862 : 3 : nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1863 : 3 : CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1864 : 3 : CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS);
1865 : : /* Get ctrlr data and status data pointers */
1866 : 3 : ctrlr_data = (void *)((char *)req.iov[0].iov_base + sizeof(*status_data));
1867 : 3 : status_data = (void *)req.iov[0].iov_base;
1868 [ + + + + : 3 : SPDK_CU_ASSERT_FATAL(status_data != NULL && ctrlr_data != NULL);
- + ]
1869 : 3 : CU_ASSERT(status_data->data.gen == 1);
1870 : 3 : CU_ASSERT(status_data->data.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE);
1871 : 3 : CU_ASSERT(status_data->data.ptpls == true);
1872 : 3 : CU_ASSERT(status_data->data.regctl == 2);
1873 : 3 : CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1874 : 3 : CU_ASSERT(ctrlr_data->rcsts.status == false);
1875 : 3 : CU_ASSERT(ctrlr_data->rkey == 0xa);
1876 : 3 : CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, ®[0].hostid));
1877 : : /* Check second ctrlr data */
1878 : 3 : ctrlr_data++;
1879 : 3 : CU_ASSERT(ctrlr_data->cntlid == 0xffff);
1880 : 3 : CU_ASSERT(ctrlr_data->rcsts.status == false);
1881 : 3 : CU_ASSERT(ctrlr_data->rkey == 0xb);
1882 : 3 : CU_ASSERT(!spdk_uuid_compare((struct spdk_uuid *)ctrlr_data->hostid, ®[1].hostid));
1883 : :
1884 : : /* extended controller data structure */
1885 : 3 : spdk_iov_memset(req.iov, req.iovcnt, 0);
1886 [ - + ]: 3 : memset(req.rsp, 0, sizeof(*req.rsp));
1887 : 3 : cmd.nvme_cmd.cdw11_bits.resv_report.eds = false;
1888 : :
1889 : 3 : nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1890 : 3 : CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT);
1891 : 3 : CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1892 : :
1893 : : /* Transfer length invalid */
1894 : 3 : spdk_iov_memset(req.iov, req.iovcnt, 0);
1895 [ - + ]: 3 : memset(req.rsp, 0, sizeof(*req.rsp));
1896 : 3 : cmd.nvme_cmd.cdw11_bits.resv_report.eds = true;
1897 : 3 : cmd.nvme_cmd.cdw10 = 0;
1898 : :
1899 : 3 : nvmf_ns_reservation_report(&ns, &ctrlr, &req);
1900 : 3 : CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INTERNAL_DEVICE_ERROR);
1901 : 3 : CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
1902 : :
1903 : 3 : free(req.iov[0].iov_base);
1904 : 3 : free(reg);
1905 : 3 : }
1906 : :
1907 : : static void
1908 : 3 : test_nvmf_nqn_is_valid(void)
1909 : : {
1910 : : bool rc;
1911 : 3 : char uuid[SPDK_NVMF_UUID_STRING_LEN + 1] = {};
1912 : 3 : char nqn[SPDK_NVMF_NQN_MAX_LEN + 1] = {};
1913 : 3 : struct spdk_uuid s_uuid = {};
1914 : :
1915 : 3 : spdk_uuid_generate(&s_uuid);
1916 : 3 : spdk_uuid_fmt_lower(uuid, sizeof(uuid), &s_uuid);
1917 : :
1918 : : /* discovery nqn */
1919 [ - + ]: 3 : snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
1920 : :
1921 : 3 : rc = nvmf_nqn_is_valid(nqn);
1922 : 3 : CU_ASSERT(rc == true);
1923 : :
1924 : : /* nqn with uuid */
1925 [ - + ]: 3 : memset(nqn, 0xff, sizeof(nqn));
1926 [ - + ]: 3 : snprintf(nqn, sizeof(nqn), "%s%s", SPDK_NVMF_NQN_UUID_PRE, uuid);
1927 : :
1928 : 3 : rc = nvmf_nqn_is_valid(nqn);
1929 : 3 : CU_ASSERT(rc == true);
1930 : :
1931 : : /* Check nqn valid reverse domain */
1932 [ - + ]: 3 : memset(nqn, 0xff, sizeof(nqn));
1933 [ - + ]: 3 : snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io.spdk:cnode1");
1934 : :
1935 : 3 : rc = nvmf_nqn_is_valid(nqn);
1936 : 3 : CU_ASSERT(rc == true);
1937 : :
1938 : : /* Invalid nqn length */
1939 [ - + ]: 3 : memset(nqn, 0xff, sizeof(nqn));
1940 [ - + ]: 3 : snprintf(nqn, sizeof(nqn), "%s", "nqn.");
1941 : :
1942 : 3 : rc = nvmf_nqn_is_valid(nqn);
1943 : 3 : CU_ASSERT(rc == false);
1944 : :
1945 : : /* Copy uuid to the nqn string, but omit the last character to make it invalid */
1946 [ - + ]: 3 : memset(nqn, 0, SPDK_NVMF_NQN_MAX_LEN + 1);
1947 [ - + ]: 3 : snprintf(nqn, sizeof(nqn), "%s", SPDK_NVMF_NQN_UUID_PRE);
1948 [ - + - + ]: 3 : memcpy(&nqn[SPDK_NVMF_NQN_UUID_PRE_LEN], uuid, SPDK_NVMF_UUID_STRING_LEN - 1);
1949 : :
1950 : 3 : rc = nvmf_nqn_is_valid(nqn);
1951 : 3 : CU_ASSERT(rc == false);
1952 : :
1953 : : /* Invalid domain */
1954 [ - + ]: 3 : memset(nqn, 0xff, SPDK_NVMF_NQN_MAX_LEN + 1);
1955 [ - + ]: 3 : snprintf(nqn, sizeof(nqn), "%s", "nqn.2016-06.io...spdk:cnode1");
1956 : :
1957 : 3 : rc = nvmf_nqn_is_valid(nqn);
1958 : 3 : CU_ASSERT(rc == false);
1959 : 3 : }
1960 : :
1961 : : static void
1962 : 3 : test_nvmf_ns_reservation_restore(void)
1963 : : {
1964 : 3 : struct spdk_nvmf_ns ns = {};
1965 : 3 : struct spdk_nvmf_reservation_info info = {};
1966 : 3 : struct spdk_bdev bdev = {};
1967 : 3 : struct spdk_uuid s_uuid = {};
1968 : : struct spdk_nvmf_registrant *reg0, *reg1;
1969 : 3 : char uuid[SPDK_UUID_STRING_LEN] = {};
1970 : : int rc;
1971 : :
1972 : 3 : ns.bdev = &bdev;
1973 : 3 : TAILQ_INIT(&ns.registrants);
1974 : 3 : info.ptpl_activated = true;
1975 : 3 : info.num_regs = 2;
1976 : 3 : info.rtype = SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS;
1977 : 3 : info.registrants[0].rkey = 0xb;
1978 : 3 : info.registrants[1].rkey = 0xc;
1979 : :
1980 : : /* Generate and prepare uuids, make sure bdev and info uuid are the same */
1981 : 3 : spdk_uuid_generate(&s_uuid);
1982 : 3 : spdk_uuid_fmt_lower(uuid, sizeof(uuid), &s_uuid);
1983 [ - + ]: 3 : snprintf(info.holder_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1984 [ - + ]: 3 : snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1985 [ - + ]: 3 : snprintf(info.registrants[0].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1986 : 3 : spdk_uuid_copy(&bdev.uuid, &s_uuid);
1987 : 3 : spdk_uuid_generate(&s_uuid);
1988 : 3 : spdk_uuid_fmt_lower(uuid, sizeof(uuid), &s_uuid);
1989 [ - + ]: 3 : snprintf(info.registrants[1].host_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
1990 : :
1991 : : /* info->rkey not exist in registrants */
1992 : 3 : info.crkey = 0xa;
1993 : :
1994 : 3 : rc = nvmf_ns_reservation_restore(&ns, &info);
1995 : 3 : CU_ASSERT(rc == -EINVAL);
1996 : :
1997 : : /* info->rkey exists in registrants */
1998 : 3 : info.crkey = 0xb;
1999 : :
2000 : 3 : rc = nvmf_ns_reservation_restore(&ns, &info);
2001 : 3 : CU_ASSERT(rc == 0);
2002 : 3 : CU_ASSERT(ns.crkey == 0xb);
2003 : 3 : CU_ASSERT(ns.rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS);
2004 [ - + ]: 3 : CU_ASSERT(ns.ptpl_activated == true);
2005 : : /* Check two registrant`s rkey */
2006 : 3 : reg0 = TAILQ_FIRST(&ns.registrants);
2007 : 3 : reg1 = TAILQ_NEXT(reg0, link);
2008 : 3 : CU_ASSERT(ns.holder == reg0);
2009 : 3 : CU_ASSERT(reg0->rkey == 0xb);
2010 : 3 : CU_ASSERT(reg1->rkey == 0xc);
2011 : :
2012 : 3 : rc = nvmf_ns_reservation_clear_all_registrants(&ns);
2013 : 3 : CU_ASSERT(rc == 2);
2014 : 3 : CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
2015 : :
2016 : : /* Existing bdev UUID is different with configuration */
2017 : 3 : spdk_uuid_generate(&s_uuid);
2018 : 3 : spdk_uuid_fmt_lower(uuid, sizeof(uuid), &s_uuid);
2019 [ - + ]: 3 : snprintf(info.bdev_uuid, SPDK_UUID_STRING_LEN, "%s", uuid);
2020 : 3 : spdk_uuid_generate(&s_uuid);
2021 : 3 : spdk_uuid_copy(&bdev.uuid, &s_uuid);
2022 : :
2023 : 3 : rc = nvmf_ns_reservation_restore(&ns, &info);
2024 : 3 : CU_ASSERT(rc == -EINVAL);
2025 : :
2026 : : /* Check restore without reservation */
2027 : 3 : spdk_uuid_fmt_lower(info.bdev_uuid, sizeof(info.bdev_uuid), &bdev.uuid);
2028 : 3 : info.rtype = 0;
2029 : 3 : info.crkey = 0;
2030 [ - + ]: 3 : memset(info.holder_uuid, 0, SPDK_UUID_STRING_LEN);
2031 : :
2032 : 3 : rc = nvmf_ns_reservation_restore(&ns, &info);
2033 : 3 : CU_ASSERT(rc == 0);
2034 : 3 : CU_ASSERT(ns.crkey == 0);
2035 : 3 : CU_ASSERT(ns.rtype == 0);
2036 [ - + ]: 3 : CU_ASSERT(ns.ptpl_activated == true);
2037 : 3 : CU_ASSERT(ns.holder == NULL);
2038 : 3 : reg0 = TAILQ_FIRST(&ns.registrants);
2039 : 3 : reg1 = TAILQ_NEXT(reg0, link);
2040 : 3 : CU_ASSERT(reg0->rkey == 0xb);
2041 : 3 : CU_ASSERT(reg1->rkey == 0xc);
2042 : :
2043 : 3 : rc = nvmf_ns_reservation_clear_all_registrants(&ns);
2044 : 3 : CU_ASSERT(rc == 2);
2045 : 3 : CU_ASSERT(TAILQ_EMPTY(&ns.registrants));
2046 : 3 : }
2047 : :
2048 : : static void
2049 : 3 : ut_nvmf_subsystem_paused(struct spdk_nvmf_subsystem *subsystem, void *ctx, int status)
2050 : : {
2051 : 3 : CU_ASSERT_EQUAL(status, 0);
2052 : 3 : CU_ASSERT_EQUAL(subsystem->state, SPDK_NVMF_SUBSYSTEM_PAUSED);
2053 : 3 : }
2054 : :
2055 : : static void
2056 : 3 : test_nvmf_subsystem_state_change(void)
2057 : : {
2058 : 3 : struct spdk_nvmf_tgt tgt = {};
2059 : : struct spdk_nvmf_subsystem *subsystem, *discovery_subsystem;
2060 : : int rc;
2061 : :
2062 : 3 : tgt.max_subsystems = 1024;
2063 : 3 : tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
2064 : 3 : RB_INIT(&tgt.subsystems);
2065 : :
2066 : 3 : discovery_subsystem = spdk_nvmf_subsystem_create(&tgt, SPDK_NVMF_DISCOVERY_NQN,
2067 : : SPDK_NVMF_SUBTYPE_DISCOVERY_CURRENT, 0);
2068 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(discovery_subsystem != NULL);
2069 : 3 : subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
2070 : : SPDK_NVMF_SUBTYPE_NVME, 0);
2071 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem != NULL);
2072 : :
2073 : 3 : spdk_io_device_register(&tgt,
2074 : : nvmf_tgt_create_poll_group,
2075 : : nvmf_tgt_destroy_poll_group,
2076 : : sizeof(struct spdk_nvmf_poll_group),
2077 : : NULL);
2078 : :
2079 : 3 : rc = spdk_nvmf_subsystem_start(discovery_subsystem, NULL, NULL);
2080 : 3 : CU_ASSERT(rc == 0);
2081 : 3 : poll_threads();
2082 : 3 : CU_ASSERT(discovery_subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVE);
2083 : 3 : rc = spdk_nvmf_subsystem_start(subsystem, NULL, NULL);
2084 : 3 : CU_ASSERT(rc == 0);
2085 : 3 : poll_threads();
2086 : 3 : CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_ACTIVE);
2087 : :
2088 : 3 : rc = spdk_nvmf_subsystem_pause(subsystem, SPDK_NVME_GLOBAL_NS_TAG,
2089 : : ut_nvmf_subsystem_paused, NULL);
2090 : 3 : CU_ASSERT(rc == 0);
2091 : 3 : rc = spdk_nvmf_subsystem_stop(subsystem, NULL, NULL);
2092 : 3 : CU_ASSERT(rc == 0);
2093 : 3 : poll_threads();
2094 : 3 : CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
2095 : :
2096 : 3 : rc = spdk_nvmf_subsystem_stop(discovery_subsystem, NULL, NULL);
2097 : 3 : CU_ASSERT(rc == 0);
2098 : 3 : poll_threads();
2099 : 3 : CU_ASSERT(discovery_subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
2100 : 3 : rc = spdk_nvmf_subsystem_stop(subsystem, NULL, NULL);
2101 : 3 : CU_ASSERT(rc == 0);
2102 : 3 : poll_threads();
2103 : 3 : CU_ASSERT(subsystem->state == SPDK_NVMF_SUBSYSTEM_INACTIVE);
2104 : :
2105 : 3 : rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
2106 : 3 : CU_ASSERT(rc == 0);
2107 : 3 : rc = spdk_nvmf_subsystem_destroy(discovery_subsystem, NULL, NULL);
2108 : 3 : CU_ASSERT(rc == 0);
2109 : :
2110 : 3 : spdk_io_device_unregister(&tgt, NULL);
2111 : 3 : poll_threads();
2112 : :
2113 : 3 : spdk_bit_array_free(&tgt.subsystem_ids);
2114 : 3 : }
2115 : :
2116 : : static bool
2117 : 12 : ut_is_ptpl_capable(const struct spdk_nvmf_ns *ns)
2118 : : {
2119 : 12 : return true;
2120 : : }
2121 : :
2122 : : static struct spdk_nvmf_reservation_info g_resv_info;
2123 : :
2124 : : static int
2125 : 6 : ut_update_reservation(const struct spdk_nvmf_ns *ns, const struct spdk_nvmf_reservation_info *info)
2126 : : {
2127 : 6 : g_resv_info = *info;
2128 : :
2129 : 6 : return 0;
2130 : : }
2131 : :
2132 : : static int
2133 : 3 : ut_load_reservation(const struct spdk_nvmf_ns *ns, struct spdk_nvmf_reservation_info *info)
2134 : : {
2135 : 3 : *info = g_resv_info;
2136 : :
2137 : 3 : return 0;
2138 : : }
2139 : :
2140 : : static void
2141 : 3 : test_nvmf_reservation_custom_ops(void)
2142 : : {
2143 : 3 : struct spdk_nvmf_ns_reservation_ops ops = {
2144 : : .is_ptpl_capable = ut_is_ptpl_capable,
2145 : : .update = ut_update_reservation,
2146 : : .load = ut_load_reservation,
2147 : : };
2148 : : struct spdk_nvmf_request *req;
2149 : : struct spdk_nvme_cpl *rsp;
2150 : : struct spdk_nvmf_registrant *reg;
2151 : 3 : bool update_sgroup = false;
2152 : 3 : struct spdk_nvmf_tgt tgt = {};
2153 : 3 : struct spdk_nvmf_subsystem subsystem = {
2154 : : .max_nsid = 4,
2155 : : .tgt = &tgt,
2156 : : };
2157 : : uint32_t nsid;
2158 : : struct spdk_nvmf_ns *ns;
2159 : : int rc;
2160 : :
2161 : 3 : subsystem.ns = calloc(subsystem.max_nsid, sizeof(struct spdk_nvmf_subsystem_ns *));
2162 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ns != NULL);
2163 : 3 : subsystem.ana_group = calloc(subsystem.max_nsid, sizeof(uint32_t));
2164 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(subsystem.ana_group != NULL);
2165 : :
2166 : 3 : spdk_nvmf_set_custom_ns_reservation_ops(&ops);
2167 : :
2168 : 3 : ut_reservation_init();
2169 : :
2170 : 3 : req = ut_reservation_build_req(16);
2171 : 3 : rsp = &req->rsp->nvme_cpl;
2172 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(req != NULL);
2173 : :
2174 : : /* Add a registrant and activate ptpl */
2175 : 3 : ut_reservation_build_register_request(req, SPDK_NVME_RESERVE_REGISTER_KEY, 0,
2176 : : SPDK_NVME_RESERVE_PTPL_PERSIST_POWER_LOSS, 0, 0xa1);
2177 : 3 : update_sgroup = nvmf_ns_reservation_register(&g_ns, &g_ctrlr1_A, req);
2178 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(update_sgroup == true);
2179 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
2180 [ + + - + ]: 3 : SPDK_CU_ASSERT_FATAL(g_ns.ptpl_activated == true);
2181 : 3 : rc = nvmf_ns_update_reservation_info(&g_ns);
2182 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
2183 : :
2184 : : /* Acquire a reservation */
2185 : 3 : rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
2186 : 3 : ut_reservation_build_acquire_request(req, SPDK_NVME_RESERVE_ACQUIRE, 0,
2187 : : SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY, 0xa1, 0x0);
2188 : 3 : update_sgroup = nvmf_ns_reservation_acquire(&g_ns, &g_ctrlr1_A, req);
2189 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(update_sgroup == true);
2190 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rsp->status.sc == SPDK_NVME_SC_SUCCESS);
2191 : 3 : rc = nvmf_ns_update_reservation_info(&g_ns);
2192 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
2193 : :
2194 : : /* Add the namespace using a different subsystem.
2195 : : * Reservation information should be restored. */
2196 : 3 : nsid = spdk_nvmf_subsystem_add_ns_ext(&subsystem, g_ns.bdev->name, NULL, 0, NULL);
2197 : 3 : CU_ASSERT(nsid == 1);
2198 : :
2199 : 3 : ns = _nvmf_subsystem_get_ns(&subsystem, nsid);
2200 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(ns != NULL);
2201 : 3 : CU_ASSERT(ns->crkey == 0xa1);
2202 : 3 : CU_ASSERT(ns->rtype == SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY);
2203 [ - + ]: 3 : CU_ASSERT(ns->ptpl_activated == true);
2204 : :
2205 : 3 : reg = nvmf_ns_reservation_get_registrant(ns, &g_ctrlr1_A.hostid);
2206 [ + + ]: 3 : SPDK_CU_ASSERT_FATAL(reg != NULL);
2207 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(!spdk_uuid_compare(&g_ctrlr1_A.hostid, ®->hostid));
2208 : 3 : CU_ASSERT(reg == ns->holder);
2209 : :
2210 : 3 : rc = spdk_nvmf_subsystem_remove_ns(&subsystem, nsid);
2211 : 3 : CU_ASSERT(rc == 0);
2212 : :
2213 : 3 : free(subsystem.ns);
2214 : 3 : free(subsystem.ana_group);
2215 : 3 : ut_reservation_free_req(req);
2216 : 3 : ut_reservation_deinit();
2217 : 3 : }
2218 : :
2219 : : int
2220 : 3 : main(int argc, char **argv)
2221 : : {
2222 : 3 : CU_pSuite suite = NULL;
2223 : : unsigned int num_failures;
2224 : :
2225 : 3 : CU_initialize_registry();
2226 : :
2227 : 3 : suite = CU_add_suite("nvmf", NULL, NULL);
2228 : :
2229 : 3 : CU_ADD_TEST(suite, nvmf_test_create_subsystem);
2230 : 3 : CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_ns);
2231 : 3 : CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_fdp_ns);
2232 : 3 : CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_set_sn);
2233 : 3 : CU_ADD_TEST(suite, test_spdk_nvmf_ns_visible);
2234 : 3 : CU_ADD_TEST(suite, test_reservation_register);
2235 : 3 : CU_ADD_TEST(suite, test_reservation_register_with_ptpl);
2236 : 3 : CU_ADD_TEST(suite, test_reservation_acquire_preempt_1);
2237 : 3 : CU_ADD_TEST(suite, test_reservation_acquire_release_with_ptpl);
2238 : 3 : CU_ADD_TEST(suite, test_reservation_release);
2239 : 3 : CU_ADD_TEST(suite, test_reservation_unregister_notification);
2240 : 3 : CU_ADD_TEST(suite, test_reservation_release_notification);
2241 : 3 : CU_ADD_TEST(suite, test_reservation_release_notification_write_exclusive);
2242 : 3 : CU_ADD_TEST(suite, test_reservation_clear_notification);
2243 : 3 : CU_ADD_TEST(suite, test_reservation_preempt_notification);
2244 : 3 : CU_ADD_TEST(suite, test_spdk_nvmf_ns_event);
2245 : 3 : CU_ADD_TEST(suite, test_nvmf_ns_reservation_add_remove_registrant);
2246 : 3 : CU_ADD_TEST(suite, test_nvmf_subsystem_add_ctrlr);
2247 : 3 : CU_ADD_TEST(suite, test_spdk_nvmf_subsystem_add_host);
2248 : 3 : CU_ADD_TEST(suite, test_nvmf_ns_reservation_report);
2249 : 3 : CU_ADD_TEST(suite, test_nvmf_nqn_is_valid);
2250 : 3 : CU_ADD_TEST(suite, test_nvmf_ns_reservation_restore);
2251 : 3 : CU_ADD_TEST(suite, test_nvmf_subsystem_state_change);
2252 : 3 : CU_ADD_TEST(suite, test_nvmf_reservation_custom_ops);
2253 : :
2254 : 3 : allocate_threads(1);
2255 : 3 : set_thread(0);
2256 : :
2257 : 3 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
2258 : 3 : CU_cleanup_registry();
2259 : :
2260 : 3 : free_threads();
2261 : :
2262 : 3 : return num_failures;
2263 : : }
|