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