LCOV - code coverage report
Current view: top level - spdk/lib/scsi - task.c (source / functions) Hit Total Coverage
Test: Combined Lines: 141 152 92.8 %
Date: 2024-11-19 05:00:21 Functions: 11 12 91.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 244 474 51.5 %

           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/util.h"
      11                 :            : 
      12                 :            : static void
      13                 :   30676650 : scsi_task_free_data(struct spdk_scsi_task *task)
      14                 :            : {
      15   [ +  +  +  -  :   30676650 :         if (task->alloc_len != 0) {
                   +  + ]
      16   [ +  -  +  -  :      20218 :                 spdk_dma_free(task->iov.iov_base);
                   +  - ]
      17   [ +  -  +  - ]:      20218 :                 task->alloc_len = 0;
      18                 :          1 :         }
      19                 :            : 
      20   [ +  -  +  -  :   30676650 :         task->iov.iov_base = NULL;
                   +  - ]
      21   [ +  -  +  -  :   30676650 :         task->iov.iov_len = 0;
                   +  - ]
      22                 :   30676650 : }
      23                 :            : 
      24                 :            : void
      25                 :   55701737 : spdk_scsi_task_put(struct spdk_scsi_task *task)
      26                 :            : {
      27         [ +  + ]:   55701737 :         if (!task) {
      28                 :          0 :                 return;
      29                 :            :         }
      30                 :            : 
      31   [ +  +  +  -  :   55701737 :         assert(task->ref > 0);
             +  -  #  # ]
      32         [ +  - ]:   55701737 :         task->ref--;
      33                 :            : 
      34   [ +  +  +  -  :   55701737 :         if (task->ref == 0) {
                   -  + ]
      35   [ +  -  +  - ]:   30676650 :                 struct spdk_bdev_io *bdev_io = task->bdev_io;
      36                 :            : 
      37         [ +  + ]:   30676650 :                 if (bdev_io) {
      38                 :   15479624 :                         spdk_bdev_free_io(bdev_io);
      39                 :          0 :                 }
      40                 :            : 
      41                 :   30676650 :                 scsi_task_free_data(task);
      42                 :            : 
      43   [ +  -  +  -  :   30676650 :                 task->free_fn(task);
             -  +  +  - ]
      44                 :          2 :         }
      45                 :          2 : }
      46                 :            : 
      47                 :            : void
      48                 :   30677364 : spdk_scsi_task_construct(struct spdk_scsi_task *task,
      49                 :            :                          spdk_scsi_task_cpl cpl_fn,
      50                 :            :                          spdk_scsi_task_free free_fn)
      51                 :            : {
      52   [ +  +  #  # ]:   30677364 :         assert(task != NULL);
      53   [ +  +  #  # ]:   30677364 :         assert(cpl_fn != NULL);
      54   [ +  +  #  # ]:   30677364 :         assert(free_fn != NULL);
      55                 :            : 
      56   [ +  -  +  - ]:   30677364 :         task->cpl_fn = cpl_fn;
      57   [ +  -  +  - ]:   30677364 :         task->free_fn = free_fn;
      58                 :            : 
      59         [ +  - ]:   30677364 :         task->ref++;
      60                 :            : 
      61                 :            :         /*
      62                 :            :          * Pre-fill the iov_buffers to point to the embedded iov
      63                 :            :          */
      64   [ +  +  +  -  :   30677364 :         assert(task->iov.iov_base == NULL);
          +  -  +  -  #  
                      # ]
      65   [ +  -  +  -  :   30677364 :         task->iovs = &task->iov;
                   +  - ]
      66   [ +  -  +  - ]:   30677364 :         task->iovcnt = 1;
      67                 :   30677364 : }
      68                 :            : 
      69                 :            : static void *
      70                 :      20236 : scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
      71                 :            : {
      72                 :          4 :         uint32_t zmalloc_len;
      73                 :            : 
      74   [ +  +  +  -  :      20236 :         assert(task->alloc_len == 0);
             +  -  #  # ]
      75                 :            : 
      76                 :            :         /* Some ULPs (such as iSCSI) need to round len up to nearest
      77                 :            :          * 4 bytes. We can help those ULPs by allocating memory here
      78                 :            :          * up to next 4 byte boundary, so they don't have to worry
      79                 :            :          * about handling out-of-bounds errors.
      80                 :            :          */
      81                 :      20236 :         zmalloc_len = 4 * spdk_divide_round_up(alloc_len, 4);
      82   [ +  -  +  -  :      20236 :         task->iov.iov_base = spdk_dma_zmalloc(zmalloc_len, 0, NULL);
                   +  - ]
      83   [ +  -  +  -  :      20236 :         task->iov.iov_len = alloc_len;
                   +  - ]
      84   [ +  -  +  - ]:      20236 :         task->alloc_len = alloc_len;
      85                 :            : 
      86   [ +  -  +  -  :      20236 :         return task->iov.iov_base;
                   +  - ]
      87                 :          4 : }
      88                 :            : 
      89                 :            : int
      90                 :      24134 : spdk_scsi_task_scatter_data(struct spdk_scsi_task *task, const void *src, size_t buf_len)
      91                 :            : {
      92                 :      24134 :         size_t len = 0;
      93                 :      24134 :         size_t buf_left = buf_len;
      94                 :        261 :         int i;
      95   [ +  -  +  - ]:      24134 :         struct iovec *iovs = task->iovs;
      96                 :        261 :         const uint8_t *pos;
      97                 :            : 
      98         [ +  + ]:      24134 :         if (buf_len == 0) {
      99                 :         14 :                 return 0;
     100                 :            :         }
     101                 :            : 
     102   [ +  -  +  +  :      24120 :         if (task->iovcnt == 1 && iovs[0].iov_base == NULL) {
          +  -  +  -  +  
             -  +  -  +  
                      + ]
     103                 :      20236 :                 scsi_task_alloc_data(task, buf_len);
     104   [ +  -  +  - ]:      20236 :                 iovs[0] = task->iov;
     105                 :          4 :         }
     106                 :            : 
     107   [ +  +  +  -  :      48240 :         for (i = 0; i < task->iovcnt; i++) {
             +  +  +  - ]
     108   [ +  +  +  -  :      24120 :                 assert(iovs[i].iov_base != NULL);
          +  -  +  -  #  
                      # ]
     109   [ +  -  +  -  :      24120 :                 len += iovs[i].iov_len;
                   +  - ]
     110                 :        259 :         }
     111                 :            : 
     112         [ -  + ]:      24120 :         if (len < buf_len) {
     113                 :          0 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
     114                 :            :                                           SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
     115                 :            :                                           SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
     116                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
     117                 :          0 :                 return -1;
     118                 :            :         }
     119                 :            : 
     120                 :      24120 :         pos = src;
     121                 :            : 
     122   [ +  +  +  -  :      48240 :         for (i = 0; i < task->iovcnt; i++) {
             +  +  +  - ]
     123   [ +  -  +  -  :      24120 :                 len = spdk_min(iovs[i].iov_len, buf_left);
          +  -  -  +  #  
             #  #  #  #  
                      # ]
     124                 :      24120 :                 buf_left -= len;
     125   [ +  +  +  +  :      24120 :                 memcpy(iovs[i].iov_base, pos, len);
          +  -  +  -  +  
                      - ]
     126         [ +  - ]:      24120 :                 pos += len;
     127                 :        259 :         }
     128                 :            : 
     129                 :      24120 :         return buf_len;
     130                 :        261 : }
     131                 :            : 
     132                 :            : void *
     133                 :          6 : spdk_scsi_task_gather_data(struct spdk_scsi_task *task, int *len)
     134                 :            : {
     135                 :          1 :         int i;
     136   [ +  -  +  - ]:          6 :         struct iovec *iovs = task->iovs;
     137                 :          6 :         size_t buf_len = 0;
     138                 :          1 :         uint8_t *buf, *pos;
     139                 :            : 
     140   [ +  +  +  -  :         12 :         for (i = 0; i < task->iovcnt; i++) {
             +  +  +  - ]
     141                 :            :                 /* It is OK for iov_base to be NULL if iov_len is 0. */
     142   [ +  +  +  -  :          6 :                 assert(iovs[i].iov_base != NULL || iovs[i].iov_len == 0);
          +  -  -  +  #  
          #  #  #  #  #  
             #  #  #  # ]
     143   [ +  -  +  -  :          6 :                 buf_len += iovs[i].iov_len;
                   +  - ]
     144                 :          1 :         }
     145                 :            : 
     146         [ -  + ]:          6 :         if (buf_len == 0) {
     147         [ #  # ]:          0 :                 *len = 0;
     148                 :          0 :                 return NULL;
     149                 :            :         }
     150                 :            : 
     151                 :          6 :         buf = calloc(1, buf_len);
     152         [ +  + ]:          6 :         if (buf == NULL) {
     153         [ #  # ]:          0 :                 *len = -1;
     154                 :          0 :                 return NULL;
     155                 :            :         }
     156                 :            : 
     157                 :          6 :         pos = buf;
     158   [ +  +  +  -  :         12 :         for (i = 0; i < task->iovcnt; i++) {
             +  +  +  - ]
     159   [ +  +  +  +  :          6 :                 memcpy(pos, iovs[i].iov_base, iovs[i].iov_len);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     160   [ +  -  +  -  :          6 :                 pos += iovs[i].iov_len;
             +  -  +  - ]
     161                 :          1 :         }
     162                 :            : 
     163         [ +  - ]:          6 :         *len = buf_len;
     164                 :          6 :         return buf;
     165                 :          1 : }
     166                 :            : 
     167                 :            : void
     168                 :   22491225 : spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
     169                 :            : {
     170   [ +  +  +  -  :   22491225 :         assert(task->iovcnt == 1);
             +  -  #  # ]
     171   [ +  +  +  -  :   22491225 :         assert(task->alloc_len == 0);
             +  -  #  # ]
     172                 :            : 
     173   [ +  -  +  -  :   22491225 :         task->iovs[0].iov_base = data;
          +  -  +  -  +  
                      - ]
     174   [ +  -  +  -  :   22491225 :         task->iovs[0].iov_len = len;
          +  -  +  -  +  
                      - ]
     175                 :   22491225 : }
     176                 :            : 
     177                 :            : void
     178                 :     174034 : spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc, int ascq)
     179                 :            : {
     180                 :          9 :         uint8_t *cp;
     181                 :          9 :         int resp_code;
     182                 :            : 
     183                 :     174034 :         resp_code = 0x70; /* Current + Fixed format */
     184                 :            : 
     185                 :            :         /* Sense Data */
     186         [ +  - ]:     174034 :         cp = task->sense_data;
     187                 :            : 
     188                 :            :         /* VALID(7) RESPONSE CODE(6-0) */
     189   [ +  -  +  - ]:     174034 :         cp[0] = 0x80 | resp_code;
     190                 :            :         /* Obsolete */
     191   [ +  -  +  - ]:     174034 :         cp[1] = 0;
     192                 :            :         /* FILEMARK(7) EOM(6) ILI(5) SENSE KEY(3-0) */
     193   [ +  -  +  - ]:     174034 :         cp[2] = sk & 0xf;
     194                 :            :         /* INFORMATION */
     195   [ +  +  +  - ]:     174034 :         memset(&cp[3], 0, 4);
     196                 :            : 
     197                 :            :         /* ADDITIONAL SENSE LENGTH */
     198   [ +  -  +  - ]:     174034 :         cp[7] = 10;
     199                 :            : 
     200                 :            :         /* COMMAND-SPECIFIC INFORMATION */
     201   [ +  +  +  - ]:     174034 :         memset(&cp[8], 0, 4);
     202                 :            :         /* ADDITIONAL SENSE CODE */
     203   [ +  -  +  - ]:     174034 :         cp[12] = asc;
     204                 :            :         /* ADDITIONAL SENSE CODE QUALIFIER */
     205   [ +  -  +  - ]:     174034 :         cp[13] = ascq;
     206                 :            :         /* FIELD REPLACEABLE UNIT CODE */
     207   [ +  -  +  - ]:     174034 :         cp[14] = 0;
     208                 :            : 
     209                 :            :         /* SKSV(7) SENSE KEY SPECIFIC(6-0,7-0,7-0) */
     210   [ +  -  +  - ]:     174034 :         cp[15] = 0;
     211   [ +  -  +  - ]:     174034 :         cp[16] = 0;
     212   [ +  -  +  - ]:     174034 :         cp[17] = 0;
     213                 :            : 
     214                 :            :         /* SenseLength */
     215   [ +  -  +  - ]:     174034 :         task->sense_data_len = 18;
     216                 :     174034 : }
     217                 :            : 
     218                 :            : void
     219                 :   29008481 : spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
     220                 :            :                           int asc, int ascq)
     221                 :            : {
     222         [ +  + ]:   29008481 :         if (sc == SPDK_SCSI_STATUS_CHECK_CONDITION) {
     223                 :     174034 :                 spdk_scsi_task_build_sense_data(task, sk, asc, ascq);
     224                 :          9 :         }
     225   [ +  -  +  - ]:   29008481 :         task->status = sc;
     226                 :   29008481 : }
     227                 :            : 
     228                 :            : void
     229                 :         36 : spdk_scsi_task_copy_status(struct spdk_scsi_task *dst,
     230                 :            :                            struct spdk_scsi_task *src)
     231                 :            : {
     232   [ -  +  -  +  :         36 :         memcpy(dst->sense_data, src->sense_data, src->sense_data_len);
          #  #  #  #  #  
                #  #  # ]
     233   [ #  #  #  #  :         36 :         dst->sense_data_len = src->sense_data_len;
             #  #  #  # ]
     234   [ #  #  #  #  :         36 :         dst->status = src->status;
             #  #  #  # ]
     235                 :         36 : }
     236                 :            : 
     237                 :            : void
     238                 :     167680 : spdk_scsi_task_process_null_lun(struct spdk_scsi_task *task)
     239                 :            : {
     240                 :         15 :         uint8_t buffer[36];
     241                 :          3 :         uint32_t allocation_len;
     242                 :          3 :         uint32_t data_len;
     243                 :            : 
     244   [ +  -  +  -  :     167680 :         task->length = task->transfer_len;
             +  -  +  - ]
     245   [ +  +  +  -  :     167680 :         if (task->cdb[0] == SPDK_SPC_INQUIRY) {
          +  -  +  -  +  
                      + ]
     246                 :            :                 /*
     247                 :            :                  * SPC-4 states that INQUIRY commands to an unsupported LUN
     248                 :            :                  *  must be served with PERIPHERAL QUALIFIER = 0x3 and
     249                 :            :                  *  PERIPHERAL DEVICE TYPE = 0x1F.
     250                 :            :                  */
     251                 :        659 :                 data_len = sizeof(buffer);
     252                 :            : 
     253         [ +  + ]:        659 :                 memset(buffer, 0, data_len);
     254                 :            :                 /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
     255   [ -  +  +  -  :        659 :                 buffer[0] = 0x03 << 5 | 0x1f;
             +  -  +  - ]
     256                 :            :                 /* ADDITIONAL LENGTH */
     257   [ +  -  +  -  :        659 :                 buffer[4] = data_len - 5;
                   +  - ]
     258                 :            : 
     259   [ +  -  +  -  :        659 :                 allocation_len = from_be16(&task->cdb[3]);
                   +  - ]
     260   [ +  +  -  + ]:        659 :                 if (spdk_scsi_task_scatter_data(task, buffer, spdk_min(allocation_len, data_len)) >= 0) {
     261   [ -  +  -  + ]:        659 :                         task->data_transferred = data_len;
     262   [ -  +  -  + ]:        659 :                         task->status = SPDK_SCSI_STATUS_GOOD;
     263                 :          2 :                 }
     264                 :          2 :         } else {
     265                 :            :                 /* LOGICAL UNIT NOT SUPPORTED */
     266                 :     167021 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
     267                 :            :                                           SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
     268                 :            :                                           SPDK_SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
     269                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
     270   [ +  -  +  - ]:     167021 :                 task->data_transferred = 0;
     271                 :            :         }
     272                 :     167680 : }
     273                 :            : 
     274                 :            : void
     275                 :          0 : spdk_scsi_task_process_abort(struct spdk_scsi_task *task)
     276                 :            : {
     277                 :          0 :         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
     278                 :            :                                   SPDK_SCSI_SENSE_ABORTED_COMMAND,
     279                 :            :                                   SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
     280                 :            :                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
     281                 :          0 : }

Generated by: LCOV version 1.15