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