1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
3 * Copyright (C) 2016 Intel Corporation.
4 * All rights reserved.
5 */
6
7 #include "scsi_internal.h"
8 #include "spdk/endian.h"
9 #include "spdk/env.h"
10 #include "spdk/thread.h"
11 #include "spdk/util.h"
12 #include "spdk/likely.h"
13
14 static void scsi_lun_execute_tasks(struct spdk_scsi_lun *lun);
15 static void _scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun);
16
17 void
scsi_lun_complete_task(struct spdk_scsi_lun * lun,struct spdk_scsi_task * task)18 scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
19 {
20 if (lun) {
21 TAILQ_REMOVE(&lun->tasks, task, scsi_link);
22 spdk_trace_record(TRACE_SCSI_TASK_DONE, lun->dev->id, 0, (uintptr_t)task);
23 }
24 task->cpl_fn(task);
25 }
26
27 static void
scsi_lun_complete_mgmt_task(struct spdk_scsi_lun * lun,struct spdk_scsi_task * task)28 scsi_lun_complete_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
29 {
30 TAILQ_REMOVE(&lun->mgmt_tasks, task, scsi_link);
31
32 task->cpl_fn(task);
33
34 /* Try to execute the first pending mgmt task if it exists. */
35 _scsi_lun_execute_mgmt_task(lun);
36 }
37
38 static bool
_scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun * lun)39 _scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun)
40 {
41 return !TAILQ_EMPTY(&lun->pending_mgmt_tasks);
42 }
43
44 static bool
scsi_lun_has_outstanding_mgmt_tasks(const struct spdk_scsi_lun * lun)45 scsi_lun_has_outstanding_mgmt_tasks(const struct spdk_scsi_lun *lun)
46 {
47 return !TAILQ_EMPTY(&lun->mgmt_tasks);
48 }
49
50 static bool
_scsi_lun_has_pending_tasks(const struct spdk_scsi_lun * lun)51 _scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun)
52 {
53 return !TAILQ_EMPTY(&lun->pending_tasks);
54 }
55
56 static bool
scsi_lun_has_outstanding_tasks(const struct spdk_scsi_lun * lun)57 scsi_lun_has_outstanding_tasks(const struct spdk_scsi_lun *lun)
58 {
59 return !TAILQ_EMPTY(&lun->tasks);
60 }
61
62 /* Reset task have to wait until all prior outstanding tasks complete. */
63 static int
scsi_lun_reset_check_outstanding_tasks(void * arg)64 scsi_lun_reset_check_outstanding_tasks(void *arg)
65 {
66 struct spdk_scsi_task *task = (struct spdk_scsi_task *)arg;
67 struct spdk_scsi_lun *lun = task->lun;
68
69 if (scsi_lun_has_outstanding_tasks(lun)) {
70 return SPDK_POLLER_BUSY;
71 }
72 spdk_poller_unregister(&lun->reset_poller);
73
74 scsi_lun_complete_mgmt_task(lun, task);
75 return SPDK_POLLER_BUSY;
76 }
77
78 void
scsi_lun_complete_reset_task(struct spdk_scsi_lun * lun,struct spdk_scsi_task * task)79 scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
80 {
81 if (task->status == SPDK_SCSI_STATUS_GOOD) {
82 if (scsi_lun_has_outstanding_tasks(lun)) {
83 lun->reset_poller =
84 SPDK_POLLER_REGISTER(scsi_lun_reset_check_outstanding_tasks,
85 task, 10);
86 return;
87 }
88 }
89
90 scsi_lun_complete_mgmt_task(lun, task);
91 }
92
93 static void
scsi_lun_append_mgmt_task(struct spdk_scsi_lun * lun,struct spdk_scsi_task * task)94 scsi_lun_append_mgmt_task(struct spdk_scsi_lun *lun,
95 struct spdk_scsi_task *task)
96 {
97 TAILQ_INSERT_TAIL(&lun->pending_mgmt_tasks, task, scsi_link);
98 }
99
100 static bool
_scsi_lun_handle_unit_attention(struct spdk_scsi_task * task)101 _scsi_lun_handle_unit_attention(struct spdk_scsi_task *task)
102 {
103 uint8_t *cdb = task->cdb;
104
105 assert(task->cdb);
106
107 switch (cdb[0]) {
108 case SPDK_SPC_INQUIRY:
109 case SPDK_SPC_REPORT_LUNS:
110 case SPDK_SPC_REQUEST_SENSE:
111 return false;
112 default:
113 return true;
114 }
115 }
116
117 static void
_scsi_lun_execute_mgmt_task(struct spdk_scsi_lun * lun)118 _scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun)
119 {
120 struct spdk_scsi_task *task;
121 static const char *spdk_scsi_task_names[] = {
122 "abort task",
123 "abort task set",
124 "clear task set",
125 "lun reset",
126 "target reset"
127 };
128 const char *scsi_tn = "unknown task";
129
130 if (!TAILQ_EMPTY(&lun->mgmt_tasks)) {
131 return;
132 }
133
134 task = TAILQ_FIRST(&lun->pending_mgmt_tasks);
135 if (spdk_likely(task == NULL)) {
136 /* Try to execute all pending tasks */
137 scsi_lun_execute_tasks(lun);
138 return;
139 }
140 TAILQ_REMOVE(&lun->pending_mgmt_tasks, task, scsi_link);
141
142 TAILQ_INSERT_TAIL(&lun->mgmt_tasks, task, scsi_link);
143
144 if (lun->removed) {
145 task->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN;
146 scsi_lun_complete_mgmt_task(lun, task);
147 return;
148 }
149
150 if (task->function < SPDK_COUNTOF(spdk_scsi_task_names)) {
151 scsi_tn = spdk_scsi_task_names[task->function];
152 }
153
154 switch (task->function) {
155 case SPDK_SCSI_TASK_FUNC_LUN_RESET:
156 case SPDK_SCSI_TASK_FUNC_TARGET_RESET:
157 SPDK_NOTICELOG("Bdev scsi reset on %s\n", scsi_tn);
158 bdev_scsi_reset(task);
159 return;
160
161 case SPDK_SCSI_TASK_FUNC_ABORT_TASK:
162 case SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET:
163 default:
164 /*
165 * Task management functions other than those above should never
166 * reach this point having been filtered by the frontend. Reject
167 * the task as being unsupported.
168 */
169 SPDK_ERRLOG("%s not supported\n", scsi_tn);
170 task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
171 scsi_lun_complete_mgmt_task(lun, task);
172 break;
173 }
174 }
175
176 void
scsi_lun_execute_mgmt_task(struct spdk_scsi_lun * lun,struct spdk_scsi_task * task)177 scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun,
178 struct spdk_scsi_task *task)
179 {
180 scsi_lun_append_mgmt_task(lun, task);
181 _scsi_lun_execute_mgmt_task(lun);
182 }
183
184 static void
_scsi_lun_execute_task(struct spdk_scsi_lun * lun,struct spdk_scsi_task * task)185 _scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
186 {
187 int rc;
188
189 task->status = SPDK_SCSI_STATUS_GOOD;
190 spdk_trace_record(TRACE_SCSI_TASK_START, lun->dev->id, task->length, (uintptr_t)task);
191 TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link);
192 if (spdk_unlikely(lun->removed)) {
193 spdk_scsi_task_process_abort(task);
194 rc = SPDK_SCSI_TASK_COMPLETE;
195 } else if (spdk_unlikely(lun->resizing) && _scsi_lun_handle_unit_attention(task)) {
196 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
197 SPDK_SCSI_SENSE_UNIT_ATTENTION,
198 SPDK_SCSI_ASC_CAPACITY_DATA_HAS_CHANGED,
199 SPDK_SCSI_ASCQ_CAPACITY_DATA_HAS_CHANGED);
200 lun->resizing = false;
201 rc = SPDK_SCSI_TASK_COMPLETE;
202 } else {
203 /* Check the command is allowed or not when reservation is exist */
204 if (spdk_unlikely(lun->reservation.flags & SCSI_SPC2_RESERVE)) {
205 rc = scsi2_reserve_check(task);
206 } else {
207 rc = scsi_pr_check(task);
208 }
209 if (spdk_unlikely(rc < 0)) {
210 /* Reservation Conflict */
211 rc = SPDK_SCSI_TASK_COMPLETE;
212 } else {
213 rc = bdev_scsi_execute(task);
214 }
215 }
216
217 switch (rc) {
218 case SPDK_SCSI_TASK_PENDING:
219 break;
220
221 case SPDK_SCSI_TASK_COMPLETE:
222 scsi_lun_complete_task(lun, task);
223 break;
224
225 default:
226 abort();
227 }
228 }
229
230 static void
scsi_lun_append_task(struct spdk_scsi_lun * lun,struct spdk_scsi_task * task)231 scsi_lun_append_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
232 {
233 TAILQ_INSERT_TAIL(&lun->pending_tasks, task, scsi_link);
234 }
235
236 static void
scsi_lun_execute_tasks(struct spdk_scsi_lun * lun)237 scsi_lun_execute_tasks(struct spdk_scsi_lun *lun)
238 {
239 struct spdk_scsi_task *task, *task_tmp;
240
241 TAILQ_FOREACH_SAFE(task, &lun->pending_tasks, scsi_link, task_tmp) {
242 TAILQ_REMOVE(&lun->pending_tasks, task, scsi_link);
243 _scsi_lun_execute_task(lun, task);
244 }
245 }
246
247 void
scsi_lun_execute_task(struct spdk_scsi_lun * lun,struct spdk_scsi_task * task)248 scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
249 {
250 if (spdk_unlikely(_scsi_lun_has_pending_mgmt_tasks(lun))) {
251 /* Add the IO task to pending list and wait for completion of
252 * existing mgmt tasks.
253 */
254 scsi_lun_append_task(lun, task);
255 } else if (spdk_unlikely(_scsi_lun_has_pending_tasks(lun))) {
256 /* If there is any pending IO task, append the IO task to the
257 * tail of the pending list, and then execute all pending IO tasks
258 * from the head to submit IO tasks in order.
259 */
260 scsi_lun_append_task(lun, task);
261 scsi_lun_execute_tasks(lun);
262 } else {
263 /* Execute the IO task directly. */
264 _scsi_lun_execute_task(lun, task);
265 }
266 }
267
268 static void
_scsi_lun_remove(void * arg)269 _scsi_lun_remove(void *arg)
270 {
271 struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
272
273 spdk_bdev_close(lun->bdev_desc);
274 spdk_scsi_dev_delete_lun(lun->dev, lun);
275 free(lun);
276 }
277
278 static void
scsi_lun_remove(struct spdk_scsi_lun * lun)279 scsi_lun_remove(struct spdk_scsi_lun *lun)
280 {
281 struct spdk_scsi_pr_registrant *reg, *tmp;
282
283 TAILQ_FOREACH_SAFE(reg, &lun->reg_head, link, tmp) {
284 TAILQ_REMOVE(&lun->reg_head, reg, link);
285 free(reg);
286 }
287
288 spdk_thread_exec_msg(lun->thread, _scsi_lun_remove, lun);
289 }
290
291 static int
scsi_lun_check_io_channel(void * arg)292 scsi_lun_check_io_channel(void *arg)
293 {
294 struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
295
296 if (lun->io_channel) {
297 return SPDK_POLLER_BUSY;
298 }
299 spdk_poller_unregister(&lun->hotremove_poller);
300
301 scsi_lun_remove(lun);
302 return SPDK_POLLER_BUSY;
303 }
304
305 static void
scsi_lun_notify_hot_remove(struct spdk_scsi_lun * lun)306 scsi_lun_notify_hot_remove(struct spdk_scsi_lun *lun)
307 {
308 struct spdk_scsi_lun_desc *desc, *tmp;
309
310 if (lun->hotremove_cb) {
311 lun->hotremove_cb(lun, lun->hotremove_ctx);
312 }
313
314 TAILQ_FOREACH_SAFE(desc, &lun->open_descs, link, tmp) {
315 if (desc->hotremove_cb) {
316 desc->hotremove_cb(lun, desc->hotremove_ctx);
317 } else {
318 spdk_scsi_lun_close(desc);
319 }
320 }
321
322 if (lun->io_channel) {
323 lun->hotremove_poller = SPDK_POLLER_REGISTER(scsi_lun_check_io_channel,
324 lun, 10);
325 } else {
326 scsi_lun_remove(lun);
327 }
328 }
329
330 static int
scsi_lun_check_outstanding_tasks(void * arg)331 scsi_lun_check_outstanding_tasks(void *arg)
332 {
333 struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
334
335 if (scsi_lun_has_outstanding_tasks(lun) ||
336 scsi_lun_has_outstanding_mgmt_tasks(lun)) {
337 return SPDK_POLLER_BUSY;
338 }
339 spdk_poller_unregister(&lun->hotremove_poller);
340
341 scsi_lun_notify_hot_remove(lun);
342 return SPDK_POLLER_BUSY;
343 }
344
345 static void
_scsi_lun_hot_remove(void * arg1)346 _scsi_lun_hot_remove(void *arg1)
347 {
348 struct spdk_scsi_lun *lun = arg1;
349
350 /* If lun->removed is set, no new task can be submitted to the LUN.
351 * Execute previously queued tasks, which will be immediately aborted.
352 */
353 scsi_lun_execute_tasks(lun);
354
355 /* Then we only need to wait for all outstanding tasks to be completed
356 * before notifying the upper layer about the removal.
357 */
358 if (scsi_lun_has_outstanding_tasks(lun) ||
359 scsi_lun_has_outstanding_mgmt_tasks(lun)) {
360 lun->hotremove_poller = SPDK_POLLER_REGISTER(scsi_lun_check_outstanding_tasks,
361 lun, 10);
362 } else {
363 scsi_lun_notify_hot_remove(lun);
364 }
365 }
366
367 static void
scsi_lun_hot_remove(void * remove_ctx)368 scsi_lun_hot_remove(void *remove_ctx)
369 {
370 struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)remove_ctx;
371 struct spdk_thread *thread;
372
373 if (lun->removed) {
374 return;
375 }
376
377 lun->removed = true;
378 if (lun->io_channel == NULL) {
379 _scsi_lun_hot_remove(lun);
380 return;
381 }
382
383 thread = spdk_io_channel_get_thread(lun->io_channel);
384 if (thread != spdk_get_thread()) {
385 spdk_thread_send_msg(thread, _scsi_lun_hot_remove, lun);
386 } else {
387 _scsi_lun_hot_remove(lun);
388 }
389 }
390
391 static void
bdev_event_cb(enum spdk_bdev_event_type type,struct spdk_bdev * bdev,void * event_ctx)392 bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
393 void *event_ctx)
394 {
395 struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)event_ctx;
396 switch (type) {
397 case SPDK_BDEV_EVENT_REMOVE:
398 SPDK_NOTICELOG("bdev name (%s) received event(SPDK_BDEV_EVENT_REMOVE)\n", spdk_bdev_get_name(bdev));
399 scsi_lun_hot_remove(event_ctx);
400 break;
401 case SPDK_BDEV_EVENT_RESIZE:
402 SPDK_NOTICELOG("bdev name (%s) received event(SPDK_BDEV_EVENT_RESIZE)\n", spdk_bdev_get_name(bdev));
403 lun->resizing = true;
404 if (lun->resize_cb) {
405 lun->resize_cb(lun, lun->resize_ctx);
406 }
407 break;
408 default:
409 SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
410 break;
411 }
412 }
413
414 /**
415 * \brief Constructs a new spdk_scsi_lun object based on the provided parameters.
416 *
417 * \param bdev_name Bdev name to open and associate with this LUN
418 *
419 * \return NULL if bdev whose name matches is not found
420 * \return pointer to the new spdk_scsi_lun object otherwise
421 */
scsi_lun_construct(const char * bdev_name,void (* resize_cb)(const struct spdk_scsi_lun *,void *),void * resize_ctx,void (* hotremove_cb)(const struct spdk_scsi_lun *,void *),void * hotremove_ctx)422 struct spdk_scsi_lun *scsi_lun_construct(const char *bdev_name,
423 void (*resize_cb)(const struct spdk_scsi_lun *, void *),
424 void *resize_ctx,
425 void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
426 void *hotremove_ctx)
427 {
428 struct spdk_scsi_lun *lun;
429 int rc;
430
431 if (bdev_name == NULL) {
432 SPDK_ERRLOG("bdev_name must be non-NULL\n");
433 return NULL;
434 }
435
436 lun = calloc(1, sizeof(*lun));
437 if (lun == NULL) {
438 SPDK_ERRLOG("could not allocate lun\n");
439 return NULL;
440 }
441
442 rc = spdk_bdev_open_ext(bdev_name, true, bdev_event_cb, lun, &lun->bdev_desc);
443
444 if (rc != 0) {
445 SPDK_ERRLOG("bdev %s cannot be opened, error=%d\n", bdev_name, rc);
446 free(lun);
447 return NULL;
448 }
449
450 lun->thread = spdk_get_thread();
451
452 TAILQ_INIT(&lun->tasks);
453 TAILQ_INIT(&lun->pending_tasks);
454 TAILQ_INIT(&lun->mgmt_tasks);
455 TAILQ_INIT(&lun->pending_mgmt_tasks);
456
457 /* Bdev is not removed while it is opened. */
458 lun->bdev = spdk_bdev_desc_get_bdev(lun->bdev_desc);
459 lun->io_channel = NULL;
460 lun->hotremove_cb = hotremove_cb;
461 lun->hotremove_ctx = hotremove_ctx;
462
463 lun->resize_cb = resize_cb;
464 lun->resize_ctx = resize_ctx;
465 lun->resizing = false;
466
467 TAILQ_INIT(&lun->open_descs);
468 TAILQ_INIT(&lun->reg_head);
469
470 return lun;
471 }
472
473 void
scsi_lun_destruct(struct spdk_scsi_lun * lun)474 scsi_lun_destruct(struct spdk_scsi_lun *lun)
475 {
476 scsi_lun_hot_remove(lun);
477 }
478
479 int
spdk_scsi_lun_open(struct spdk_scsi_lun * lun,spdk_scsi_lun_remove_cb_t hotremove_cb,void * hotremove_ctx,struct spdk_scsi_lun_desc ** _desc)480 spdk_scsi_lun_open(struct spdk_scsi_lun *lun, spdk_scsi_lun_remove_cb_t hotremove_cb,
481 void *hotremove_ctx, struct spdk_scsi_lun_desc **_desc)
482 {
483 struct spdk_scsi_lun_desc *desc;
484
485 desc = calloc(1, sizeof(*desc));
486 if (desc == NULL) {
487 SPDK_ERRLOG("calloc() failed for LUN descriptor.\n");
488 return -ENOMEM;
489 }
490
491 TAILQ_INSERT_TAIL(&lun->open_descs, desc, link);
492
493 desc->lun = lun;
494 desc->hotremove_cb = hotremove_cb;
495 desc->hotremove_ctx = hotremove_ctx;
496 *_desc = desc;
497
498 return 0;
499 }
500
501 void
spdk_scsi_lun_close(struct spdk_scsi_lun_desc * desc)502 spdk_scsi_lun_close(struct spdk_scsi_lun_desc *desc)
503 {
504 struct spdk_scsi_lun *lun = desc->lun;
505
506 TAILQ_REMOVE(&lun->open_descs, desc, link);
507 free(desc);
508
509 assert(!TAILQ_EMPTY(&lun->open_descs) || lun->io_channel == NULL);
510 }
511
512 int
scsi_lun_allocate_io_channel(struct spdk_scsi_lun * lun)513 scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun)
514 {
515 if (lun->io_channel != NULL) {
516 if (spdk_get_thread() == spdk_io_channel_get_thread(lun->io_channel)) {
517 lun->ref++;
518 return 0;
519 }
520 SPDK_ERRLOG("io_channel already allocated for lun %s\n",
521 spdk_bdev_get_name(lun->bdev));
522 return -1;
523 }
524
525 lun->io_channel = spdk_bdev_get_io_channel(lun->bdev_desc);
526 if (lun->io_channel == NULL) {
527 return -1;
528 }
529 lun->ref = 1;
530 return 0;
531 }
532
533 void
scsi_lun_free_io_channel(struct spdk_scsi_lun * lun)534 scsi_lun_free_io_channel(struct spdk_scsi_lun *lun)
535 {
536 if (lun->io_channel == NULL) {
537 return;
538 }
539
540 if (spdk_get_thread() != spdk_io_channel_get_thread(lun->io_channel)) {
541 SPDK_ERRLOG("io_channel was freed by different thread\n");
542 return;
543 }
544
545 lun->ref--;
546 if (lun->ref == 0) {
547 spdk_put_io_channel(lun->io_channel);
548 lun->io_channel = NULL;
549 }
550 }
551
552 int
spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun_desc * desc)553 spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun_desc *desc)
554 {
555 struct spdk_scsi_lun *lun = desc->lun;
556
557 return scsi_lun_allocate_io_channel(lun);
558 }
559
560 void
spdk_scsi_lun_free_io_channel(struct spdk_scsi_lun_desc * desc)561 spdk_scsi_lun_free_io_channel(struct spdk_scsi_lun_desc *desc)
562 {
563 struct spdk_scsi_lun *lun = desc->lun;
564
565 scsi_lun_free_io_channel(lun);
566 }
567
568 int
spdk_scsi_lun_get_id(const struct spdk_scsi_lun * lun)569 spdk_scsi_lun_get_id(const struct spdk_scsi_lun *lun)
570 {
571 return lun->id;
572 }
573
574 const char *
spdk_scsi_lun_get_bdev_name(const struct spdk_scsi_lun * lun)575 spdk_scsi_lun_get_bdev_name(const struct spdk_scsi_lun *lun)
576 {
577 return spdk_bdev_get_name(lun->bdev);
578 }
579
580 const struct spdk_scsi_dev *
spdk_scsi_lun_get_dev(const struct spdk_scsi_lun * lun)581 spdk_scsi_lun_get_dev(const struct spdk_scsi_lun *lun)
582 {
583 return lun->dev;
584 }
585
586 bool
scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun * lun,const struct spdk_scsi_port * initiator_port)587 scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun,
588 const struct spdk_scsi_port *initiator_port)
589 {
590 struct spdk_scsi_task *task;
591
592 if (initiator_port == NULL) {
593 return _scsi_lun_has_pending_mgmt_tasks(lun) ||
594 scsi_lun_has_outstanding_mgmt_tasks(lun);
595 }
596
597 TAILQ_FOREACH(task, &lun->pending_mgmt_tasks, scsi_link) {
598 if (task->initiator_port == initiator_port) {
599 return true;
600 }
601 }
602
603 TAILQ_FOREACH(task, &lun->mgmt_tasks, scsi_link) {
604 if (task->initiator_port == initiator_port) {
605 return true;
606 }
607 }
608
609 return false;
610 }
611 /* This check includes both pending and submitted (outstanding) tasks. */
612 bool
scsi_lun_has_pending_tasks(const struct spdk_scsi_lun * lun,const struct spdk_scsi_port * initiator_port)613 scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun,
614 const struct spdk_scsi_port *initiator_port)
615 {
616 struct spdk_scsi_task *task;
617
618 if (initiator_port == NULL) {
619 return _scsi_lun_has_pending_tasks(lun) ||
620 scsi_lun_has_outstanding_tasks(lun);
621 }
622
623 TAILQ_FOREACH(task, &lun->pending_tasks, scsi_link) {
624 if (task->initiator_port == initiator_port) {
625 return true;
626 }
627 }
628
629 TAILQ_FOREACH(task, &lun->tasks, scsi_link) {
630 if (task->initiator_port == initiator_port) {
631 return true;
632 }
633 }
634
635 return false;
636 }
637
638 bool
spdk_scsi_lun_is_removing(const struct spdk_scsi_lun * lun)639 spdk_scsi_lun_is_removing(const struct spdk_scsi_lun *lun)
640 {
641 return lun->removed;
642 }
643
644 bool
spdk_scsi_lun_get_dif_ctx(struct spdk_scsi_lun * lun,struct spdk_scsi_task * task,struct spdk_dif_ctx * dif_ctx)645 spdk_scsi_lun_get_dif_ctx(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task,
646 struct spdk_dif_ctx *dif_ctx)
647 {
648 return bdev_scsi_get_dif_ctx(lun->bdev, task, dif_ctx);
649 }
650