xref: /spdk/test/unit/lib/scsi/dev.c/dev_ut.c (revision 5d62af41a3f5ef1e75b3ecdb2c8dcafe112d9597)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "CUnit/Basic.h"
37 #include "spdk_cunit.h"
38 
39 #include "spdk/util.h"
40 
41 #include "scsi/dev.c"
42 #include "scsi/port.c"
43 
44 #include "spdk_internal/mock.h"
45 
46 DEFINE_STUB(spdk_scsi_lun_is_removing, bool,
47 	    (const struct spdk_scsi_lun *lun), false);
48 
49 static char *g_bdev_names[] = {
50 	"malloc0",
51 	"malloc1",
52 	"malloc2",
53 	"malloc4",
54 };
55 
56 static struct spdk_scsi_port *g_initiator_port_with_pending_tasks = NULL;
57 static struct spdk_scsi_port *g_initiator_port_with_pending_mgmt_tasks = NULL;
58 
59 static struct spdk_scsi_task *
60 spdk_get_task(uint32_t *owner_task_ctr)
61 {
62 	struct spdk_scsi_task *task;
63 
64 	task = calloc(1, sizeof(*task));
65 	if (!task) {
66 		return NULL;
67 	}
68 
69 	return task;
70 }
71 
72 void
73 spdk_scsi_task_put(struct spdk_scsi_task *task)
74 {
75 	free(task);
76 }
77 
78 struct spdk_scsi_lun *scsi_lun_construct(const char *bdev_name,
79 		void (*resize_cb)(const struct spdk_scsi_lun *, void *),
80 		void *resize_ctx,
81 		void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
82 		void *hotremove_ctx)
83 {
84 	struct spdk_scsi_lun *lun;
85 	size_t i;
86 
87 	for (i = 0; i < SPDK_COUNTOF(g_bdev_names); i++) {
88 		if (strcmp(bdev_name, g_bdev_names[i]) == 0) {
89 			lun = calloc(1, sizeof(struct spdk_scsi_lun));
90 			SPDK_CU_ASSERT_FATAL(lun != NULL);
91 
92 			return lun;
93 		}
94 	}
95 
96 	return NULL;
97 }
98 
99 void
100 scsi_lun_destruct(struct spdk_scsi_lun *lun)
101 {
102 	free(lun);
103 }
104 
105 DEFINE_STUB_V(scsi_lun_execute_mgmt_task,
106 	      (struct spdk_scsi_lun *lun, struct spdk_scsi_task *task));
107 
108 DEFINE_STUB_V(scsi_lun_execute_task,
109 	      (struct spdk_scsi_lun *lun, struct spdk_scsi_task *task));
110 
111 DEFINE_STUB(scsi_lun_allocate_io_channel, int,
112 	    (struct spdk_scsi_lun *lun), 0);
113 
114 DEFINE_STUB_V(scsi_lun_free_io_channel, (struct spdk_scsi_lun *lun));
115 
116 bool
117 scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun,
118 				const struct spdk_scsi_port *initiator_port)
119 {
120 	return (g_initiator_port_with_pending_mgmt_tasks == initiator_port);
121 }
122 
123 bool
124 scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun,
125 			   const struct spdk_scsi_port *initiator_port)
126 {
127 	return (g_initiator_port_with_pending_tasks == initiator_port);
128 }
129 
130 static void
131 dev_destruct_null_dev(void)
132 {
133 	/* pass null for the dev */
134 	spdk_scsi_dev_destruct(NULL, NULL, NULL);
135 }
136 
137 static void
138 dev_destruct_zero_luns(void)
139 {
140 	struct spdk_scsi_dev dev = { .is_allocated = 1 };
141 
142 	/* No luns attached to the dev */
143 
144 	/* free the dev */
145 	spdk_scsi_dev_destruct(&dev, NULL, NULL);
146 }
147 
148 static void
149 dev_destruct_null_lun(void)
150 {
151 	struct spdk_scsi_dev dev = { .is_allocated = 1 };
152 
153 	/* pass null for the lun */
154 	TAILQ_INIT(&dev.luns);
155 
156 	/* free the dev */
157 	spdk_scsi_dev_destruct(&dev, NULL, NULL);
158 }
159 
160 static void
161 dev_destruct_success(void)
162 {
163 	struct spdk_scsi_dev dev = {
164 		.is_allocated = 1,
165 		.luns = TAILQ_HEAD_INITIALIZER(dev.luns),
166 	};
167 	int rc;
168 
169 	/* dev with a single lun */
170 	rc = spdk_scsi_dev_add_lun(&dev, "malloc0", 0, NULL, NULL);
171 
172 	CU_ASSERT(rc == 0);
173 
174 	/* free the dev */
175 	spdk_scsi_dev_destruct(&dev, NULL, NULL);
176 
177 }
178 
179 static void
180 dev_construct_num_luns_zero(void)
181 {
182 	struct spdk_scsi_dev *dev;
183 	const char *bdev_name_list[1] = {};
184 	int lun_id_list[1] = { 0 };
185 
186 	dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 0,
187 				      SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL);
188 
189 	/* dev should be null since we passed num_luns = 0 */
190 	CU_ASSERT_TRUE(dev == NULL);
191 }
192 
193 static void
194 dev_construct_no_lun_zero(void)
195 {
196 	struct spdk_scsi_dev *dev;
197 	const char *bdev_name_list[1] = {};
198 	int lun_id_list[1] = { 0 };
199 
200 	lun_id_list[0] = 1;
201 
202 	dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1,
203 				      SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL);
204 
205 	/* dev should be null since no LUN0 was specified (lun_id_list[0] = 1) */
206 	CU_ASSERT_TRUE(dev == NULL);
207 }
208 
209 static void
210 dev_construct_null_lun(void)
211 {
212 	struct spdk_scsi_dev *dev;
213 	const char *bdev_name_list[1] = {};
214 	int lun_id_list[1] = { 0 };
215 
216 	dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1,
217 				      SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL);
218 
219 	/* dev should be null since no LUN0 was specified (lun_list[0] = NULL) */
220 	CU_ASSERT_TRUE(dev == NULL);
221 }
222 
223 static void
224 dev_construct_name_too_long(void)
225 {
226 	struct spdk_scsi_dev *dev;
227 	const char *bdev_name_list[1] = {"malloc0"};
228 	int lun_id_list[1] = { 0 };
229 	char name[SPDK_SCSI_DEV_MAX_NAME + 1 + 1];
230 
231 	/* Try to construct a dev with a name that is one byte longer than allowed. */
232 	memset(name, 'x', sizeof(name) - 1);
233 	name[sizeof(name) - 1] = '\0';
234 
235 	dev = spdk_scsi_dev_construct(name, bdev_name_list, lun_id_list, 1,
236 				      SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL);
237 
238 	CU_ASSERT(dev == NULL);
239 }
240 
241 static void
242 dev_construct_success(void)
243 {
244 	struct spdk_scsi_dev *dev;
245 	const char *bdev_name_list[1] = {"malloc0"};
246 	int lun_id_list[1] = { 0 };
247 
248 	dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1,
249 				      SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL);
250 
251 	/* Successfully constructs and returns a dev */
252 	CU_ASSERT_TRUE(dev != NULL);
253 
254 	/* free the dev */
255 	spdk_scsi_dev_destruct(dev, NULL, NULL);
256 }
257 
258 static void
259 dev_construct_success_lun_zero_not_first(void)
260 {
261 	struct spdk_scsi_dev *dev;
262 	const char *bdev_name_list[2] = {"malloc1", "malloc0"};
263 	int lun_id_list[2] = { 1, 0 };
264 
265 	dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 2,
266 				      SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL);
267 
268 	/* Successfully constructs and returns a dev */
269 	CU_ASSERT_TRUE(dev != NULL);
270 
271 	/* free the dev */
272 	spdk_scsi_dev_destruct(dev, NULL, NULL);
273 }
274 
275 static void
276 dev_queue_mgmt_task_success(void)
277 {
278 	struct spdk_scsi_dev *dev;
279 	const char *bdev_name_list[1] = {"malloc0"};
280 	int lun_id_list[1] = { 0 };
281 	struct spdk_scsi_task *task;
282 
283 	dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1,
284 				      SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL);
285 
286 	/* Successfully constructs and returns a dev */
287 	CU_ASSERT_TRUE(dev != NULL);
288 
289 	task = spdk_get_task(NULL);
290 
291 	task->function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
292 	spdk_scsi_dev_queue_mgmt_task(dev, task);
293 
294 	spdk_scsi_task_put(task);
295 
296 	spdk_scsi_dev_destruct(dev, NULL, NULL);
297 }
298 
299 static void
300 dev_queue_task_success(void)
301 {
302 	struct spdk_scsi_dev *dev;
303 	const char *bdev_name_list[1] = {"malloc0"};
304 	int lun_id_list[1] = { 0 };
305 	struct spdk_scsi_task *task;
306 
307 	dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 1,
308 				      SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL);
309 
310 	/* Successfully constructs and returns a dev */
311 	CU_ASSERT_TRUE(dev != NULL);
312 
313 	task = spdk_get_task(NULL);
314 
315 	spdk_scsi_dev_queue_task(dev, task);
316 
317 	spdk_scsi_task_put(task);
318 
319 	spdk_scsi_dev_destruct(dev, NULL, NULL);
320 }
321 
322 static void
323 dev_stop_success(void)
324 {
325 	struct spdk_scsi_dev dev = { 0 };
326 	struct spdk_scsi_task *task;
327 	struct spdk_scsi_task *task_mgmt;
328 
329 	task = spdk_get_task(NULL);
330 
331 	spdk_scsi_dev_queue_task(&dev, task);
332 
333 	task_mgmt = spdk_get_task(NULL);
334 
335 	/* Enqueue the tasks into dev->task_mgmt_submit_queue */
336 	task->function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
337 	spdk_scsi_dev_queue_mgmt_task(&dev, task_mgmt);
338 
339 	spdk_scsi_task_put(task);
340 	spdk_scsi_task_put(task_mgmt);
341 }
342 
343 static void
344 dev_add_port_max_ports(void)
345 {
346 	struct spdk_scsi_dev dev = { 0 };
347 	const char *name;
348 	int id, rc;
349 
350 	/* dev is set to SPDK_SCSI_DEV_MAX_PORTS */
351 	dev.num_ports = SPDK_SCSI_DEV_MAX_PORTS;
352 	name = "Name of Port";
353 	id = 1;
354 
355 	rc = spdk_scsi_dev_add_port(&dev, id, name);
356 
357 	/* returns -1; since the dev already has maximum
358 	 * number of ports (SPDK_SCSI_DEV_MAX_PORTS) */
359 	CU_ASSERT_TRUE(rc < 0);
360 }
361 
362 static void
363 dev_add_port_construct_failure1(void)
364 {
365 	struct spdk_scsi_dev dev = { 0 };
366 	const int port_name_length = SPDK_SCSI_PORT_MAX_NAME_LENGTH + 2;
367 	char name[port_name_length];
368 	uint64_t id;
369 	int rc;
370 
371 	dev.num_ports = 1;
372 	/* Set the name such that the length exceeds SPDK_SCSI_PORT_MAX_NAME_LENGTH
373 	 * SPDK_SCSI_PORT_MAX_NAME_LENGTH = 256 */
374 	memset(name, 'a', port_name_length - 1);
375 	name[port_name_length - 1] = '\0';
376 	id = 1;
377 
378 	rc = spdk_scsi_dev_add_port(&dev, id, name);
379 
380 	/* returns -1; since the length of the name exceeds
381 	 * SPDK_SCSI_PORT_MAX_NAME_LENGTH */
382 	CU_ASSERT_TRUE(rc < 0);
383 }
384 
385 static void
386 dev_add_port_construct_failure2(void)
387 {
388 	struct spdk_scsi_dev dev = { 0 };
389 	const char *name;
390 	uint64_t id;
391 	int rc;
392 
393 	dev.num_ports = 1;
394 	name = "Name of Port";
395 	id = 1;
396 
397 	/* Initialize port[0] to be valid and its index is set to 1 */
398 	dev.port[0].id = id;
399 	dev.port[0].is_used = 1;
400 
401 	rc = spdk_scsi_dev_add_port(&dev, id, name);
402 
403 	/* returns -1; since the dev already has a port whose index to be 1 */
404 	CU_ASSERT_TRUE(rc < 0);
405 }
406 
407 static void
408 dev_add_port_success1(void)
409 {
410 	struct spdk_scsi_dev dev = { 0 };
411 	const char *name;
412 	int id, rc;
413 
414 	dev.num_ports = 1;
415 	name = "Name of Port";
416 	id = 1;
417 
418 	rc = spdk_scsi_dev_add_port(&dev, id, name);
419 
420 	/* successfully adds a port */
421 	CU_ASSERT_EQUAL(rc, 0);
422 	/* Assert num_ports has been incremented to  2 */
423 	CU_ASSERT_EQUAL(dev.num_ports, 2);
424 }
425 
426 static void
427 dev_add_port_success2(void)
428 {
429 	struct spdk_scsi_dev dev = { 0 };
430 	const char *name;
431 	uint64_t id;
432 	int rc;
433 
434 	dev.num_ports = 1;
435 	name = "Name of Port";
436 	id = 1;
437 	/* set id of invalid port[0] to 1. This must be ignored */
438 	dev.port[0].id = id;
439 	dev.port[0].is_used = 0;
440 
441 	rc = spdk_scsi_dev_add_port(&dev, id, name);
442 
443 	/* successfully adds a port */
444 	CU_ASSERT_EQUAL(rc, 0);
445 	/* Assert num_ports has been incremented to 1 */
446 	CU_ASSERT_EQUAL(dev.num_ports, 2);
447 }
448 
449 static void
450 dev_add_port_success3(void)
451 {
452 	struct spdk_scsi_dev dev = { 0 };
453 	const char *name;
454 	uint64_t add_id;
455 	int rc;
456 
457 	dev.num_ports = 1;
458 	name = "Name of Port";
459 	dev.port[0].id = 1;
460 	dev.port[0].is_used = 1;
461 	add_id = 2;
462 
463 	/* Add a port with id = 2 */
464 	rc = spdk_scsi_dev_add_port(&dev, add_id, name);
465 
466 	/* successfully adds a port */
467 	CU_ASSERT_EQUAL(rc, 0);
468 	/* Assert num_ports has been incremented to 2 */
469 	CU_ASSERT_EQUAL(dev.num_ports, 2);
470 }
471 
472 static void
473 dev_find_port_by_id_num_ports_zero(void)
474 {
475 	struct spdk_scsi_dev dev = { 0 };
476 	struct spdk_scsi_port *rp_port;
477 	uint64_t id;
478 
479 	dev.num_ports = 0;
480 	id = 1;
481 
482 	rp_port = spdk_scsi_dev_find_port_by_id(&dev, id);
483 
484 	/* returns null; since dev's num_ports is 0 */
485 	CU_ASSERT_TRUE(rp_port == NULL);
486 }
487 
488 static void
489 dev_find_port_by_id_id_not_found_failure(void)
490 {
491 	struct spdk_scsi_dev dev = { 0 };
492 	struct spdk_scsi_port *rp_port;
493 	const char *name;
494 	int rc;
495 	uint64_t id, find_id;
496 
497 	id = 1;
498 	dev.num_ports = 1;
499 	name = "Name of Port";
500 	find_id = 2;
501 
502 	/* Add a port with id = 1 */
503 	rc = spdk_scsi_dev_add_port(&dev, id, name);
504 
505 	CU_ASSERT_EQUAL(rc, 0);
506 
507 	/* Find port with id = 2 */
508 	rp_port = spdk_scsi_dev_find_port_by_id(&dev, find_id);
509 
510 	/* returns null; failed to find port specified by id = 2 */
511 	CU_ASSERT_TRUE(rp_port == NULL);
512 }
513 
514 static void
515 dev_find_port_by_id_success(void)
516 {
517 	struct spdk_scsi_dev dev = { 0 };
518 	struct spdk_scsi_port *rp_port;
519 	const char *name;
520 	int rc;
521 	uint64_t id;
522 
523 	id = 1;
524 	dev.num_ports = 1;
525 	name = "Name of Port";
526 
527 	/* Add a port */
528 	rc = spdk_scsi_dev_add_port(&dev, id, name);
529 
530 	CU_ASSERT_EQUAL(rc, 0);
531 
532 	/* Find port by the same id as the one added above */
533 	rp_port = spdk_scsi_dev_find_port_by_id(&dev, id);
534 
535 	/* Successfully found port specified by id */
536 	CU_ASSERT_TRUE(rp_port != NULL);
537 	if (rp_port != NULL) {
538 		/* Assert the found port's id and name are same as
539 		 * the port added. */
540 		CU_ASSERT_EQUAL(rp_port->id, 1);
541 		CU_ASSERT_STRING_EQUAL(rp_port->name, "Name of Port");
542 	}
543 }
544 
545 static void
546 dev_add_lun_bdev_not_found(void)
547 {
548 	int rc;
549 	struct spdk_scsi_dev dev = { .luns = TAILQ_HEAD_INITIALIZER(dev.luns), };
550 
551 	rc = spdk_scsi_dev_add_lun(&dev, "malloc3", 0, NULL, NULL);
552 
553 	SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&dev.luns));
554 	CU_ASSERT_NOT_EQUAL(rc, 0);
555 }
556 
557 static void
558 dev_add_lun_no_free_lun_id(void)
559 {
560 	int rc;
561 	int i;
562 	struct spdk_scsi_dev dev = { .luns = TAILQ_HEAD_INITIALIZER(dev.luns), };
563 	struct spdk_scsi_lun *lun;
564 
565 	lun = calloc(SPDK_SCSI_DEV_MAX_LUN, sizeof(*lun));
566 	SPDK_CU_ASSERT_FATAL(lun != NULL);
567 
568 	for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) {
569 		lun[i].id = i;
570 		TAILQ_INSERT_TAIL(&dev.luns, &lun[i], tailq);
571 	}
572 
573 	rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL);
574 
575 	CU_ASSERT_NOT_EQUAL(rc, 0);
576 
577 	free(lun);
578 }
579 
580 static void
581 dev_add_lun_success1(void)
582 {
583 	int rc;
584 	struct spdk_scsi_dev dev = { .luns = TAILQ_HEAD_INITIALIZER(dev.luns), };
585 
586 	rc = spdk_scsi_dev_add_lun(&dev, "malloc0", -1, NULL, NULL);
587 
588 	CU_ASSERT_EQUAL(rc, 0);
589 
590 	spdk_scsi_dev_destruct(&dev, NULL, NULL);
591 }
592 
593 static void
594 dev_add_lun_success2(void)
595 {
596 	int rc;
597 	struct spdk_scsi_dev dev = { .luns = TAILQ_HEAD_INITIALIZER(dev.luns), };
598 
599 	rc = spdk_scsi_dev_add_lun(&dev, "malloc0", 0, NULL, NULL);
600 
601 	CU_ASSERT_EQUAL(rc, 0);
602 
603 	spdk_scsi_dev_destruct(&dev, NULL, NULL);
604 }
605 
606 static void
607 dev_check_pending_tasks(void)
608 {
609 	struct spdk_scsi_dev dev = { .luns = TAILQ_HEAD_INITIALIZER(dev.luns), };
610 	struct spdk_scsi_lun lun = { .id = SPDK_SCSI_DEV_MAX_LUN - 1, };
611 	struct spdk_scsi_port initiator_port = {};
612 
613 	g_initiator_port_with_pending_tasks = NULL;
614 	g_initiator_port_with_pending_mgmt_tasks = NULL;
615 
616 	CU_ASSERT(spdk_scsi_dev_has_pending_tasks(&dev, NULL) == false);
617 
618 	TAILQ_INSERT_TAIL(&dev.luns, &lun, tailq);
619 
620 	CU_ASSERT(spdk_scsi_dev_has_pending_tasks(&dev, NULL) == true);
621 	CU_ASSERT(spdk_scsi_dev_has_pending_tasks(&dev, &initiator_port) == false);
622 
623 	g_initiator_port_with_pending_tasks = &initiator_port;
624 	CU_ASSERT(spdk_scsi_dev_has_pending_tasks(&dev, NULL) == true);
625 	CU_ASSERT(spdk_scsi_dev_has_pending_tasks(&dev, &initiator_port) == true);
626 
627 	g_initiator_port_with_pending_tasks = NULL;
628 	g_initiator_port_with_pending_mgmt_tasks = &initiator_port;
629 	CU_ASSERT(spdk_scsi_dev_has_pending_tasks(&dev, NULL) == true);
630 	CU_ASSERT(spdk_scsi_dev_has_pending_tasks(&dev, &initiator_port) == true);
631 }
632 
633 static void
634 dev_iterate_luns(void)
635 {
636 	struct spdk_scsi_dev *dev;
637 	struct spdk_scsi_lun *lun;
638 	const char *bdev_name_list[3] = {"malloc0", "malloc2", "malloc4"};
639 	int lun_id_list[3] = {0, 2, 4};
640 
641 	dev = spdk_scsi_dev_construct("Name", bdev_name_list, lun_id_list, 3,
642 				      SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI, NULL, NULL);
643 
644 	/* Successfully constructs and returns a dev */
645 	CU_ASSERT_TRUE(dev != NULL);
646 
647 	lun = spdk_scsi_dev_get_first_lun(dev);
648 	CU_ASSERT(lun != NULL);
649 	CU_ASSERT(lun->id == 0);
650 	lun = spdk_scsi_dev_get_next_lun(lun);
651 	CU_ASSERT(lun != NULL);
652 	CU_ASSERT(lun->id == 2);
653 	lun = spdk_scsi_dev_get_next_lun(lun);
654 	CU_ASSERT(lun != NULL);
655 	CU_ASSERT(lun->id == 4);
656 	lun = spdk_scsi_dev_get_next_lun(lun);
657 	CU_ASSERT(lun == NULL);
658 
659 	/* free the dev */
660 	spdk_scsi_dev_destruct(dev, NULL, NULL);
661 }
662 
663 static void
664 dev_find_free_lun(void)
665 {
666 	struct spdk_scsi_dev dev = { .luns = TAILQ_HEAD_INITIALIZER(dev.luns), };
667 	struct spdk_scsi_lun *lun, *prev_lun = NULL;
668 	int i, rc;
669 
670 	lun = calloc(SPDK_SCSI_DEV_MAX_LUN, sizeof(*lun));
671 	SPDK_CU_ASSERT_FATAL(lun != NULL);
672 
673 	for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) {
674 		lun[i].id = i;
675 	}
676 
677 	/* LUN ID 0, 1, 15, 16, 17, SPDK_SCSI_DEV_MAX_LUN - 2, and SPDK_SCSI_DEV_MAX_LUN - 1
678 	 * are free first. LUNs are required to be sorted by LUN ID.
679 	 */
680 	for (i = 2; i < 15; i++) {
681 		TAILQ_INSERT_TAIL(&dev.luns, &lun[i], tailq);
682 	}
683 
684 	for (i = 18; i < SPDK_SCSI_DEV_MAX_LUN - 2; i++) {
685 		TAILQ_INSERT_TAIL(&dev.luns, &lun[i], tailq);
686 	}
687 
688 	rc = scsi_dev_find_free_lun(&dev, -1, &prev_lun);
689 	CU_ASSERT(rc == 0);
690 	CU_ASSERT(prev_lun == NULL);
691 
692 	rc = scsi_dev_find_free_lun(&dev, 0, &prev_lun);
693 	CU_ASSERT(rc == 0);
694 	CU_ASSERT(prev_lun == NULL);
695 
696 	rc = scsi_dev_find_free_lun(&dev, 1, &prev_lun);
697 	CU_ASSERT(rc == 0);
698 	CU_ASSERT(prev_lun == NULL);
699 
700 	rc = scsi_dev_find_free_lun(&dev, 2, &prev_lun);
701 	CU_ASSERT(rc == -EEXIST);
702 
703 	TAILQ_INSERT_HEAD(&dev.luns, &lun[0], tailq);
704 
705 	rc = scsi_dev_find_free_lun(&dev, 0, &prev_lun);
706 	CU_ASSERT(rc == -EEXIST);
707 
708 	rc = scsi_dev_find_free_lun(&dev, -1, &prev_lun);
709 	CU_ASSERT(rc == 0);
710 	CU_ASSERT(prev_lun == &lun[0]);
711 	prev_lun = NULL;
712 
713 	rc = scsi_dev_find_free_lun(&dev, 1, &prev_lun);
714 	CU_ASSERT(rc == 0);
715 	CU_ASSERT(prev_lun == &lun[0]);
716 	prev_lun = NULL;
717 
718 	TAILQ_INSERT_AFTER(&dev.luns, &lun[0], &lun[1], tailq);
719 
720 	rc = scsi_dev_find_free_lun(&dev, 1, &prev_lun);
721 	CU_ASSERT(rc == -EEXIST);
722 
723 	rc = scsi_dev_find_free_lun(&dev, -1, &prev_lun);
724 	CU_ASSERT(rc == 0);
725 	CU_ASSERT(prev_lun == &lun[14]);
726 	prev_lun = NULL;
727 
728 	rc = scsi_dev_find_free_lun(&dev, 15, &prev_lun);
729 	CU_ASSERT(rc == 0);
730 	CU_ASSERT(prev_lun == &lun[14]);
731 	prev_lun = NULL;
732 
733 	rc = scsi_dev_find_free_lun(&dev, 16, &prev_lun);
734 	CU_ASSERT(rc == 0);
735 	CU_ASSERT(prev_lun == &lun[14]);
736 	prev_lun = NULL;
737 
738 	rc = scsi_dev_find_free_lun(&dev, 17, &prev_lun);
739 	CU_ASSERT(rc == 0);
740 	CU_ASSERT(prev_lun == &lun[14]);
741 	prev_lun = NULL;
742 
743 	TAILQ_INSERT_AFTER(&dev.luns, &lun[14], &lun[15], tailq);
744 	TAILQ_INSERT_AFTER(&dev.luns, &lun[15], &lun[16], tailq);
745 	TAILQ_INSERT_AFTER(&dev.luns, &lun[16], &lun[17], tailq);
746 
747 	rc = scsi_dev_find_free_lun(&dev, 15, &prev_lun);
748 	CU_ASSERT(rc == -EEXIST);
749 
750 	rc = scsi_dev_find_free_lun(&dev, 16, &prev_lun);
751 	CU_ASSERT(rc == -EEXIST);
752 
753 	rc = scsi_dev_find_free_lun(&dev, 17, &prev_lun);
754 	CU_ASSERT(rc == -EEXIST);
755 
756 	rc = scsi_dev_find_free_lun(&dev, -1, &prev_lun);
757 	CU_ASSERT(rc == 0);
758 	CU_ASSERT(prev_lun == &lun[SPDK_SCSI_DEV_MAX_LUN - 3]);
759 	prev_lun = NULL;
760 
761 	rc = scsi_dev_find_free_lun(&dev, SPDK_SCSI_DEV_MAX_LUN - 2, &prev_lun);
762 	CU_ASSERT(rc == 0);
763 	CU_ASSERT(prev_lun == &lun[SPDK_SCSI_DEV_MAX_LUN - 3]);
764 	prev_lun = NULL;
765 
766 	rc = scsi_dev_find_free_lun(&dev, SPDK_SCSI_DEV_MAX_LUN - 1, &prev_lun);
767 	CU_ASSERT(rc == 0);
768 	CU_ASSERT(prev_lun == &lun[SPDK_SCSI_DEV_MAX_LUN - 3]);
769 	prev_lun = NULL;
770 
771 	TAILQ_INSERT_AFTER(&dev.luns, &lun[SPDK_SCSI_DEV_MAX_LUN - 3],
772 			   &lun[SPDK_SCSI_DEV_MAX_LUN - 1], tailq);
773 
774 	rc = scsi_dev_find_free_lun(&dev, -1, &prev_lun);
775 	CU_ASSERT(rc == 0);
776 	CU_ASSERT(prev_lun == &lun[SPDK_SCSI_DEV_MAX_LUN - 3]);
777 	prev_lun = NULL;
778 
779 	rc = scsi_dev_find_free_lun(&dev, SPDK_SCSI_DEV_MAX_LUN - 2, &prev_lun);
780 	CU_ASSERT(rc == 0);
781 	CU_ASSERT(prev_lun == &lun[SPDK_SCSI_DEV_MAX_LUN - 3]);
782 	prev_lun = NULL;
783 
784 	TAILQ_INSERT_AFTER(&dev.luns, &lun[SPDK_SCSI_DEV_MAX_LUN - 3],
785 			   &lun[SPDK_SCSI_DEV_MAX_LUN - 2], tailq);
786 
787 	rc = scsi_dev_find_free_lun(&dev, -1, &prev_lun);
788 	CU_ASSERT(rc == -ENOSPC);
789 
790 	/* LUN ID 20 and 21 were freed. */
791 	TAILQ_REMOVE(&dev.luns, &lun[20], tailq);
792 	TAILQ_REMOVE(&dev.luns, &lun[21], tailq);
793 
794 	rc = scsi_dev_find_free_lun(&dev, -1, &prev_lun);
795 	CU_ASSERT(rc == 0);
796 	CU_ASSERT(prev_lun == &lun[19]);
797 	prev_lun = NULL;
798 
799 	rc = scsi_dev_find_free_lun(&dev, 21, &prev_lun);
800 	CU_ASSERT(rc  == 0);
801 	CU_ASSERT(prev_lun == &lun[19]);
802 	prev_lun = NULL;
803 
804 	free(lun);
805 }
806 
807 int
808 main(int argc, char **argv)
809 {
810 	CU_pSuite	suite = NULL;
811 	unsigned int	num_failures;
812 
813 	CU_set_error_action(CUEA_ABORT);
814 	CU_initialize_registry();
815 
816 	suite = CU_add_suite("dev_suite", NULL, NULL);
817 
818 	CU_ADD_TEST(suite, dev_destruct_null_dev);
819 	CU_ADD_TEST(suite, dev_destruct_zero_luns);
820 	CU_ADD_TEST(suite, dev_destruct_null_lun);
821 	CU_ADD_TEST(suite, dev_destruct_success);
822 	CU_ADD_TEST(suite, dev_construct_num_luns_zero);
823 	CU_ADD_TEST(suite, dev_construct_no_lun_zero);
824 	CU_ADD_TEST(suite, dev_construct_null_lun);
825 	CU_ADD_TEST(suite, dev_construct_name_too_long);
826 	CU_ADD_TEST(suite, dev_construct_success);
827 	CU_ADD_TEST(suite, dev_construct_success_lun_zero_not_first);
828 	CU_ADD_TEST(suite, dev_queue_mgmt_task_success);
829 	CU_ADD_TEST(suite, dev_queue_task_success);
830 	CU_ADD_TEST(suite, dev_stop_success);
831 	CU_ADD_TEST(suite, dev_add_port_max_ports);
832 	CU_ADD_TEST(suite, dev_add_port_construct_failure1);
833 	CU_ADD_TEST(suite, dev_add_port_construct_failure2);
834 	CU_ADD_TEST(suite, dev_add_port_success1);
835 	CU_ADD_TEST(suite, dev_add_port_success2);
836 	CU_ADD_TEST(suite, dev_add_port_success3);
837 	CU_ADD_TEST(suite, dev_find_port_by_id_num_ports_zero);
838 	CU_ADD_TEST(suite, dev_find_port_by_id_id_not_found_failure);
839 	CU_ADD_TEST(suite, dev_find_port_by_id_success);
840 	CU_ADD_TEST(suite, dev_add_lun_bdev_not_found);
841 	CU_ADD_TEST(suite, dev_add_lun_no_free_lun_id);
842 	CU_ADD_TEST(suite, dev_add_lun_success1);
843 	CU_ADD_TEST(suite, dev_add_lun_success2);
844 	CU_ADD_TEST(suite, dev_check_pending_tasks);
845 	CU_ADD_TEST(suite, dev_iterate_luns);
846 	CU_ADD_TEST(suite, dev_find_free_lun);
847 
848 	CU_basic_set_mode(CU_BRM_VERBOSE);
849 	CU_basic_run_tests();
850 	num_failures = CU_get_number_of_failures();
851 	CU_cleanup_registry();
852 
853 	return num_failures;
854 }
855