xref: /spdk/lib/scsi/lun.c (revision b30d57cdad6d2bc75cc1e4e2ebbcebcb0d98dcfa)
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, 0);
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 void
129 _scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun)
130 {
131 	struct spdk_scsi_task *task;
132 
133 	if (!TAILQ_EMPTY(&lun->mgmt_tasks)) {
134 		return;
135 	}
136 
137 	task = TAILQ_FIRST(&lun->pending_mgmt_tasks);
138 	if (spdk_likely(task == NULL)) {
139 		/* Try to execute all pending tasks */
140 		scsi_lun_execute_tasks(lun);
141 		return;
142 	}
143 	TAILQ_REMOVE(&lun->pending_mgmt_tasks, task, scsi_link);
144 
145 	TAILQ_INSERT_TAIL(&lun->mgmt_tasks, task, scsi_link);
146 
147 	if (lun->removed) {
148 		task->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN;
149 		scsi_lun_complete_mgmt_task(lun, task);
150 		return;
151 	}
152 
153 	switch (task->function) {
154 	case SPDK_SCSI_TASK_FUNC_ABORT_TASK:
155 		task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
156 		SPDK_ERRLOG("ABORT_TASK failed\n");
157 		break;
158 
159 	case SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET:
160 		task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
161 		SPDK_ERRLOG("ABORT_TASK_SET failed\n");
162 		break;
163 
164 	case SPDK_SCSI_TASK_FUNC_LUN_RESET:
165 		bdev_scsi_reset(task);
166 		return;
167 
168 	default:
169 		SPDK_ERRLOG("Unknown Task Management Function!\n");
170 		/*
171 		 * Task management functions other than those above should never
172 		 * reach this point having been filtered by the frontend. Reject
173 		 * the task as being unsupported.
174 		 */
175 		task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
176 		break;
177 	}
178 
179 	scsi_lun_complete_mgmt_task(lun, task);
180 }
181 
182 void
183 scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun,
184 			   struct spdk_scsi_task *task)
185 {
186 	scsi_lun_append_mgmt_task(lun, task);
187 	_scsi_lun_execute_mgmt_task(lun);
188 }
189 
190 static void
191 _scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
192 {
193 	int rc;
194 
195 	task->status = SPDK_SCSI_STATUS_GOOD;
196 	spdk_trace_record(TRACE_SCSI_TASK_START, lun->dev->id, task->length, (uintptr_t)task, 0);
197 	TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link);
198 	if (!lun->removed) {
199 		/* Check the command is allowed or not when reservation is exist */
200 		if (spdk_unlikely(lun->reservation.flags & SCSI_SPC2_RESERVE)) {
201 			rc = scsi2_reserve_check(task);
202 		} else {
203 			rc = scsi_pr_check(task);
204 		}
205 		if (spdk_unlikely(rc < 0)) {
206 			/* Reservation Conflict */
207 			rc = SPDK_SCSI_TASK_COMPLETE;
208 		} else {
209 			rc = bdev_scsi_execute(task);
210 		}
211 	} else {
212 		spdk_scsi_task_process_abort(task);
213 		rc = SPDK_SCSI_TASK_COMPLETE;
214 	}
215 
216 	switch (rc) {
217 	case SPDK_SCSI_TASK_PENDING:
218 		break;
219 
220 	case SPDK_SCSI_TASK_COMPLETE:
221 		scsi_lun_complete_task(lun, task);
222 		break;
223 
224 	default:
225 		abort();
226 	}
227 }
228 
229 static void
230 scsi_lun_append_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
231 {
232 	TAILQ_INSERT_TAIL(&lun->pending_tasks, task, scsi_link);
233 }
234 
235 static void
236 scsi_lun_execute_tasks(struct spdk_scsi_lun *lun)
237 {
238 	struct spdk_scsi_task *task, *task_tmp;
239 
240 	TAILQ_FOREACH_SAFE(task, &lun->pending_tasks, scsi_link, task_tmp) {
241 		TAILQ_REMOVE(&lun->pending_tasks, task, scsi_link);
242 		_scsi_lun_execute_task(lun, task);
243 	}
244 }
245 
246 void
247 scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
248 {
249 	if (spdk_unlikely(_scsi_lun_has_pending_mgmt_tasks(lun))) {
250 		/* Add the IO task to pending list and wait for completion of
251 		 * existing mgmt tasks.
252 		 */
253 		scsi_lun_append_task(lun, task);
254 	} else if (spdk_unlikely(_scsi_lun_has_pending_tasks(lun))) {
255 		/* If there is any pending IO task, append the IO task to the
256 		 * tail of the pending list, and then execute all pending IO tasks
257 		 * from the head to submit IO tasks in order.
258 		 */
259 		scsi_lun_append_task(lun, task);
260 		scsi_lun_execute_tasks(lun);
261 	} else {
262 		/* Execute the IO task directly. */
263 		_scsi_lun_execute_task(lun, task);
264 	}
265 }
266 
267 static void
268 _scsi_lun_remove(void *arg)
269 {
270 	struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
271 
272 	spdk_bdev_close(lun->bdev_desc);
273 	spdk_scsi_dev_delete_lun(lun->dev, lun);
274 	free(lun);
275 }
276 
277 static void
278 scsi_lun_remove(struct spdk_scsi_lun *lun)
279 {
280 	struct spdk_scsi_pr_registrant *reg, *tmp;
281 	struct spdk_thread *thread;
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 	thread = spdk_get_thread();
289 	if (thread != lun->thread) {
290 		spdk_thread_send_msg(lun->thread, _scsi_lun_remove, lun);
291 	} else {
292 		_scsi_lun_remove(lun);
293 	}
294 }
295 
296 static int
297 scsi_lun_check_io_channel(void *arg)
298 {
299 	struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
300 
301 	if (lun->io_channel) {
302 		return SPDK_POLLER_BUSY;
303 	}
304 	spdk_poller_unregister(&lun->hotremove_poller);
305 
306 	scsi_lun_remove(lun);
307 	return SPDK_POLLER_BUSY;
308 }
309 
310 static void
311 scsi_lun_notify_hot_remove(struct spdk_scsi_lun *lun)
312 {
313 	struct spdk_scsi_lun_desc *desc, *tmp;
314 
315 	if (lun->hotremove_cb) {
316 		lun->hotremove_cb(lun, lun->hotremove_ctx);
317 	}
318 
319 	TAILQ_FOREACH_SAFE(desc, &lun->open_descs, link, tmp) {
320 		if (desc->hotremove_cb) {
321 			desc->hotremove_cb(lun, desc->hotremove_ctx);
322 		} else {
323 			spdk_scsi_lun_close(desc);
324 		}
325 	}
326 
327 	if (lun->io_channel) {
328 		lun->hotremove_poller = SPDK_POLLER_REGISTER(scsi_lun_check_io_channel,
329 					lun, 10);
330 	} else {
331 		scsi_lun_remove(lun);
332 	}
333 }
334 
335 static int
336 scsi_lun_check_outstanding_tasks(void *arg)
337 {
338 	struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
339 
340 	if (scsi_lun_has_outstanding_tasks(lun) ||
341 	    scsi_lun_has_outstanding_mgmt_tasks(lun)) {
342 		return SPDK_POLLER_BUSY;
343 	}
344 	spdk_poller_unregister(&lun->hotremove_poller);
345 
346 	scsi_lun_notify_hot_remove(lun);
347 	return SPDK_POLLER_BUSY;
348 }
349 
350 static void
351 _scsi_lun_hot_remove(void *arg1)
352 {
353 	struct spdk_scsi_lun *lun = arg1;
354 
355 	/* If lun->removed is set, no new task can be submitted to the LUN.
356 	 * Execute previously queued tasks, which will be immediately aborted.
357 	 */
358 	scsi_lun_execute_tasks(lun);
359 
360 	/* Then we only need to wait for all outstanding tasks to be completed
361 	 * before notifying the upper layer about the removal.
362 	 */
363 	if (scsi_lun_has_outstanding_tasks(lun) ||
364 	    scsi_lun_has_outstanding_mgmt_tasks(lun)) {
365 		lun->hotremove_poller = SPDK_POLLER_REGISTER(scsi_lun_check_outstanding_tasks,
366 					lun, 10);
367 	} else {
368 		scsi_lun_notify_hot_remove(lun);
369 	}
370 }
371 
372 static void
373 scsi_lun_hot_remove(void *remove_ctx)
374 {
375 	struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)remove_ctx;
376 	struct spdk_thread *thread;
377 
378 	if (lun->removed) {
379 		return;
380 	}
381 
382 	lun->removed = true;
383 	if (lun->io_channel == NULL) {
384 		_scsi_lun_hot_remove(lun);
385 		return;
386 	}
387 
388 	thread = spdk_io_channel_get_thread(lun->io_channel);
389 	if (thread != spdk_get_thread()) {
390 		spdk_thread_send_msg(thread, _scsi_lun_hot_remove, lun);
391 	} else {
392 		_scsi_lun_hot_remove(lun);
393 	}
394 }
395 
396 static void
397 bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
398 	      void *event_ctx)
399 {
400 	struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)event_ctx;
401 	switch (type) {
402 	case SPDK_BDEV_EVENT_REMOVE:
403 		SPDK_NOTICELOG("bdev name (%s) received event(SPDK_BDEV_EVENT_REMOVE)\n", spdk_bdev_get_name(bdev));
404 		scsi_lun_hot_remove(event_ctx);
405 		break;
406 	case SPDK_BDEV_EVENT_RESIZE:
407 		SPDK_NOTICELOG("bdev name (%s) received event(SPDK_BDEV_EVENT_RESIZE)\n", spdk_bdev_get_name(bdev));
408 		if (lun->resize_cb) {
409 			lun->resize_cb(lun, lun->resize_ctx);
410 		}
411 		break;
412 	default:
413 		SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
414 		break;
415 	}
416 }
417 
418 /**
419  * \brief Constructs a new spdk_scsi_lun object based on the provided parameters.
420  *
421  * \param bdev_name Bdev name to open and associate with this LUN
422  *
423  * \return NULL if bdev whose name matches is not found
424  * \return pointer to the new spdk_scsi_lun object otherwise
425  */
426 struct spdk_scsi_lun *scsi_lun_construct(const char *bdev_name,
427 		void (*resize_cb)(const struct spdk_scsi_lun *, void *),
428 		void *resize_ctx,
429 		void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
430 		void *hotremove_ctx)
431 {
432 	struct spdk_scsi_lun *lun;
433 	int rc;
434 
435 	if (bdev_name == NULL) {
436 		SPDK_ERRLOG("bdev_name must be non-NULL\n");
437 		return NULL;
438 	}
439 
440 	lun = calloc(1, sizeof(*lun));
441 	if (lun == NULL) {
442 		SPDK_ERRLOG("could not allocate lun\n");
443 		return NULL;
444 	}
445 
446 	rc = spdk_bdev_open_ext(bdev_name, true, bdev_event_cb, lun, &lun->bdev_desc);
447 
448 	if (rc != 0) {
449 		SPDK_ERRLOG("bdev %s cannot be opened, error=%d\n", bdev_name, rc);
450 		free(lun);
451 		return NULL;
452 	}
453 
454 	lun->thread = spdk_get_thread();
455 
456 	TAILQ_INIT(&lun->tasks);
457 	TAILQ_INIT(&lun->pending_tasks);
458 	TAILQ_INIT(&lun->mgmt_tasks);
459 	TAILQ_INIT(&lun->pending_mgmt_tasks);
460 
461 	/* Bdev is not removed while it is opened. */
462 	lun->bdev = spdk_bdev_desc_get_bdev(lun->bdev_desc);
463 	lun->io_channel = NULL;
464 	lun->hotremove_cb = hotremove_cb;
465 	lun->hotremove_ctx = hotremove_ctx;
466 
467 	lun->resize_cb = resize_cb;
468 	lun->resize_ctx = resize_ctx;
469 
470 	TAILQ_INIT(&lun->open_descs);
471 	TAILQ_INIT(&lun->reg_head);
472 
473 	return lun;
474 }
475 
476 void
477 scsi_lun_destruct(struct spdk_scsi_lun *lun)
478 {
479 	scsi_lun_hot_remove(lun);
480 }
481 
482 int
483 spdk_scsi_lun_open(struct spdk_scsi_lun *lun, spdk_scsi_lun_remove_cb_t hotremove_cb,
484 		   void *hotremove_ctx, struct spdk_scsi_lun_desc **_desc)
485 {
486 	struct spdk_scsi_lun_desc *desc;
487 
488 	desc = calloc(1, sizeof(*desc));
489 	if (desc == NULL) {
490 		SPDK_ERRLOG("calloc() failed for LUN descriptor.\n");
491 		return -ENOMEM;
492 	}
493 
494 	TAILQ_INSERT_TAIL(&lun->open_descs, desc, link);
495 
496 	desc->lun = lun;
497 	desc->hotremove_cb = hotremove_cb;
498 	desc->hotremove_ctx = hotremove_ctx;
499 	*_desc = desc;
500 
501 	return 0;
502 }
503 
504 void
505 spdk_scsi_lun_close(struct spdk_scsi_lun_desc *desc)
506 {
507 	struct spdk_scsi_lun *lun = desc->lun;
508 
509 	TAILQ_REMOVE(&lun->open_descs, desc, link);
510 	free(desc);
511 
512 	assert(!TAILQ_EMPTY(&lun->open_descs) || lun->io_channel == NULL);
513 }
514 
515 int
516 scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun)
517 {
518 	if (lun->io_channel != NULL) {
519 		if (spdk_get_thread() == spdk_io_channel_get_thread(lun->io_channel)) {
520 			lun->ref++;
521 			return 0;
522 		}
523 		SPDK_ERRLOG("io_channel already allocated for lun %s\n",
524 			    spdk_bdev_get_name(lun->bdev));
525 		return -1;
526 	}
527 
528 	lun->io_channel = spdk_bdev_get_io_channel(lun->bdev_desc);
529 	if (lun->io_channel == NULL) {
530 		return -1;
531 	}
532 	lun->ref = 1;
533 	return 0;
534 }
535 
536 void
537 scsi_lun_free_io_channel(struct spdk_scsi_lun *lun)
538 {
539 	if (lun->io_channel == NULL) {
540 		return;
541 	}
542 
543 	if (spdk_get_thread() != spdk_io_channel_get_thread(lun->io_channel)) {
544 		SPDK_ERRLOG("io_channel was freed by different thread\n");
545 		return;
546 	}
547 
548 	lun->ref--;
549 	if (lun->ref == 0) {
550 		spdk_put_io_channel(lun->io_channel);
551 		lun->io_channel = NULL;
552 	}
553 }
554 
555 int
556 spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun_desc *desc)
557 {
558 	struct spdk_scsi_lun *lun = desc->lun;
559 
560 	return scsi_lun_allocate_io_channel(lun);
561 }
562 
563 void
564 spdk_scsi_lun_free_io_channel(struct spdk_scsi_lun_desc *desc)
565 {
566 	struct spdk_scsi_lun *lun = desc->lun;
567 
568 	scsi_lun_free_io_channel(lun);
569 }
570 
571 int
572 spdk_scsi_lun_get_id(const struct spdk_scsi_lun *lun)
573 {
574 	return lun->id;
575 }
576 
577 const char *
578 spdk_scsi_lun_get_bdev_name(const struct spdk_scsi_lun *lun)
579 {
580 	return spdk_bdev_get_name(lun->bdev);
581 }
582 
583 const struct spdk_scsi_dev *
584 spdk_scsi_lun_get_dev(const struct spdk_scsi_lun *lun)
585 {
586 	return lun->dev;
587 }
588 
589 bool
590 scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun,
591 				const struct spdk_scsi_port *initiator_port)
592 {
593 	struct spdk_scsi_task *task;
594 
595 	if (initiator_port == NULL) {
596 		return _scsi_lun_has_pending_mgmt_tasks(lun) ||
597 		       scsi_lun_has_outstanding_mgmt_tasks(lun);
598 	}
599 
600 	TAILQ_FOREACH(task, &lun->pending_mgmt_tasks, scsi_link) {
601 		if (task->initiator_port == initiator_port) {
602 			return true;
603 		}
604 	}
605 
606 	TAILQ_FOREACH(task, &lun->mgmt_tasks, scsi_link) {
607 		if (task->initiator_port == initiator_port) {
608 			return true;
609 		}
610 	}
611 
612 	return false;
613 }
614 /* This check includes both pending and submitted (outstanding) tasks. */
615 bool
616 scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun,
617 			   const struct spdk_scsi_port *initiator_port)
618 {
619 	struct spdk_scsi_task *task;
620 
621 	if (initiator_port == NULL) {
622 		return _scsi_lun_has_pending_tasks(lun) ||
623 		       scsi_lun_has_outstanding_tasks(lun);
624 	}
625 
626 	TAILQ_FOREACH(task, &lun->pending_tasks, scsi_link) {
627 		if (task->initiator_port == initiator_port) {
628 			return true;
629 		}
630 	}
631 
632 	TAILQ_FOREACH(task, &lun->tasks, scsi_link) {
633 		if (task->initiator_port == initiator_port) {
634 			return true;
635 		}
636 	}
637 
638 	return false;
639 }
640 
641 bool
642 spdk_scsi_lun_is_removing(const struct spdk_scsi_lun *lun)
643 {
644 	return lun->removed;
645 }
646 
647 bool
648 spdk_scsi_lun_get_dif_ctx(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task,
649 			  struct spdk_dif_ctx *dif_ctx)
650 {
651 	return bdev_scsi_get_dif_ctx(lun->bdev, task, dif_ctx);
652 }
653