LCOV - code coverage report
Current view: top level - lib/scsi - lun.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 184 301 61.1 %
Date: 2024-12-09 07:16:24 Functions: 25 39 64.1 %

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

Generated by: LCOV version 1.15