Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2016 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : :
8 : : #include "spdk_internal/cunit.h"
9 : :
10 : : #include "scsi/task.c"
11 : : #include "scsi/lun.c"
12 : :
13 : : #include "spdk_internal/mock.h"
14 : : /* These unit tests aren't multithreads, but we need to allocate threads since
15 : : * the lun.c code will register pollers.
16 : : */
17 : : #include "common/lib/ut_multithread.c"
18 : :
19 : : /* Unit test bdev mockup */
20 : : struct spdk_bdev {
21 : : int x;
22 : : };
23 : :
24 : 5 : SPDK_LOG_REGISTER_COMPONENT(scsi)
25 : :
26 : : static bool g_lun_execute_fail = false;
27 : : static int g_lun_execute_status = SPDK_SCSI_TASK_PENDING;
28 : : static uint32_t g_task_count = 0;
29 : :
30 [ # # # # ]: 0 : DEFINE_STUB(bdev_scsi_get_dif_ctx, bool,
31 : : (struct spdk_bdev *bdev, struct spdk_scsi_task *task,
32 : : struct spdk_dif_ctx *dif_ctx), false);
33 : :
34 : : static void
35 : 100 : spdk_lun_ut_cpl_task(struct spdk_scsi_task *task)
36 : : {
37 [ - + ]: 100 : SPDK_CU_ASSERT_FATAL(g_task_count > 0);
38 : 100 : g_task_count--;
39 : 100 : }
40 : :
41 : : static void
42 : 10 : spdk_lun_ut_free_task(struct spdk_scsi_task *task)
43 : : {
44 : 10 : }
45 : :
46 : : static void
47 : 115 : ut_init_task(struct spdk_scsi_task *task)
48 : : {
49 [ - + ]: 115 : memset(task, 0, sizeof(*task));
50 : 115 : spdk_scsi_task_construct(task, spdk_lun_ut_cpl_task,
51 : : spdk_lun_ut_free_task);
52 : 115 : g_task_count++;
53 : 115 : }
54 : :
55 : : void
56 : 0 : spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
57 : : {
58 : 0 : CU_ASSERT(0);
59 : 0 : }
60 : :
61 [ - + ]: 70 : DEFINE_STUB(spdk_bdev_open_ext, int,
62 : : (const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
63 : : void *event_ctx, struct spdk_bdev_desc **desc),
64 : : 0);
65 : :
66 : 70 : DEFINE_STUB_V(spdk_bdev_close, (struct spdk_bdev_desc *desc));
67 : :
68 [ # # ]: 0 : DEFINE_STUB(spdk_bdev_get_name, const char *,
69 : : (const struct spdk_bdev *bdev), "test");
70 : :
71 [ - + ]: 70 : DEFINE_STUB(spdk_bdev_desc_get_bdev, struct spdk_bdev *,
72 : : (struct spdk_bdev_desc *bdev_desc), NULL);
73 : :
74 : 0 : DEFINE_STUB_V(spdk_scsi_dev_queue_mgmt_task,
75 : : (struct spdk_scsi_dev *dev, struct spdk_scsi_task *task));
76 : :
77 : 70 : DEFINE_STUB_V(spdk_scsi_dev_delete_lun,
78 : : (struct spdk_scsi_dev *dev, struct spdk_scsi_lun *lun));
79 : :
80 [ - + ]: 30 : DEFINE_STUB(scsi_pr_check, int, (struct spdk_scsi_task *task), 0);
81 [ # # ]: 0 : DEFINE_STUB(scsi2_reserve_check, int, (struct spdk_scsi_task *task), 0);
82 : :
83 : : void
84 : 35 : bdev_scsi_reset(struct spdk_scsi_task *task)
85 : : {
86 : 35 : task->status = SPDK_SCSI_STATUS_GOOD;
87 : 35 : task->response = SPDK_SCSI_TASK_MGMT_RESP_SUCCESS;
88 : :
89 : 35 : scsi_lun_complete_reset_task(task->lun, task);
90 : 35 : }
91 : :
92 : : int
93 : 30 : bdev_scsi_execute(struct spdk_scsi_task *task)
94 : : {
95 [ - + - + ]: 30 : if (g_lun_execute_fail) {
96 : 0 : return -EINVAL;
97 : : } else {
98 : 30 : task->status = SPDK_SCSI_STATUS_GOOD;
99 : :
100 [ + + ]: 30 : if (g_lun_execute_status == SPDK_SCSI_TASK_PENDING) {
101 : 20 : return g_lun_execute_status;
102 [ + - ]: 10 : } else if (g_lun_execute_status == SPDK_SCSI_TASK_COMPLETE) {
103 : 10 : return g_lun_execute_status;
104 : : } else {
105 : 0 : return 0;
106 : : }
107 : : }
108 : : }
109 : :
110 [ # # ]: 0 : DEFINE_STUB(spdk_bdev_get_io_channel, struct spdk_io_channel *,
111 : : (struct spdk_bdev_desc *desc), NULL);
112 : :
113 : : static struct spdk_scsi_lun *
114 : 60 : lun_construct(void)
115 : : {
116 : : struct spdk_scsi_lun *lun;
117 : :
118 : 60 : lun = scsi_lun_construct("ut_bdev", NULL, NULL, NULL, NULL);
119 : :
120 [ - + ]: 60 : SPDK_CU_ASSERT_FATAL(lun != NULL);
121 : 60 : return lun;
122 : : }
123 : :
124 : : static void
125 : 55 : lun_destruct(struct spdk_scsi_lun *lun)
126 : : {
127 : : /* LUN will defer its removal if there are any unfinished tasks */
128 [ - + ]: 55 : SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&lun->tasks));
129 : :
130 : 55 : scsi_lun_destruct(lun);
131 : 55 : }
132 : :
133 : : static void
134 : 5 : lun_task_mgmt_execute_abort_task_not_supported(void)
135 : : {
136 : : struct spdk_scsi_lun *lun;
137 : 5 : struct spdk_scsi_task task = { 0 };
138 : 5 : struct spdk_scsi_task mgmt_task = { 0 };
139 : 5 : struct spdk_scsi_port initiator_port = { 0 };
140 : 5 : struct spdk_scsi_dev dev = { 0 };
141 : 5 : uint8_t cdb[6] = { 0 };
142 : :
143 : 5 : lun = lun_construct();
144 : 5 : lun->dev = &dev;
145 : :
146 : 5 : ut_init_task(&mgmt_task);
147 : 5 : mgmt_task.lun = lun;
148 : 5 : mgmt_task.initiator_port = &initiator_port;
149 : 5 : mgmt_task.function = SPDK_SCSI_TASK_FUNC_ABORT_TASK;
150 : :
151 : : /* Params to add regular task to the lun->tasks */
152 : 5 : ut_init_task(&task);
153 : 5 : task.lun = lun;
154 : 5 : task.cdb = cdb;
155 : :
156 : 5 : scsi_lun_execute_task(lun, &task);
157 : :
158 : : /* task should now be on the tasks list */
159 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));
160 : :
161 : 5 : scsi_lun_execute_mgmt_task(lun, &mgmt_task);
162 : :
163 : : /* task abort is not supported */
164 : 5 : CU_ASSERT(mgmt_task.response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED);
165 : :
166 : : /* task is still on the tasks list */
167 : 5 : CU_ASSERT_EQUAL(g_task_count, 1);
168 : :
169 : 5 : scsi_lun_complete_task(lun, &task);
170 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
171 : :
172 : 5 : lun_destruct(lun);
173 : 5 : }
174 : :
175 : : static void
176 : 5 : lun_task_mgmt_execute_abort_task_all_not_supported(void)
177 : : {
178 : : struct spdk_scsi_lun *lun;
179 : 5 : struct spdk_scsi_task task = { 0 };
180 : 5 : struct spdk_scsi_task mgmt_task = { 0 };
181 : 5 : struct spdk_scsi_port initiator_port = { 0 };
182 : 5 : struct spdk_scsi_dev dev = { 0 };
183 : 5 : uint8_t cdb[6] = { 0 };
184 : :
185 : 5 : lun = lun_construct();
186 : 5 : lun->dev = &dev;
187 : :
188 : 5 : ut_init_task(&mgmt_task);
189 : 5 : mgmt_task.lun = lun;
190 : 5 : mgmt_task.initiator_port = &initiator_port;
191 : 5 : mgmt_task.function = SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET;
192 : :
193 : : /* Params to add regular task to the lun->tasks */
194 : 5 : ut_init_task(&task);
195 : 5 : task.initiator_port = &initiator_port;
196 : 5 : task.lun = lun;
197 : 5 : task.cdb = cdb;
198 : :
199 : 5 : scsi_lun_execute_task(lun, &task);
200 : :
201 : : /* task should now be on the tasks list */
202 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));
203 : :
204 : 5 : scsi_lun_execute_mgmt_task(lun, &mgmt_task);
205 : :
206 : : /* task abort is not supported */
207 : 5 : CU_ASSERT(mgmt_task.response == SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED);
208 : :
209 : : /* task is still on the tasks list */
210 : 5 : CU_ASSERT_EQUAL(g_task_count, 1);
211 : :
212 : 5 : scsi_lun_complete_task(lun, &task);
213 : :
214 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
215 : :
216 : 5 : lun_destruct(lun);
217 : 5 : }
218 : :
219 : : static void
220 : 5 : lun_task_mgmt_execute_lun_reset(void)
221 : : {
222 : : struct spdk_scsi_lun *lun;
223 : 5 : struct spdk_scsi_task mgmt_task = { 0 };
224 : 5 : struct spdk_scsi_dev dev = { 0 };
225 : :
226 : 5 : lun = lun_construct();
227 : 5 : lun->dev = &dev;
228 : :
229 : 5 : ut_init_task(&mgmt_task);
230 : 5 : mgmt_task.lun = lun;
231 : 5 : mgmt_task.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
232 : :
233 : 5 : scsi_lun_execute_mgmt_task(lun, &mgmt_task);
234 : :
235 : : /* Returns success */
236 : 5 : CU_ASSERT_EQUAL(mgmt_task.status, SPDK_SCSI_STATUS_GOOD);
237 : 5 : CU_ASSERT_EQUAL(mgmt_task.response, SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
238 : :
239 : 5 : lun_destruct(lun);
240 : :
241 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
242 : 5 : }
243 : :
244 : : static void
245 : 5 : lun_task_mgmt_execute_target_reset(void)
246 : : {
247 : : struct spdk_scsi_lun *lun;
248 : 5 : struct spdk_scsi_task mgmt_task = { 0 };
249 : 5 : struct spdk_scsi_dev dev = { 0 };
250 : :
251 : 5 : lun = lun_construct();
252 : 5 : lun->dev = &dev;
253 : :
254 : 5 : ut_init_task(&mgmt_task);
255 : 5 : mgmt_task.lun = lun;
256 : 5 : mgmt_task.function = SPDK_SCSI_TASK_FUNC_TARGET_RESET;
257 : :
258 : 5 : scsi_lun_execute_mgmt_task(lun, &mgmt_task);
259 : :
260 : : /* Returns success */
261 : 5 : CU_ASSERT_EQUAL(mgmt_task.status, SPDK_SCSI_STATUS_GOOD);
262 : 5 : CU_ASSERT_EQUAL(mgmt_task.response, SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
263 : :
264 : 5 : lun_destruct(lun);
265 : :
266 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
267 : 5 : }
268 : :
269 : : static void
270 : 5 : lun_task_mgmt_execute_invalid_case(void)
271 : : {
272 : : struct spdk_scsi_lun *lun;
273 : 5 : struct spdk_scsi_task mgmt_task = { 0 };
274 : 5 : struct spdk_scsi_dev dev = { 0 };
275 : :
276 : 5 : lun = lun_construct();
277 : 5 : lun->dev = &dev;
278 : :
279 : 5 : ut_init_task(&mgmt_task);
280 : 5 : mgmt_task.function = 6;
281 : :
282 : : /* Pass an invalid value to the switch statement */
283 : 5 : scsi_lun_execute_mgmt_task(lun, &mgmt_task);
284 : :
285 : : /* function code is invalid */
286 : 5 : CU_ASSERT_EQUAL(mgmt_task.response, SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED);
287 : :
288 : 5 : lun_destruct(lun);
289 : :
290 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
291 : 5 : }
292 : :
293 : : static void
294 : 5 : lun_append_task_null_lun_task_cdb_spc_inquiry(void)
295 : : {
296 : 5 : struct spdk_scsi_task task = { 0 };
297 : 5 : uint8_t cdb[6] = { 0 };
298 : :
299 : 5 : ut_init_task(&task);
300 : 5 : task.cdb = cdb;
301 : 5 : task.cdb[0] = SPDK_SPC_INQUIRY;
302 : : /* alloc_len >= 4096 */
303 : 5 : task.cdb[3] = 0xFF;
304 : 5 : task.cdb[4] = 0xFF;
305 : 5 : task.lun = NULL;
306 : :
307 : 5 : spdk_scsi_task_process_null_lun(&task);
308 : :
309 : 5 : CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_GOOD);
310 : :
311 : 5 : spdk_scsi_task_put(&task);
312 : :
313 : : /* spdk_scsi_task_process_null_lun() does not call cpl_fn */
314 : 5 : CU_ASSERT_EQUAL(g_task_count, 1);
315 : 5 : g_task_count = 0;
316 : 5 : }
317 : :
318 : : static void
319 : 5 : lun_append_task_null_lun_alloc_len_lt_4096(void)
320 : : {
321 : 5 : struct spdk_scsi_task task = { 0 };
322 : 5 : uint8_t cdb[6] = { 0 };
323 : :
324 : 5 : ut_init_task(&task);
325 : 5 : task.cdb = cdb;
326 : 5 : task.cdb[0] = SPDK_SPC_INQUIRY;
327 : : /* alloc_len < 4096 */
328 : 5 : task.cdb[3] = 0;
329 : 5 : task.cdb[4] = 0;
330 : : /* alloc_len is set to a minimal value of 4096
331 : : * Hence, buf of size 4096 is allocated */
332 : 5 : spdk_scsi_task_process_null_lun(&task);
333 : :
334 : 5 : CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_GOOD);
335 : :
336 : 5 : spdk_scsi_task_put(&task);
337 : :
338 : : /* spdk_scsi_task_process_null_lun() does not call cpl_fn */
339 : 5 : CU_ASSERT_EQUAL(g_task_count, 1);
340 : 5 : g_task_count = 0;
341 : 5 : }
342 : :
343 : : static void
344 : 5 : lun_append_task_null_lun_not_supported(void)
345 : : {
346 : 5 : struct spdk_scsi_task task = { 0 };
347 : 5 : uint8_t cdb[6] = { 0 };
348 : :
349 : 5 : ut_init_task(&task);
350 : 5 : task.cdb = cdb;
351 : 5 : task.lun = NULL;
352 : :
353 : 5 : spdk_scsi_task_process_null_lun(&task);
354 : :
355 : 5 : CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
356 : : /* LUN not supported; task's data transferred should be 0 */
357 : 5 : CU_ASSERT_EQUAL(task.data_transferred, 0);
358 : :
359 : : /* spdk_scsi_task_process_null_lun() does not call cpl_fn */
360 : 5 : CU_ASSERT_EQUAL(g_task_count, 1);
361 : 5 : g_task_count = 0;
362 : 5 : }
363 : :
364 : : static void
365 : 5 : lun_execute_scsi_task_pending(void)
366 : : {
367 : : struct spdk_scsi_lun *lun;
368 : 5 : struct spdk_scsi_task task = { 0 };
369 : 5 : struct spdk_scsi_dev dev = { 0 };
370 : :
371 : 5 : lun = lun_construct();
372 : :
373 : 5 : ut_init_task(&task);
374 : 5 : task.lun = lun;
375 : 5 : lun->dev = &dev;
376 : :
377 : 5 : g_lun_execute_fail = false;
378 : 5 : g_lun_execute_status = SPDK_SCSI_TASK_PENDING;
379 : :
380 : : /* the tasks list should still be empty since it has not been
381 : : executed yet
382 : : */
383 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
384 : :
385 : 5 : scsi_lun_execute_task(lun, &task);
386 : :
387 : : /* Assert the task has been successfully added to the tasks queue */
388 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));
389 : :
390 : : /* task is still on the tasks list */
391 : 5 : CU_ASSERT_EQUAL(g_task_count, 1);
392 : :
393 : : /* Need to complete task so LUN might be removed right now */
394 : 5 : scsi_lun_complete_task(lun, &task);
395 : :
396 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
397 : :
398 : 5 : lun_destruct(lun);
399 : 5 : }
400 : :
401 : : static void
402 : 5 : lun_execute_scsi_task_complete(void)
403 : : {
404 : : struct spdk_scsi_lun *lun;
405 : 5 : struct spdk_scsi_task task = { 0 };
406 : 5 : struct spdk_scsi_dev dev = { 0 };
407 : :
408 : 5 : lun = lun_construct();
409 : :
410 : 5 : ut_init_task(&task);
411 : 5 : task.lun = lun;
412 : 5 : lun->dev = &dev;
413 : :
414 : 5 : g_lun_execute_fail = false;
415 : 5 : g_lun_execute_status = SPDK_SCSI_TASK_COMPLETE;
416 : :
417 : : /* the tasks list should still be empty since it has not been
418 : : executed yet
419 : : */
420 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
421 : :
422 : 5 : scsi_lun_execute_task(lun, &task);
423 : :
424 : : /* Assert the task has not been added to the tasks queue */
425 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
426 : :
427 : 5 : lun_destruct(lun);
428 : :
429 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
430 : 5 : }
431 : :
432 : : static void
433 : 5 : lun_execute_scsi_task_resize(void)
434 : : {
435 : : struct spdk_scsi_lun *lun;
436 : 5 : struct spdk_scsi_task task = { 0 };
437 : 5 : struct spdk_scsi_dev dev = { 0 };
438 : 5 : uint8_t cdb = SPDK_SBC_READ_16;
439 : :
440 : 5 : lun = lun_construct();
441 : :
442 : 5 : ut_init_task(&task);
443 : 5 : task.lun = lun;
444 : 5 : task.cdb = &cdb;
445 : 5 : lun->dev = &dev;
446 : 5 : lun->resizing = true;
447 : :
448 : : /* the tasks list should still be empty since it has not been
449 : : executed yet
450 : : */
451 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
452 : :
453 : 5 : scsi_lun_execute_task(lun, &task);
454 : 5 : CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
455 : : /* SENSE KEY */
456 : 5 : CU_ASSERT_EQUAL(task.sense_data[2], SPDK_SCSI_SENSE_UNIT_ATTENTION);
457 : : /* SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED: 0x2a09 */
458 : 5 : CU_ASSERT_EQUAL(task.sense_data[12], SPDK_SCSI_ASC_CAPACITY_DATA_HAS_CHANGED);
459 : 5 : CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_CAPACITY_DATA_HAS_CHANGED);
460 [ - + ]: 5 : CU_ASSERT(lun->resizing == false);
461 : :
462 : : /* Assert the task has not been added to the tasks queue */
463 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
464 : :
465 : 5 : lun_destruct(lun);
466 : :
467 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
468 : 5 : }
469 : :
470 : : static void
471 : 5 : lun_destruct_success(void)
472 : : {
473 : : struct spdk_scsi_lun *lun;
474 : :
475 : 5 : lun = lun_construct();
476 : :
477 : 5 : scsi_lun_destruct(lun);
478 : :
479 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
480 : 5 : }
481 : :
482 : : static void
483 : 5 : lun_construct_null_ctx(void)
484 : : {
485 : : struct spdk_scsi_lun *lun;
486 : :
487 : 5 : lun = scsi_lun_construct(NULL, NULL, NULL, NULL, NULL);
488 : :
489 : : /* lun should be NULL since we passed NULL for the ctx pointer. */
490 : 5 : CU_ASSERT(lun == NULL);
491 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
492 : 5 : }
493 : :
494 : : static void
495 : 5 : lun_construct_success(void)
496 : : {
497 : 5 : struct spdk_scsi_lun *lun = lun_construct();
498 : :
499 : 5 : lun_destruct(lun);
500 : :
501 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
502 : 5 : }
503 : :
504 : : static void
505 : 5 : lun_reset_task_wait_scsi_task_complete(void)
506 : : {
507 : : struct spdk_scsi_lun *lun;
508 : 5 : struct spdk_scsi_task task = { 0 };
509 : 5 : struct spdk_scsi_task mgmt_task = { 0 };
510 : 5 : struct spdk_scsi_dev dev = { 0 };
511 : :
512 : 5 : lun = lun_construct();
513 : 5 : lun->dev = &dev;
514 : :
515 : 5 : ut_init_task(&task);
516 : 5 : task.lun = lun;
517 : :
518 : 5 : g_lun_execute_fail = false;
519 : 5 : g_lun_execute_status = SPDK_SCSI_TASK_PENDING;
520 : :
521 : 5 : ut_init_task(&mgmt_task);
522 : 5 : mgmt_task.lun = lun;
523 : 5 : mgmt_task.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
524 : :
525 : : /* Execute the task but it is still in the task list. */
526 : 5 : scsi_lun_execute_task(lun, &task);
527 : :
528 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->pending_tasks));
529 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->tasks));
530 : :
531 : : /* Execute the reset task */
532 : 5 : scsi_lun_execute_mgmt_task(lun, &mgmt_task);
533 : :
534 : : /* The reset task should be on the submitted mgmt task list and
535 : : * a poller is created because the task prior to the reset task is pending.
536 : : */
537 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->mgmt_tasks));
538 : 5 : CU_ASSERT(lun->reset_poller != NULL);
539 : :
540 : : /* Execute the poller to check if the task prior to the reset task complete. */
541 : 5 : scsi_lun_reset_check_outstanding_tasks(&mgmt_task);
542 : :
543 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->mgmt_tasks));
544 : 5 : CU_ASSERT(lun->reset_poller != NULL);
545 : :
546 : : /* Complete the task. */
547 : 5 : scsi_lun_complete_task(lun, &task);
548 : :
549 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
550 : :
551 : : /* Execute the poller to check if the task prior to the reset task complete. */
552 : 5 : scsi_lun_reset_check_outstanding_tasks(&mgmt_task);
553 : :
554 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->mgmt_tasks));
555 : 5 : CU_ASSERT(lun->reset_poller == NULL);
556 : 5 : CU_ASSERT_EQUAL(mgmt_task.status, SPDK_SCSI_STATUS_GOOD);
557 : 5 : CU_ASSERT_EQUAL(mgmt_task.response, SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
558 : :
559 : 5 : lun_destruct(lun);
560 : :
561 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
562 : 5 : }
563 : :
564 : : static void
565 : 5 : lun_reset_task_suspend_scsi_task(void)
566 : : {
567 : : struct spdk_scsi_lun *lun;
568 : 5 : struct spdk_scsi_task task = { 0 };
569 : 5 : struct spdk_scsi_task mgmt_task = { 0 };
570 : 5 : struct spdk_scsi_dev dev = { 0 };
571 : :
572 : 5 : lun = lun_construct();
573 : 5 : lun->dev = &dev;
574 : :
575 : 5 : ut_init_task(&task);
576 : 5 : task.lun = lun;
577 : :
578 : 5 : g_lun_execute_fail = false;
579 : 5 : g_lun_execute_status = SPDK_SCSI_TASK_COMPLETE;
580 : :
581 : 5 : ut_init_task(&mgmt_task);
582 : 5 : mgmt_task.lun = lun;
583 : 5 : mgmt_task.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
584 : :
585 : : /* Append a reset task to the pending mgmt task list. */
586 : 5 : scsi_lun_append_mgmt_task(lun, &mgmt_task);
587 : :
588 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->pending_mgmt_tasks));
589 : :
590 : : /* Execute the task but it is on the pending task list. */
591 : 5 : scsi_lun_execute_task(lun, &task);
592 : :
593 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->pending_tasks));
594 : :
595 : : /* Execute the reset task. The task will be executed then. */
596 : 5 : _scsi_lun_execute_mgmt_task(lun);
597 : :
598 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->mgmt_tasks));
599 : 5 : CU_ASSERT(lun->reset_poller == NULL);
600 : 5 : CU_ASSERT_EQUAL(mgmt_task.status, SPDK_SCSI_STATUS_GOOD);
601 : 5 : CU_ASSERT_EQUAL(mgmt_task.response, SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
602 : :
603 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->pending_tasks));
604 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->tasks));
605 : :
606 : 5 : lun_destruct(lun);
607 : :
608 : 5 : CU_ASSERT_EQUAL(g_task_count, 0);
609 : 5 : }
610 : :
611 : : static void
612 : 5 : lun_check_pending_tasks_only_for_specific_initiator(void)
613 : : {
614 : : struct spdk_scsi_lun *lun;
615 : 5 : struct spdk_scsi_task task1 = {};
616 : 5 : struct spdk_scsi_task task2 = {};
617 : 5 : struct spdk_scsi_port initiator_port1 = {};
618 : 5 : struct spdk_scsi_port initiator_port2 = {};
619 : 5 : struct spdk_scsi_port initiator_port3 = {};
620 : :
621 : 5 : lun = scsi_lun_construct("ut_bdev", NULL, NULL, NULL, NULL);
622 : :
623 : 5 : task1.initiator_port = &initiator_port1;
624 : 5 : task2.initiator_port = &initiator_port2;
625 : :
626 : 5 : TAILQ_INSERT_TAIL(&lun->tasks, &task1, scsi_link);
627 : 5 : TAILQ_INSERT_TAIL(&lun->tasks, &task2, scsi_link);
628 : 5 : CU_ASSERT(scsi_lun_has_outstanding_tasks(lun) == true);
629 : 5 : CU_ASSERT(_scsi_lun_has_pending_tasks(lun) == false);
630 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, NULL) == true);
631 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, &initiator_port1) == true);
632 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, &initiator_port2) == true);
633 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, &initiator_port3) == false);
634 [ + - ]: 5 : TAILQ_REMOVE(&lun->tasks, &task1, scsi_link);
635 [ - + ]: 5 : TAILQ_REMOVE(&lun->tasks, &task2, scsi_link);
636 : 5 : CU_ASSERT(_scsi_lun_has_pending_tasks(lun) == false);
637 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, NULL) == false);
638 : :
639 : 5 : TAILQ_INSERT_TAIL(&lun->pending_tasks, &task1, scsi_link);
640 : 5 : TAILQ_INSERT_TAIL(&lun->pending_tasks, &task2, scsi_link);
641 : 5 : CU_ASSERT(scsi_lun_has_outstanding_tasks(lun) == false);
642 : 5 : CU_ASSERT(_scsi_lun_has_pending_tasks(lun) == true);
643 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, NULL) == true);
644 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, &initiator_port1) == true);
645 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, &initiator_port2) == true);
646 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, &initiator_port3) == false);
647 [ + - ]: 5 : TAILQ_REMOVE(&lun->pending_tasks, &task1, scsi_link);
648 [ - + ]: 5 : TAILQ_REMOVE(&lun->pending_tasks, &task2, scsi_link);
649 : 5 : CU_ASSERT(_scsi_lun_has_pending_tasks(lun) == false);
650 : 5 : CU_ASSERT(scsi_lun_has_pending_tasks(lun, NULL) == false);
651 : :
652 : 5 : TAILQ_INSERT_TAIL(&lun->mgmt_tasks, &task1, scsi_link);
653 : 5 : TAILQ_INSERT_TAIL(&lun->mgmt_tasks, &task2, scsi_link);
654 : 5 : CU_ASSERT(scsi_lun_has_outstanding_mgmt_tasks(lun) == true);
655 : 5 : CU_ASSERT(_scsi_lun_has_pending_mgmt_tasks(lun) == false);
656 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, NULL) == true);
657 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, &initiator_port1) == true);
658 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, &initiator_port2) == true);
659 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, &initiator_port3) == false);
660 [ + - ]: 5 : TAILQ_REMOVE(&lun->mgmt_tasks, &task1, scsi_link);
661 [ - + ]: 5 : TAILQ_REMOVE(&lun->mgmt_tasks, &task2, scsi_link);
662 : 5 : CU_ASSERT(_scsi_lun_has_pending_mgmt_tasks(lun) == false);
663 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, NULL) == false);
664 : :
665 : 5 : TAILQ_INSERT_TAIL(&lun->pending_mgmt_tasks, &task1, scsi_link);
666 : 5 : TAILQ_INSERT_TAIL(&lun->pending_mgmt_tasks, &task2, scsi_link);
667 : 5 : CU_ASSERT(_scsi_lun_has_pending_mgmt_tasks(lun) == true);
668 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, NULL) == true);
669 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, &initiator_port1) == true);
670 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, &initiator_port2) == true);
671 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, &initiator_port3) == false);
672 [ + - ]: 5 : TAILQ_REMOVE(&lun->pending_mgmt_tasks, &task1, scsi_link);
673 [ - + ]: 5 : TAILQ_REMOVE(&lun->pending_mgmt_tasks, &task2, scsi_link);
674 : 5 : CU_ASSERT(_scsi_lun_has_pending_mgmt_tasks(lun) == false);
675 : 5 : CU_ASSERT(scsi_lun_has_pending_mgmt_tasks(lun, NULL) == false);
676 : :
677 : 5 : scsi_lun_remove(lun);
678 : 5 : }
679 : :
680 : : static void
681 : 5 : abort_pending_mgmt_tasks_when_lun_is_removed(void)
682 : : {
683 : : struct spdk_scsi_lun *lun;
684 : 4 : struct spdk_scsi_task task1, task2, task3;
685 : :
686 : 5 : lun = scsi_lun_construct("ut_bdev", NULL, NULL, NULL, NULL);
687 : :
688 : : /* Normal case */
689 : 5 : ut_init_task(&task1);
690 : 5 : ut_init_task(&task2);
691 : 5 : ut_init_task(&task3);
692 : 5 : task1.lun = lun;
693 : 5 : task2.lun = lun;
694 : 5 : task3.lun = lun;
695 : 5 : task1.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
696 : 5 : task2.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
697 : 5 : task3.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
698 : :
699 : 5 : CU_ASSERT(g_task_count == 3);
700 : :
701 : 5 : scsi_lun_append_mgmt_task(lun, &task1);
702 : 5 : scsi_lun_append_mgmt_task(lun, &task2);
703 : 5 : scsi_lun_append_mgmt_task(lun, &task3);
704 : :
705 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->pending_mgmt_tasks));
706 : :
707 : 5 : _scsi_lun_execute_mgmt_task(lun);
708 : :
709 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->pending_mgmt_tasks));
710 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->mgmt_tasks));
711 : 5 : CU_ASSERT(g_task_count == 0);
712 : 5 : CU_ASSERT(task1.response == SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
713 : 5 : CU_ASSERT(task2.response == SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
714 : 5 : CU_ASSERT(task3.response == SPDK_SCSI_TASK_MGMT_RESP_SUCCESS);
715 : :
716 : : /* LUN hotplug case */
717 : 5 : ut_init_task(&task1);
718 : 5 : ut_init_task(&task2);
719 : 5 : ut_init_task(&task3);
720 : 5 : task1.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
721 : 5 : task2.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
722 : 5 : task3.function = SPDK_SCSI_TASK_FUNC_LUN_RESET;
723 : :
724 : 5 : CU_ASSERT(g_task_count == 3);
725 : :
726 : 5 : scsi_lun_append_mgmt_task(lun, &task1);
727 : 5 : scsi_lun_append_mgmt_task(lun, &task2);
728 : 5 : scsi_lun_append_mgmt_task(lun, &task3);
729 : :
730 : 5 : CU_ASSERT(!TAILQ_EMPTY(&lun->pending_mgmt_tasks));
731 : :
732 : 5 : lun->removed = true;
733 : :
734 : 5 : _scsi_lun_execute_mgmt_task(lun);
735 : :
736 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->pending_mgmt_tasks));
737 : 5 : CU_ASSERT(TAILQ_EMPTY(&lun->mgmt_tasks));
738 : 5 : CU_ASSERT(g_task_count == 0);
739 : 5 : CU_ASSERT(task1.response == SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN);
740 : 5 : CU_ASSERT(task2.response == SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN);
741 : 5 : CU_ASSERT(task3.response == SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN);
742 : :
743 : 5 : scsi_lun_remove(lun);
744 : 5 : }
745 : :
746 : : int
747 : 5 : main(int argc, char **argv)
748 : : {
749 : 5 : CU_pSuite suite = NULL;
750 : : unsigned int num_failures;
751 : :
752 : 5 : CU_initialize_registry();
753 : :
754 : 5 : suite = CU_add_suite("lun_suite", NULL, NULL);
755 : :
756 : 5 : CU_ADD_TEST(suite, lun_task_mgmt_execute_abort_task_not_supported);
757 : 5 : CU_ADD_TEST(suite, lun_task_mgmt_execute_abort_task_all_not_supported);
758 : 5 : CU_ADD_TEST(suite, lun_task_mgmt_execute_lun_reset);
759 : 5 : CU_ADD_TEST(suite, lun_task_mgmt_execute_target_reset);
760 : 5 : CU_ADD_TEST(suite, lun_task_mgmt_execute_invalid_case);
761 : 5 : CU_ADD_TEST(suite, lun_append_task_null_lun_task_cdb_spc_inquiry);
762 : 5 : CU_ADD_TEST(suite, lun_append_task_null_lun_alloc_len_lt_4096);
763 : 5 : CU_ADD_TEST(suite, lun_append_task_null_lun_not_supported);
764 : 5 : CU_ADD_TEST(suite, lun_execute_scsi_task_pending);
765 : 5 : CU_ADD_TEST(suite, lun_execute_scsi_task_complete);
766 : 5 : CU_ADD_TEST(suite, lun_execute_scsi_task_resize);
767 : 5 : CU_ADD_TEST(suite, lun_destruct_success);
768 : 5 : CU_ADD_TEST(suite, lun_construct_null_ctx);
769 : 5 : CU_ADD_TEST(suite, lun_construct_success);
770 : 5 : CU_ADD_TEST(suite, lun_reset_task_wait_scsi_task_complete);
771 : 5 : CU_ADD_TEST(suite, lun_reset_task_suspend_scsi_task);
772 : 5 : CU_ADD_TEST(suite, lun_check_pending_tasks_only_for_specific_initiator);
773 : 5 : CU_ADD_TEST(suite, abort_pending_mgmt_tasks_when_lun_is_removed);
774 : :
775 : 5 : allocate_threads(1);
776 : 5 : set_thread(0);
777 : 5 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
778 : 5 : free_threads();
779 : 5 : CU_cleanup_registry();
780 : 5 : return num_failures;
781 : : }
|