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