LCOV - code coverage report
Current view: top level - spdk/lib/scsi - lun.c (source / functions) Hit Total Coverage
Test: Combined Lines: 270 301 89.7 %
Date: 2024-07-14 04:14:37 Functions: 39 39 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 120 154 77.9 %

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

Generated by: LCOV version 1.14