LCOV - code coverage report
Current view: top level - spdk/lib/scsi - task.c (source / functions) Hit Total Coverage
Test: Combined Lines: 113 128 88.3 %
Date: 2024-07-15 18:44:23 Functions: 10 12 83.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 45 74 60.8 %

           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                 :    9926026 : scsi_task_free_data(struct spdk_scsi_task *task)
      14                 :            : {
      15         [ +  + ]:    9926026 :         if (task->alloc_len != 0) {
      16                 :       9558 :                 spdk_dma_free(task->iov.iov_base);
      17                 :       9558 :                 task->alloc_len = 0;
      18                 :            :         }
      19                 :            : 
      20                 :    9926026 :         task->iov.iov_base = NULL;
      21                 :    9926026 :         task->iov.iov_len = 0;
      22                 :    9926026 : }
      23                 :            : 
      24                 :            : void
      25                 :   16671887 : spdk_scsi_task_put(struct spdk_scsi_task *task)
      26                 :            : {
      27         [ -  + ]:   16671887 :         if (!task) {
      28                 :          0 :                 return;
      29                 :            :         }
      30                 :            : 
      31         [ -  + ]:   16671887 :         assert(task->ref > 0);
      32                 :   16671887 :         task->ref--;
      33                 :            : 
      34         [ +  + ]:   16671887 :         if (task->ref == 0) {
      35                 :    9926026 :                 struct spdk_bdev_io *bdev_io = task->bdev_io;
      36                 :            : 
      37         [ +  + ]:    9926026 :                 if (bdev_io) {
      38                 :    5394333 :                         spdk_bdev_free_io(bdev_io);
      39                 :            :                 }
      40                 :            : 
      41                 :    9926026 :                 scsi_task_free_data(task);
      42                 :            : 
      43                 :    9926026 :                 task->free_fn(task);
      44                 :            :         }
      45                 :            : }
      46                 :            : 
      47                 :            : void
      48                 :    9926677 : 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         [ -  + ]:    9926677 :         assert(task != NULL);
      53         [ -  + ]:    9926677 :         assert(cpl_fn != NULL);
      54         [ -  + ]:    9926677 :         assert(free_fn != NULL);
      55                 :            : 
      56                 :    9926677 :         task->cpl_fn = cpl_fn;
      57                 :    9926677 :         task->free_fn = free_fn;
      58                 :            : 
      59                 :    9926677 :         task->ref++;
      60                 :            : 
      61                 :            :         /*
      62                 :            :          * Pre-fill the iov_buffers to point to the embedded iov
      63                 :            :          */
      64         [ -  + ]:    9926677 :         assert(task->iov.iov_base == NULL);
      65                 :    9926677 :         task->iovs = &task->iov;
      66                 :    9926677 :         task->iovcnt = 1;
      67                 :    9926677 : }
      68                 :            : 
      69                 :            : static void *
      70                 :       9567 : scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len)
      71                 :            : {
      72                 :            :         uint32_t zmalloc_len;
      73                 :            : 
      74         [ -  + ]:       9567 :         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                 :       9567 :         zmalloc_len = 4 * spdk_divide_round_up(alloc_len, 4);
      82                 :       9567 :         task->iov.iov_base = spdk_dma_zmalloc(zmalloc_len, 0, NULL);
      83                 :       9567 :         task->iov.iov_len = alloc_len;
      84                 :       9567 :         task->alloc_len = alloc_len;
      85                 :            : 
      86                 :       9567 :         return task->iov.iov_base;
      87                 :            : }
      88                 :            : 
      89                 :            : int
      90                 :      11469 : spdk_scsi_task_scatter_data(struct spdk_scsi_task *task, const void *src, size_t buf_len)
      91                 :            : {
      92                 :      11469 :         size_t len = 0;
      93                 :      11469 :         size_t buf_left = buf_len;
      94                 :            :         int i;
      95                 :      11469 :         struct iovec *iovs = task->iovs;
      96                 :            :         const uint8_t *pos;
      97                 :            : 
      98         [ +  + ]:      11469 :         if (buf_len == 0) {
      99                 :          8 :                 return 0;
     100                 :            :         }
     101                 :            : 
     102   [ +  -  +  + ]:      11461 :         if (task->iovcnt == 1 && iovs[0].iov_base == NULL) {
     103                 :       9567 :                 scsi_task_alloc_data(task, buf_len);
     104                 :       9567 :                 iovs[0] = task->iov;
     105                 :            :         }
     106                 :            : 
     107         [ +  + ]:      22922 :         for (i = 0; i < task->iovcnt; i++) {
     108         [ -  + ]:      11461 :                 assert(iovs[i].iov_base != NULL);
     109                 :      11461 :                 len += iovs[i].iov_len;
     110                 :            :         }
     111                 :            : 
     112         [ -  + ]:      11461 :         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                 :      11461 :         pos = src;
     121                 :            : 
     122         [ +  + ]:      22922 :         for (i = 0; i < task->iovcnt; i++) {
     123                 :      11461 :                 len = spdk_min(iovs[i].iov_len, buf_left);
     124                 :      11461 :                 buf_left -= len;
     125   [ -  +  -  + ]:      11461 :                 memcpy(iovs[i].iov_base, pos, len);
     126                 :      11461 :                 pos += len;
     127                 :            :         }
     128                 :            : 
     129                 :      11461 :         return buf_len;
     130                 :            : }
     131                 :            : 
     132                 :            : void *
     133                 :          3 : spdk_scsi_task_gather_data(struct spdk_scsi_task *task, int *len)
     134                 :            : {
     135                 :            :         int i;
     136                 :          3 :         struct iovec *iovs = task->iovs;
     137                 :          3 :         size_t buf_len = 0;
     138                 :            :         uint8_t *buf, *pos;
     139                 :            : 
     140         [ +  + ]:          6 :         for (i = 0; i < task->iovcnt; i++) {
     141                 :            :                 /* It is OK for iov_base to be NULL if iov_len is 0. */
     142   [ -  +  -  - ]:          3 :                 assert(iovs[i].iov_base != NULL || iovs[i].iov_len == 0);
     143                 :          3 :                 buf_len += iovs[i].iov_len;
     144                 :            :         }
     145                 :            : 
     146         [ -  + ]:          3 :         if (buf_len == 0) {
     147                 :          0 :                 *len = 0;
     148                 :          0 :                 return NULL;
     149                 :            :         }
     150                 :            : 
     151                 :          3 :         buf = calloc(1, buf_len);
     152         [ -  + ]:          3 :         if (buf == NULL) {
     153                 :          0 :                 *len = -1;
     154                 :          0 :                 return NULL;
     155                 :            :         }
     156                 :            : 
     157                 :          3 :         pos = buf;
     158         [ +  + ]:          6 :         for (i = 0; i < task->iovcnt; i++) {
     159   [ -  +  -  + ]:          3 :                 memcpy(pos, iovs[i].iov_base, iovs[i].iov_len);
     160                 :          3 :                 pos += iovs[i].iov_len;
     161                 :            :         }
     162                 :            : 
     163                 :          3 :         *len = buf_len;
     164                 :          3 :         return buf;
     165                 :            : }
     166                 :            : 
     167                 :            : void
     168                 :    5738400 : spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
     169                 :            : {
     170         [ -  + ]:    5738400 :         assert(task->iovcnt == 1);
     171         [ -  + ]:    5738400 :         assert(task->alloc_len == 0);
     172                 :            : 
     173                 :    5738400 :         task->iovs[0].iov_base = data;
     174                 :    5738400 :         task->iovs[0].iov_len = len;
     175                 :    5738400 : }
     176                 :            : 
     177                 :            : void
     178                 :     125069 : spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc, int ascq)
     179                 :            : {
     180                 :            :         uint8_t *cp;
     181                 :            :         int resp_code;
     182                 :            : 
     183                 :     125069 :         resp_code = 0x70; /* Current + Fixed format */
     184                 :            : 
     185                 :            :         /* Sense Data */
     186                 :     125069 :         cp = task->sense_data;
     187                 :            : 
     188                 :            :         /* VALID(7) RESPONSE CODE(6-0) */
     189                 :     125069 :         cp[0] = 0x80 | resp_code;
     190                 :            :         /* Obsolete */
     191                 :     125069 :         cp[1] = 0;
     192                 :            :         /* FILEMARK(7) EOM(6) ILI(5) SENSE KEY(3-0) */
     193                 :     125069 :         cp[2] = sk & 0xf;
     194                 :            :         /* INFORMATION */
     195         [ -  + ]:     125069 :         memset(&cp[3], 0, 4);
     196                 :            : 
     197                 :            :         /* ADDITIONAL SENSE LENGTH */
     198                 :     125069 :         cp[7] = 10;
     199                 :            : 
     200                 :            :         /* COMMAND-SPECIFIC INFORMATION */
     201         [ -  + ]:     125069 :         memset(&cp[8], 0, 4);
     202                 :            :         /* ADDITIONAL SENSE CODE */
     203                 :     125069 :         cp[12] = asc;
     204                 :            :         /* ADDITIONAL SENSE CODE QUALIFIER */
     205                 :     125069 :         cp[13] = ascq;
     206                 :            :         /* FIELD REPLACEABLE UNIT CODE */
     207                 :     125069 :         cp[14] = 0;
     208                 :            : 
     209                 :            :         /* SKSV(7) SENSE KEY SPECIFIC(6-0,7-0,7-0) */
     210                 :     125069 :         cp[15] = 0;
     211                 :     125069 :         cp[16] = 0;
     212                 :     125069 :         cp[17] = 0;
     213                 :            : 
     214                 :            :         /* SenseLength */
     215                 :     125069 :         task->sense_data_len = 18;
     216                 :     125069 : }
     217                 :            : 
     218                 :            : void
     219                 :    8948816 : spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
     220                 :            :                           int asc, int ascq)
     221                 :            : {
     222         [ +  + ]:    8948816 :         if (sc == SPDK_SCSI_STATUS_CHECK_CONDITION) {
     223                 :     125069 :                 spdk_scsi_task_build_sense_data(task, sk, asc, ascq);
     224                 :            :         }
     225                 :    8948816 :         task->status = sc;
     226                 :    8948816 : }
     227                 :            : 
     228                 :            : void
     229                 :          0 : spdk_scsi_task_copy_status(struct spdk_scsi_task *dst,
     230                 :            :                            struct spdk_scsi_task *src)
     231                 :            : {
     232   [ #  #  #  # ]:          0 :         memcpy(dst->sense_data, src->sense_data, src->sense_data_len);
     233                 :          0 :         dst->sense_data_len = src->sense_data_len;
     234                 :          0 :         dst->status = src->status;
     235                 :          0 : }
     236                 :            : 
     237                 :            : void
     238                 :     124551 : spdk_scsi_task_process_null_lun(struct spdk_scsi_task *task)
     239                 :            : {
     240                 :          9 :         uint8_t buffer[36];
     241                 :            :         uint32_t allocation_len;
     242                 :            :         uint32_t data_len;
     243                 :            : 
     244                 :     124551 :         task->length = task->transfer_len;
     245         [ +  + ]:     124551 :         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                 :        505 :                 data_len = sizeof(buffer);
     252                 :            : 
     253         [ -  + ]:        505 :                 memset(buffer, 0, data_len);
     254                 :            :                 /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
     255                 :        505 :                 buffer[0] = 0x03 << 5 | 0x1f;
     256                 :            :                 /* ADDITIONAL LENGTH */
     257                 :        505 :                 buffer[4] = data_len - 5;
     258                 :            : 
     259                 :        505 :                 allocation_len = from_be16(&task->cdb[3]);
     260         [ +  - ]:        505 :                 if (spdk_scsi_task_scatter_data(task, buffer, spdk_min(allocation_len, data_len)) >= 0) {
     261                 :        505 :                         task->data_transferred = data_len;
     262                 :        505 :                         task->status = SPDK_SCSI_STATUS_GOOD;
     263                 :            :                 }
     264                 :            :         } else {
     265                 :            :                 /* LOGICAL UNIT NOT SUPPORTED */
     266                 :     124046 :                 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                 :     124046 :                 task->data_transferred = 0;
     271                 :            :         }
     272                 :     124551 : }
     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.14