Branch data Line data Source code
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 : 8612568 : scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
19 : : {
20 [ + - ]: 8612568 : if (lun) {
21 [ + + ]: 8612568 : TAILQ_REMOVE(&lun->tasks, task, scsi_link);
22 [ + + + + ]: 8612568 : spdk_trace_record(TRACE_SCSI_TASK_DONE, lun->dev->id, 0, (uintptr_t)task);
23 : : }
24 : 8612568 : task->cpl_fn(task);
25 : 8612568 : }
26 : :
27 : : static void
28 : 45 : scsi_lun_complete_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
29 : : {
30 [ - + ]: 45 : TAILQ_REMOVE(&lun->mgmt_tasks, task, scsi_link);
31 : :
32 : 45 : task->cpl_fn(task);
33 : :
34 : : /* Try to execute the first pending mgmt task if it exists. */
35 : 45 : _scsi_lun_execute_mgmt_task(lun);
36 : 45 : }
37 : :
38 : : static bool
39 : 8612592 : _scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun)
40 : : {
41 : 8612592 : return !TAILQ_EMPTY(&lun->pending_mgmt_tasks);
42 : : }
43 : :
44 : : static bool
45 : 247 : scsi_lun_has_outstanding_mgmt_tasks(const struct spdk_scsi_lun *lun)
46 : : {
47 : 247 : return !TAILQ_EMPTY(&lun->mgmt_tasks);
48 : : }
49 : :
50 : : static bool
51 : 8612589 : _scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun)
52 : : {
53 : 8612589 : return !TAILQ_EMPTY(&lun->pending_tasks);
54 : : }
55 : :
56 : : static bool
57 : 285 : scsi_lun_has_outstanding_tasks(const struct spdk_scsi_lun *lun)
58 : : {
59 : 285 : return !TAILQ_EMPTY(&lun->tasks);
60 : : }
61 : :
62 : : /* Reset task have to wait until all prior outstanding tasks complete. */
63 : : static int
64 : 6 : scsi_lun_reset_check_outstanding_tasks(void *arg)
65 : : {
66 : 6 : struct spdk_scsi_task *task = (struct spdk_scsi_task *)arg;
67 : 6 : struct spdk_scsi_lun *lun = task->lun;
68 : :
69 [ + + ]: 6 : if (scsi_lun_has_outstanding_tasks(lun)) {
70 : 3 : return SPDK_POLLER_BUSY;
71 : : }
72 : 3 : spdk_poller_unregister(&lun->reset_poller);
73 : :
74 : 3 : scsi_lun_complete_mgmt_task(lun, task);
75 : 3 : return SPDK_POLLER_BUSY;
76 : : }
77 : :
78 : : void
79 : 27 : scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
80 : : {
81 [ + - ]: 27 : if (task->status == SPDK_SCSI_STATUS_GOOD) {
82 [ + + ]: 27 : if (scsi_lun_has_outstanding_tasks(lun)) {
83 : 3 : lun->reset_poller =
84 : 3 : SPDK_POLLER_REGISTER(scsi_lun_reset_check_outstanding_tasks,
85 : : task, 10);
86 : 3 : return;
87 : : }
88 : : }
89 : :
90 : 24 : scsi_lun_complete_mgmt_task(lun, task);
91 : : }
92 : :
93 : : static void
94 : 45 : scsi_lun_append_mgmt_task(struct spdk_scsi_lun *lun,
95 : : struct spdk_scsi_task *task)
96 : : {
97 : 45 : TAILQ_INSERT_TAIL(&lun->pending_mgmt_tasks, task, scsi_link);
98 : 45 : }
99 : :
100 : : static bool
101 : 4 : _scsi_lun_handle_unit_attention(struct spdk_scsi_task *task)
102 : : {
103 : 4 : uint8_t *cdb = task->cdb;
104 : :
105 [ - + ]: 4 : assert(task->cdb);
106 : :
107 [ - + ]: 4 : switch (cdb[0]) {
108 : 0 : case SPDK_SPC_INQUIRY:
109 : : case SPDK_SPC_REPORT_LUNS:
110 : : case SPDK_SPC_REQUEST_SENSE:
111 : 0 : return false;
112 : 4 : default:
113 : 4 : return true;
114 : : }
115 : : }
116 : :
117 : : static void
118 : 78 : _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 : 78 : const char *scsi_tn = "unknown task";
129 : :
130 [ - + ]: 78 : if (!TAILQ_EMPTY(&lun->mgmt_tasks)) {
131 : 0 : return;
132 : : }
133 : :
134 : 78 : task = TAILQ_FIRST(&lun->pending_mgmt_tasks);
135 [ + + ]: 78 : if (spdk_likely(task == NULL)) {
136 : : /* Try to execute all pending tasks */
137 : 33 : scsi_lun_execute_tasks(lun);
138 : 33 : return;
139 : : }
140 [ + + ]: 45 : TAILQ_REMOVE(&lun->pending_mgmt_tasks, task, scsi_link);
141 : :
142 : 45 : TAILQ_INSERT_TAIL(&lun->mgmt_tasks, task, scsi_link);
143 : :
144 [ + + + + ]: 45 : if (lun->removed) {
145 : 9 : task->response = SPDK_SCSI_TASK_MGMT_RESP_INVALID_LUN;
146 : 9 : scsi_lun_complete_mgmt_task(lun, task);
147 : 9 : return;
148 : : }
149 : :
150 [ + + ]: 36 : if (task->function < SPDK_COUNTOF(spdk_scsi_task_names)) {
151 : 33 : scsi_tn = spdk_scsi_task_names[task->function];
152 : : }
153 : :
154 [ + + ]: 36 : switch (task->function) {
155 : 27 : case SPDK_SCSI_TASK_FUNC_LUN_RESET:
156 : : case SPDK_SCSI_TASK_FUNC_TARGET_RESET:
157 : 27 : SPDK_NOTICELOG("Bdev scsi reset on %s\n", scsi_tn);
158 : 27 : bdev_scsi_reset(task);
159 : 27 : return;
160 : :
161 : 9 : 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 : 9 : SPDK_ERRLOG("%s not supported\n", scsi_tn);
170 : 9 : task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
171 : 9 : scsi_lun_complete_mgmt_task(lun, task);
172 : 9 : break;
173 : : }
174 : : }
175 : :
176 : : void
177 : 24 : scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun,
178 : : struct spdk_scsi_task *task)
179 : : {
180 : 24 : scsi_lun_append_mgmt_task(lun, task);
181 : 24 : _scsi_lun_execute_mgmt_task(lun);
182 : 24 : }
183 : :
184 : : static void
185 : 8612568 : _scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
186 : : {
187 : : int rc;
188 : :
189 : 8612568 : task->status = SPDK_SCSI_STATUS_GOOD;
190 [ + + + + ]: 8612568 : spdk_trace_record(TRACE_SCSI_TASK_START, lun->dev->id, task->length, (uintptr_t)task);
191 : 8612568 : TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link);
192 [ - + - + ]: 8612568 : if (spdk_unlikely(lun->removed)) {
193 : 0 : spdk_scsi_task_process_abort(task);
194 : 0 : rc = SPDK_SCSI_TASK_COMPLETE;
195 [ + + + + : 8612568 : } else if (spdk_unlikely(lun->resizing) && _scsi_lun_handle_unit_attention(task)) {
+ - ]
196 : 4 : 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 : 4 : lun->resizing = false;
201 : 4 : rc = SPDK_SCSI_TASK_COMPLETE;
202 : : } else {
203 : : /* Check the command is allowed or not when reservation is exist */
204 [ - + ]: 8612564 : if (spdk_unlikely(lun->reservation.flags & SCSI_SPC2_RESERVE)) {
205 : 0 : rc = scsi2_reserve_check(task);
206 : : } else {
207 : 8612564 : rc = scsi_pr_check(task);
208 : : }
209 [ - + ]: 8612564 : if (spdk_unlikely(rc < 0)) {
210 : : /* Reservation Conflict */
211 : 0 : rc = SPDK_SCSI_TASK_COMPLETE;
212 : : } else {
213 : 8612564 : rc = bdev_scsi_execute(task);
214 : : }
215 : : }
216 : :
217 [ + + - ]: 8612568 : switch (rc) {
218 : 8600439 : case SPDK_SCSI_TASK_PENDING:
219 : 8600439 : break;
220 : :
221 : 12129 : case SPDK_SCSI_TASK_COMPLETE:
222 : 12129 : scsi_lun_complete_task(lun, task);
223 : 12129 : break;
224 : :
225 : 0 : default:
226 : 0 : abort();
227 : : }
228 : 8612568 : }
229 : :
230 : : static void
231 : 3 : scsi_lun_append_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
232 : : {
233 : 3 : TAILQ_INSERT_TAIL(&lun->pending_tasks, task, scsi_link);
234 : 3 : }
235 : :
236 : : static void
237 : 268 : scsi_lun_execute_tasks(struct spdk_scsi_lun *lun)
238 : : {
239 : : struct spdk_scsi_task *task, *task_tmp;
240 : :
241 [ + + ]: 271 : TAILQ_FOREACH_SAFE(task, &lun->pending_tasks, scsi_link, task_tmp) {
242 [ - + ]: 3 : TAILQ_REMOVE(&lun->pending_tasks, task, scsi_link);
243 : 3 : _scsi_lun_execute_task(lun, task);
244 : : }
245 : 268 : }
246 : :
247 : : void
248 : 8612568 : scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
249 : : {
250 [ + + ]: 8612568 : 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 : 3 : scsi_lun_append_task(lun, task);
255 [ - + ]: 8612565 : } 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 : 0 : scsi_lun_append_task(lun, task);
261 : 0 : scsi_lun_execute_tasks(lun);
262 : : } else {
263 : : /* Execute the IO task directly. */
264 : 8612565 : _scsi_lun_execute_task(lun, task);
265 : : }
266 : 8612568 : }
267 : :
268 : : static void
269 : 241 : _scsi_lun_remove(void *arg)
270 : : {
271 : 241 : struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
272 : :
273 : 241 : spdk_bdev_close(lun->bdev_desc);
274 : 241 : spdk_scsi_dev_delete_lun(lun->dev, lun);
275 : 241 : free(lun);
276 : 241 : }
277 : :
278 : : static void
279 : 241 : scsi_lun_remove(struct spdk_scsi_lun *lun)
280 : : {
281 : : struct spdk_scsi_pr_registrant *reg, *tmp;
282 : :
283 [ - + ]: 241 : TAILQ_FOREACH_SAFE(reg, &lun->reg_head, link, tmp) {
284 [ # # ]: 0 : TAILQ_REMOVE(&lun->reg_head, reg, link);
285 : 0 : free(reg);
286 : : }
287 : :
288 : 241 : spdk_thread_exec_msg(lun->thread, _scsi_lun_remove, lun);
289 : 241 : }
290 : :
291 : : static int
292 : 890 : scsi_lun_check_io_channel(void *arg)
293 : : {
294 : 890 : struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
295 : :
296 [ + + ]: 890 : if (lun->io_channel) {
297 : 886 : return SPDK_POLLER_BUSY;
298 : : }
299 : 4 : spdk_poller_unregister(&lun->hotremove_poller);
300 : :
301 : 4 : scsi_lun_remove(lun);
302 : 4 : return SPDK_POLLER_BUSY;
303 : : }
304 : :
305 : : static void
306 : 235 : scsi_lun_notify_hot_remove(struct spdk_scsi_lun *lun)
307 : : {
308 : : struct spdk_scsi_lun_desc *desc, *tmp;
309 : :
310 [ + + ]: 235 : if (lun->hotremove_cb) {
311 : 45 : lun->hotremove_cb(lun, lun->hotremove_ctx);
312 : : }
313 : :
314 [ + + ]: 239 : TAILQ_FOREACH_SAFE(desc, &lun->open_descs, link, tmp) {
315 [ + - ]: 4 : if (desc->hotremove_cb) {
316 : 4 : desc->hotremove_cb(lun, desc->hotremove_ctx);
317 : : } else {
318 : 0 : spdk_scsi_lun_close(desc);
319 : : }
320 : : }
321 : :
322 [ + + ]: 235 : if (lun->io_channel) {
323 : 4 : lun->hotremove_poller = SPDK_POLLER_REGISTER(scsi_lun_check_io_channel,
324 : : lun, 10);
325 : : } else {
326 : 231 : scsi_lun_remove(lun);
327 : : }
328 : 235 : }
329 : :
330 : : static int
331 : 2 : scsi_lun_check_outstanding_tasks(void *arg)
332 : : {
333 : 2 : struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
334 : :
335 [ + - - + ]: 4 : if (scsi_lun_has_outstanding_tasks(lun) ||
336 : 2 : scsi_lun_has_outstanding_mgmt_tasks(lun)) {
337 : 0 : return SPDK_POLLER_BUSY;
338 : : }
339 : 2 : spdk_poller_unregister(&lun->hotremove_poller);
340 : :
341 : 2 : scsi_lun_notify_hot_remove(lun);
342 : 2 : return SPDK_POLLER_BUSY;
343 : : }
344 : :
345 : : static void
346 : 235 : _scsi_lun_hot_remove(void *arg1)
347 : : {
348 : 235 : 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 : 235 : 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 [ + + - + ]: 468 : if (scsi_lun_has_outstanding_tasks(lun) ||
359 : 233 : scsi_lun_has_outstanding_mgmt_tasks(lun)) {
360 : 2 : lun->hotremove_poller = SPDK_POLLER_REGISTER(scsi_lun_check_outstanding_tasks,
361 : : lun, 10);
362 : : } else {
363 : 233 : scsi_lun_notify_hot_remove(lun);
364 : : }
365 : 235 : }
366 : :
367 : : static void
368 : 235 : scsi_lun_hot_remove(void *remove_ctx)
369 : : {
370 : 235 : struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)remove_ctx;
371 : : struct spdk_thread *thread;
372 : :
373 [ - + - + ]: 235 : if (lun->removed) {
374 : 0 : return;
375 : : }
376 : :
377 : 235 : lun->removed = true;
378 [ + + ]: 235 : if (lun->io_channel == NULL) {
379 : 231 : _scsi_lun_hot_remove(lun);
380 : 231 : return;
381 : : }
382 : :
383 : 4 : thread = spdk_io_channel_get_thread(lun->io_channel);
384 [ + - ]: 4 : if (thread != spdk_get_thread()) {
385 : 4 : spdk_thread_send_msg(thread, _scsi_lun_hot_remove, lun);
386 : : } else {
387 : 0 : _scsi_lun_hot_remove(lun);
388 : : }
389 : : }
390 : :
391 : : static void
392 : 73 : bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
393 : : void *event_ctx)
394 : : {
395 : 73 : struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)event_ctx;
396 [ + + - ]: 73 : switch (type) {
397 : 72 : case SPDK_BDEV_EVENT_REMOVE:
398 : 72 : SPDK_NOTICELOG("bdev name (%s) received event(SPDK_BDEV_EVENT_REMOVE)\n", spdk_bdev_get_name(bdev));
399 : 72 : scsi_lun_hot_remove(event_ctx);
400 : 72 : break;
401 : 1 : case SPDK_BDEV_EVENT_RESIZE:
402 : 1 : SPDK_NOTICELOG("bdev name (%s) received event(SPDK_BDEV_EVENT_RESIZE)\n", spdk_bdev_get_name(bdev));
403 : 1 : lun->resizing = true;
404 [ - + ]: 1 : if (lun->resize_cb) {
405 : 0 : lun->resize_cb(lun, lun->resize_ctx);
406 : : }
407 : 1 : break;
408 : 0 : default:
409 : 0 : SPDK_NOTICELOG("Unsupported bdev event: type %d\n", type);
410 : 0 : break;
411 : : }
412 : 73 : }
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 : : */
422 : 245 : 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 [ + + ]: 245 : if (bdev_name == NULL) {
432 : 3 : SPDK_ERRLOG("bdev_name must be non-NULL\n");
433 : 3 : return NULL;
434 : : }
435 : :
436 : 242 : lun = calloc(1, sizeof(*lun));
437 [ - + ]: 242 : if (lun == NULL) {
438 : 0 : SPDK_ERRLOG("could not allocate lun\n");
439 : 0 : return NULL;
440 : : }
441 : :
442 : 242 : rc = spdk_bdev_open_ext(bdev_name, true, bdev_event_cb, lun, &lun->bdev_desc);
443 : :
444 [ + + ]: 242 : if (rc != 0) {
445 : 1 : SPDK_ERRLOG("bdev %s cannot be opened, error=%d\n", bdev_name, rc);
446 : 1 : free(lun);
447 : 1 : return NULL;
448 : : }
449 : :
450 : 241 : lun->thread = spdk_get_thread();
451 : :
452 : 241 : TAILQ_INIT(&lun->tasks);
453 : 241 : TAILQ_INIT(&lun->pending_tasks);
454 : 241 : TAILQ_INIT(&lun->mgmt_tasks);
455 : 241 : TAILQ_INIT(&lun->pending_mgmt_tasks);
456 : :
457 : : /* Bdev is not removed while it is opened. */
458 : 241 : lun->bdev = spdk_bdev_desc_get_bdev(lun->bdev_desc);
459 : 241 : lun->io_channel = NULL;
460 : 241 : lun->hotremove_cb = hotremove_cb;
461 : 241 : lun->hotremove_ctx = hotremove_ctx;
462 : :
463 : 241 : lun->resize_cb = resize_cb;
464 : 241 : lun->resize_ctx = resize_ctx;
465 : 241 : lun->resizing = false;
466 : :
467 : 241 : TAILQ_INIT(&lun->open_descs);
468 : 241 : TAILQ_INIT(&lun->reg_head);
469 : :
470 : 241 : return lun;
471 : : }
472 : :
473 : : void
474 : 163 : scsi_lun_destruct(struct spdk_scsi_lun *lun)
475 : : {
476 : 163 : scsi_lun_hot_remove(lun);
477 : 163 : }
478 : :
479 : : int
480 : 466 : 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 : 466 : desc = calloc(1, sizeof(*desc));
486 [ - + ]: 466 : if (desc == NULL) {
487 : 0 : SPDK_ERRLOG("calloc() failed for LUN descriptor.\n");
488 : 0 : return -ENOMEM;
489 : : }
490 : :
491 : 466 : TAILQ_INSERT_TAIL(&lun->open_descs, desc, link);
492 : :
493 : 466 : desc->lun = lun;
494 : 466 : desc->hotremove_cb = hotremove_cb;
495 : 466 : desc->hotremove_ctx = hotremove_ctx;
496 : 466 : *_desc = desc;
497 : :
498 : 466 : return 0;
499 : : }
500 : :
501 : : void
502 : 466 : spdk_scsi_lun_close(struct spdk_scsi_lun_desc *desc)
503 : : {
504 : 466 : struct spdk_scsi_lun *lun = desc->lun;
505 : :
506 [ + + ]: 466 : TAILQ_REMOVE(&lun->open_descs, desc, link);
507 : 466 : free(desc);
508 : :
509 [ + + - + ]: 466 : assert(!TAILQ_EMPTY(&lun->open_descs) || lun->io_channel == NULL);
510 : 466 : }
511 : :
512 : : int
513 : 505 : scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun)
514 : : {
515 [ + + ]: 505 : if (lun->io_channel != NULL) {
516 [ + - ]: 22 : if (spdk_get_thread() == spdk_io_channel_get_thread(lun->io_channel)) {
517 : 22 : lun->ref++;
518 : 22 : return 0;
519 : : }
520 : 0 : SPDK_ERRLOG("io_channel already allocated for lun %s\n",
521 : : spdk_bdev_get_name(lun->bdev));
522 : 0 : return -1;
523 : : }
524 : :
525 : 483 : lun->io_channel = spdk_bdev_get_io_channel(lun->bdev_desc);
526 [ - + ]: 483 : if (lun->io_channel == NULL) {
527 : 0 : return -1;
528 : : }
529 : 483 : lun->ref = 1;
530 : 483 : return 0;
531 : : }
532 : :
533 : : void
534 : 505 : scsi_lun_free_io_channel(struct spdk_scsi_lun *lun)
535 : : {
536 [ - + ]: 505 : if (lun->io_channel == NULL) {
537 : 0 : return;
538 : : }
539 : :
540 [ - + ]: 505 : if (spdk_get_thread() != spdk_io_channel_get_thread(lun->io_channel)) {
541 : 0 : SPDK_ERRLOG("io_channel was freed by different thread\n");
542 : 0 : return;
543 : : }
544 : :
545 : 505 : lun->ref--;
546 [ + + ]: 505 : if (lun->ref == 0) {
547 : 483 : spdk_put_io_channel(lun->io_channel);
548 : 483 : lun->io_channel = NULL;
549 : : }
550 : : }
551 : :
552 : : int
553 : 466 : spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun_desc *desc)
554 : : {
555 : 466 : struct spdk_scsi_lun *lun = desc->lun;
556 : :
557 : 466 : return scsi_lun_allocate_io_channel(lun);
558 : : }
559 : :
560 : : void
561 : 466 : spdk_scsi_lun_free_io_channel(struct spdk_scsi_lun_desc *desc)
562 : : {
563 : 466 : struct spdk_scsi_lun *lun = desc->lun;
564 : :
565 : 466 : scsi_lun_free_io_channel(lun);
566 : 466 : }
567 : :
568 : : int
569 : 756 : spdk_scsi_lun_get_id(const struct spdk_scsi_lun *lun)
570 : : {
571 : 756 : return lun->id;
572 : : }
573 : :
574 : : const char *
575 : 788 : spdk_scsi_lun_get_bdev_name(const struct spdk_scsi_lun *lun)
576 : : {
577 : 788 : return spdk_bdev_get_name(lun->bdev);
578 : : }
579 : :
580 : : const struct spdk_scsi_dev *
581 : 42 : spdk_scsi_lun_get_dev(const struct spdk_scsi_lun *lun)
582 : : {
583 : 42 : return lun->dev;
584 : : }
585 : :
586 : : bool
587 : 538 : 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 [ + + ]: 538 : if (initiator_port == NULL) {
593 [ + + + + ]: 21 : return _scsi_lun_has_pending_mgmt_tasks(lun) ||
594 : 9 : scsi_lun_has_outstanding_mgmt_tasks(lun);
595 : : }
596 : :
597 [ + + ]: 535 : TAILQ_FOREACH(task, &lun->pending_mgmt_tasks, scsi_link) {
598 [ + + ]: 15 : if (task->initiator_port == initiator_port) {
599 : 6 : return true;
600 : : }
601 : : }
602 : :
603 [ + + ]: 529 : TAILQ_FOREACH(task, &lun->mgmt_tasks, scsi_link) {
604 [ + + ]: 15 : if (task->initiator_port == initiator_port) {
605 : 6 : return true;
606 : : }
607 : : }
608 : :
609 : 514 : return false;
610 : : }
611 : : /* This check includes both pending and submitted (outstanding) tasks. */
612 : : bool
613 : 538 : 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 [ + + ]: 538 : if (initiator_port == NULL) {
619 [ + + + + ]: 21 : return _scsi_lun_has_pending_tasks(lun) ||
620 : 9 : scsi_lun_has_outstanding_tasks(lun);
621 : : }
622 : :
623 [ + + ]: 535 : TAILQ_FOREACH(task, &lun->pending_tasks, scsi_link) {
624 [ + + ]: 15 : if (task->initiator_port == initiator_port) {
625 : 6 : return true;
626 : : }
627 : : }
628 : :
629 [ + + ]: 529 : TAILQ_FOREACH(task, &lun->tasks, scsi_link) {
630 [ + + ]: 15 : if (task->initiator_port == initiator_port) {
631 : 6 : return true;
632 : : }
633 : : }
634 : :
635 : 514 : return false;
636 : : }
637 : :
638 : : bool
639 : 17817189 : spdk_scsi_lun_is_removing(const struct spdk_scsi_lun *lun)
640 : : {
641 [ - + ]: 17817189 : return lun->removed;
642 : : }
643 : :
644 : : bool
645 : 5206818 : 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 : 5206818 : return bdev_scsi_get_dif_ctx(lun->bdev, task, dif_ctx);
649 : : }
|