LCOV - code coverage report
Current view: top level - spdk/lib/scsi - scsi_bdev.c (source / functions) Hit Total Coverage
Test: Combined Lines: 828 1119 74.0 %
Date: 2024-07-11 22:08:03 Functions: 29 30 96.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 308 591 52.1 %

           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                 :            : 
       9                 :            : #include "spdk/env.h"
      10                 :            : #include "spdk/bdev.h"
      11                 :            : #include "spdk/endian.h"
      12                 :            : #include "spdk/likely.h"
      13                 :            : #include "spdk/string.h"
      14                 :            : #include "spdk/util.h"
      15                 :            : 
      16                 :            : #define SPDK_WORK_BLOCK_SIZE            (4ULL * 1024ULL * 1024ULL)
      17                 :            : #define SPDK_WORK_ATS_BLOCK_SIZE        (1ULL * 1024ULL * 1024ULL)
      18                 :            : #define MAX_SERIAL_STRING               32
      19                 :            : 
      20                 :            : #define DEFAULT_DISK_VENDOR             "INTEL"
      21                 :            : #define DEFAULT_DISK_REVISION           "0001"
      22                 :            : #define DEFAULT_DISK_ROTATION_RATE      1       /* Non-rotating medium */
      23                 :            : #define DEFAULT_DISK_FORM_FACTOR        0x02    /* 3.5 inch */
      24                 :            : #define DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT        256
      25                 :            : 
      26                 :            : #define INQUIRY_OFFSET(field)           offsetof(struct spdk_scsi_cdb_inquiry_data, field) + \
      27                 :            :                                         SPDK_SIZEOF_MEMBER(struct spdk_scsi_cdb_inquiry_data, field)
      28                 :            : 
      29                 :            : static void bdev_scsi_process_block_resubmit(void *arg);
      30                 :            : 
      31                 :            : static void
      32                 :       1886 : bdev_scsi_set_naa_ieee_extended(const char *name, uint8_t *buf)
      33                 :            : {
      34                 :            :         int i;
      35                 :       1886 :         uint64_t local_value = 0, id_a, seed = 131;
      36                 :            : 
      37         [ +  + ]:      53969 :         for (i = 0; name[i] != '\0'; i++) {
      38                 :      52083 :                 local_value = (local_value * seed) + name[i];
      39                 :            :         }
      40                 :            : 
      41                 :            :         /*
      42                 :            :          * see spc3r23 7.6.3.6.2,
      43                 :            :          *  NAA IEEE Extended identifier format
      44                 :            :          */
      45                 :       1886 :         id_a = local_value & 0x0000000fff000000ull;
      46                 :       1886 :         id_a = id_a << 24;
      47                 :            : 
      48                 :       1886 :         local_value &= 0x0000000000ffffffull;
      49                 :            :         /* NAA 02, and 00 03 47 for IEEE Intel */
      50                 :       1886 :         local_value |= 0x2000000347000000ull;
      51                 :       1886 :         local_value |= id_a;
      52                 :            : 
      53                 :       1886 :         to_be64((void *)buf, local_value);
      54                 :       1886 : }
      55                 :            : 
      56                 :            : static int
      57                 :        181 : bdev_scsi_report_luns(struct spdk_scsi_lun *lun,
      58                 :            :                       int sel, uint8_t *data, int alloc_len)
      59                 :            : {
      60                 :            :         struct spdk_scsi_dev *dev;
      61                 :            :         struct spdk_scsi_lun *tmp_lun;
      62                 :            :         uint64_t fmt_lun;
      63                 :        181 :         int hlen, len = 0;
      64                 :            : 
      65         [ -  + ]:        181 :         if (alloc_len < 8) {
      66                 :          0 :                 return -1;
      67                 :            :         }
      68                 :            : 
      69         [ -  + ]:        181 :         if (sel == 0x00) {
      70                 :            :                 /* logical unit with addressing method */
      71         [ #  # ]:          0 :         } else if (sel == 0x01) {
      72                 :            :                 /* well known logical unit */
      73         [ #  # ]:          0 :         } else if (sel == 0x02) {
      74                 :            :                 /* logical unit */
      75                 :            :         } else {
      76                 :          0 :                 return -1;
      77                 :            :         }
      78                 :            : 
      79                 :            :         /* LUN LIST LENGTH */
      80         [ -  + ]:        181 :         memset(data, 0, 4);
      81                 :            : 
      82                 :            :         /* Reserved */
      83         [ -  + ]:        181 :         memset(&data[4], 0, 4);
      84                 :        181 :         hlen = 8;
      85                 :            : 
      86                 :        181 :         dev = lun->dev;
      87                 :            : 
      88         [ +  + ]:        544 :         for (tmp_lun = spdk_scsi_dev_get_first_lun(dev); tmp_lun != NULL;
      89                 :        363 :              tmp_lun = spdk_scsi_dev_get_next_lun(tmp_lun)) {
      90         [ -  + ]:        363 :                 if (alloc_len - (hlen + len) < 8) {
      91                 :          0 :                         return -1;
      92                 :            :                 }
      93                 :            : 
      94                 :        363 :                 fmt_lun = spdk_scsi_lun_id_int_to_fmt(tmp_lun->id);
      95                 :            : 
      96                 :            :                 /* LUN */
      97                 :        363 :                 to_be64(&data[hlen + len], fmt_lun);
      98                 :        363 :                 len += 8;
      99                 :            :         }
     100                 :            : 
     101                 :            :         /* LUN LIST LENGTH */
     102                 :        181 :         to_be32(data, len);
     103                 :            : 
     104                 :        181 :         return hlen + len;
     105                 :            : }
     106                 :            : 
     107                 :            : static int
     108                 :       1904 : bdev_scsi_pad_scsi_name(char *dst, const char *name)
     109                 :            : {
     110                 :            :         size_t len;
     111                 :            : 
     112         [ -  + ]:       1904 :         len = strlen(name);
     113   [ -  +  -  + ]:       1904 :         memcpy(dst, name, len);
     114                 :            :         do {
     115                 :       3872 :                 dst[len++] = '\0';
     116         [ +  + ]:       3872 :         } while (len & 3);
     117                 :            : 
     118                 :       1904 :         return len;
     119                 :            : }
     120                 :            : 
     121                 :            : static int
     122                 :      13754 : bdev_scsi_inquiry(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
     123                 :            :                   uint8_t *cdb, uint8_t *data, uint16_t alloc_len)
     124                 :            : {
     125                 :            :         struct spdk_scsi_lun    *lun;
     126                 :            :         struct spdk_scsi_dev    *dev;
     127                 :            :         struct spdk_scsi_port   *port;
     128                 :            :         uint32_t blocks, optimal_blocks;
     129                 :      13754 :         int hlen = 0, plen, plen2;
     130                 :      13754 :         uint16_t len = 0;
     131                 :            :         int pc;
     132                 :            :         int pd;
     133                 :            :         int evpd;
     134                 :            :         int i;
     135                 :      13754 :         struct spdk_scsi_cdb_inquiry *inq = (struct spdk_scsi_cdb_inquiry *)cdb;
     136                 :            : 
     137                 :            :         /* standard inquiry command at lease with 36 Bytes */
     138         [ -  + ]:      13754 :         if (alloc_len < 0x24) {
     139                 :          0 :                 goto inq_error;
     140                 :            :         }
     141                 :            : 
     142                 :      13754 :         lun = task->lun;
     143                 :      13754 :         dev = lun->dev;
     144                 :      13754 :         port = task->target_port;
     145                 :            : 
     146                 :      13754 :         pd = SPDK_SPC_PERIPHERAL_DEVICE_TYPE_DISK;
     147                 :      13754 :         pc = inq->page_code;
     148                 :      13754 :         evpd = inq->evpd & 0x1;
     149                 :            : 
     150   [ +  +  +  + ]:      13754 :         if (!evpd && pc) {
     151                 :          6 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
     152                 :            :                                           SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
     153                 :            :                                           SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
     154                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
     155                 :          6 :                 return -1;
     156                 :            :         }
     157                 :            : 
     158         [ +  + ]:      13748 :         if (evpd) {
     159                 :      10127 :                 struct spdk_scsi_vpd_page *vpage = (struct spdk_scsi_vpd_page *)data;
     160                 :            : 
     161                 :            :                 /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
     162                 :      10127 :                 vpage->peripheral_device_type = pd;
     163                 :      10127 :                 vpage->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
     164                 :            :                 /* PAGE CODE */
     165                 :      10127 :                 vpage->page_code = pc;
     166                 :            : 
     167                 :            :                 /* Vital product data */
     168   [ +  +  +  -  :      10127 :                 switch (pc) {
          -  -  -  +  +  
                   +  + ]
     169                 :       2601 :                 case SPDK_SPC_VPD_SUPPORTED_VPD_PAGES:
     170                 :       2601 :                         hlen = 4;
     171                 :            : 
     172                 :       2601 :                         vpage->params[0] = SPDK_SPC_VPD_SUPPORTED_VPD_PAGES;
     173                 :       2601 :                         vpage->params[1] = SPDK_SPC_VPD_UNIT_SERIAL_NUMBER;
     174                 :       2601 :                         vpage->params[2] = SPDK_SPC_VPD_DEVICE_IDENTIFICATION;
     175                 :       2601 :                         vpage->params[3] = SPDK_SPC_VPD_MANAGEMENT_NETWORK_ADDRESSES;
     176                 :       2601 :                         vpage->params[4] = SPDK_SPC_VPD_EXTENDED_INQUIRY_DATA;
     177                 :       2601 :                         vpage->params[5] = SPDK_SPC_VPD_MODE_PAGE_POLICY;
     178                 :       2601 :                         vpage->params[6] = SPDK_SPC_VPD_SCSI_PORTS;
     179                 :       2601 :                         vpage->params[7] = SPDK_SPC_VPD_BLOCK_LIMITS;
     180                 :       2601 :                         vpage->params[8] = SPDK_SPC_VPD_BLOCK_DEV_CHARS;
     181                 :       2601 :                         len = 9;
     182         [ +  + ]:       2601 :                         if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
     183                 :       2587 :                                 vpage->params[9] = SPDK_SPC_VPD_BLOCK_THIN_PROVISION;
     184                 :       2587 :                                 len++;
     185                 :            :                         }
     186                 :            : 
     187                 :            :                         /* PAGE LENGTH */
     188                 :       2601 :                         to_be16(vpage->alloc_len, len);
     189                 :       2601 :                         break;
     190                 :            : 
     191                 :       1886 :                 case SPDK_SPC_VPD_UNIT_SERIAL_NUMBER: {
     192                 :       1886 :                         const char *name = spdk_bdev_get_name(bdev);
     193                 :            : 
     194                 :       1886 :                         hlen = 4;
     195                 :            : 
     196                 :            :                         /* PRODUCT SERIAL NUMBER */
     197         [ -  + ]:       1886 :                         len = strlen(name) + 1;
     198         [ +  + ]:       1886 :                         if (len > MAX_SERIAL_STRING) {
     199                 :       1339 :                                 len = MAX_SERIAL_STRING;
     200                 :            :                         }
     201                 :            : 
     202   [ -  +  -  + ]:       1886 :                         memcpy(vpage->params, name, len - 1);
     203                 :       1886 :                         vpage->params[len - 1] = 0;
     204                 :            : 
     205                 :            :                         /* PAGE LENGTH */
     206                 :       1886 :                         to_be16(vpage->alloc_len, len);
     207                 :       1886 :                         break;
     208                 :            :                 }
     209                 :            : 
     210                 :       1886 :                 case SPDK_SPC_VPD_DEVICE_IDENTIFICATION: {
     211                 :       1886 :                         const char *name = spdk_bdev_get_name(bdev);
     212                 :       1886 :                         const char *product_name = spdk_bdev_get_product_name(bdev);
     213                 :       1886 :                         uint8_t protocol_id = dev->protocol_id;
     214                 :       1886 :                         uint8_t *buf = vpage->params;
     215                 :            :                         struct spdk_scsi_desig_desc *desig;
     216                 :            : 
     217                 :       1886 :                         hlen = 4;
     218                 :            : 
     219                 :            :                         /* Check total length by calculated how much space all entries take */
     220                 :       1886 :                         len = sizeof(struct spdk_scsi_desig_desc) + 8;
     221                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
     222                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_DEV_MAX_NAME + 1;
     223                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_PORT_MAX_NAME_LENGTH;
     224                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + 4;
     225                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + 4;
     226                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + 4;
     227         [ -  + ]:       1886 :                         if (sizeof(struct spdk_scsi_vpd_page) + len > alloc_len) {
     228                 :          0 :                                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
     229                 :            :                                                           SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
     230                 :            :                                                           SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
     231                 :            :                                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
     232                 :          0 :                                 return -1;
     233                 :            :                         }
     234                 :            : 
     235                 :            :                         /* Now fill out the designator array */
     236                 :            : 
     237                 :            :                         /* NAA designator */
     238                 :       1886 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     239                 :       1886 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
     240                 :       1886 :                         desig->protocol_id = protocol_id;
     241                 :       1886 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_NAA;
     242                 :       1886 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
     243                 :       1886 :                         desig->reserved0 = 0;
     244                 :       1886 :                         desig->piv = 1;
     245                 :       1886 :                         desig->reserved1 = 0;
     246                 :       1886 :                         desig->len = 8;
     247                 :       1886 :                         bdev_scsi_set_naa_ieee_extended(name, desig->desig);
     248                 :       1886 :                         len = sizeof(struct spdk_scsi_desig_desc) + 8;
     249                 :            : 
     250                 :       1886 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     251                 :            : 
     252                 :            :                         /* T10 Vendor ID designator */
     253                 :       1886 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     254                 :       1886 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_ASCII;
     255                 :       1886 :                         desig->protocol_id = protocol_id;
     256                 :       1886 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_T10_VENDOR_ID;
     257                 :       1886 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
     258                 :       1886 :                         desig->reserved0 = 0;
     259                 :       1886 :                         desig->piv = 1;
     260                 :       1886 :                         desig->reserved1 = 0;
     261                 :       1886 :                         desig->len = 8 + 16 + MAX_SERIAL_STRING;
     262                 :       1886 :                         spdk_strcpy_pad(desig->desig, DEFAULT_DISK_VENDOR, 8, ' ');
     263                 :       1886 :                         spdk_strcpy_pad(&desig->desig[8], product_name, 16, ' ');
     264                 :       1886 :                         spdk_strcpy_pad(&desig->desig[24], name, MAX_SERIAL_STRING, ' ');
     265                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
     266                 :            : 
     267                 :       1886 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     268                 :            : 
     269                 :            :                         /* SCSI Device Name designator */
     270                 :       1886 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     271                 :       1886 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
     272                 :       1886 :                         desig->protocol_id = protocol_id;
     273                 :       1886 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
     274                 :       1886 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_DEVICE;
     275                 :       1886 :                         desig->reserved0 = 0;
     276                 :       1886 :                         desig->piv = 1;
     277                 :       1886 :                         desig->reserved1 = 0;
     278                 :       1886 :                         desig->len = bdev_scsi_pad_scsi_name(desig->desig, dev->name);
     279                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     280                 :            : 
     281                 :       1886 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     282                 :            : 
     283                 :            :                         /* SCSI Port Name designator */
     284                 :       1886 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     285                 :       1886 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
     286                 :       1886 :                         desig->protocol_id = protocol_id;
     287                 :       1886 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
     288                 :       1886 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
     289                 :       1886 :                         desig->reserved0 = 0;
     290                 :       1886 :                         desig->piv = 1;
     291                 :       1886 :                         desig->reserved1 = 0;
     292                 :       1886 :                         desig->len = snprintf(desig->desig, SPDK_SCSI_PORT_MAX_NAME_LENGTH, "%s", port->name);
     293                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     294                 :            : 
     295                 :       1886 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     296                 :            : 
     297                 :            :                         /* Relative Target Port designator */
     298                 :       1886 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     299                 :       1886 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
     300                 :       1886 :                         desig->protocol_id = protocol_id;
     301                 :       1886 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_RELATIVE_TARGET_PORT;
     302                 :       1886 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
     303                 :       1886 :                         desig->reserved0 = 0;
     304                 :       1886 :                         desig->piv = 1;
     305                 :       1886 :                         desig->reserved1 = 0;
     306                 :       1886 :                         desig->len = 4;
     307         [ -  + ]:       1886 :                         memset(desig->desig, 0, 2); /* Reserved */
     308                 :       1886 :                         to_be16(&desig->desig[2], port->index);
     309                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     310                 :            : 
     311                 :       1886 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     312                 :            : 
     313                 :            :                         /* Target port group designator */
     314                 :       1886 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     315                 :       1886 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
     316                 :       1886 :                         desig->protocol_id = protocol_id;
     317                 :       1886 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_TARGET_PORT_GROUP;
     318                 :       1886 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
     319                 :       1886 :                         desig->reserved0 = 0;
     320                 :       1886 :                         desig->piv = 1;
     321                 :       1886 :                         desig->reserved1 = 0;
     322                 :       1886 :                         desig->len = 4;
     323         [ -  + ]:       1886 :                         memset(desig->desig, 0, 4);
     324                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     325                 :            : 
     326                 :       1886 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     327                 :            : 
     328                 :            :                         /* Logical unit group designator */
     329                 :       1886 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     330                 :       1886 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
     331                 :       1886 :                         desig->protocol_id = protocol_id;
     332                 :       1886 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_LOGICAL_UNIT_GROUP;
     333                 :       1886 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
     334                 :       1886 :                         desig->reserved0 = 0;
     335                 :       1886 :                         desig->piv = 1;
     336                 :       1886 :                         desig->reserved1 = 0;
     337                 :       1886 :                         desig->len = 4;
     338         [ -  + ]:       1886 :                         memset(desig->desig, 0, 2); /* Reserved */
     339                 :       1886 :                         to_be16(&desig->desig[2], dev->id);
     340                 :       1886 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     341                 :            : 
     342                 :       1886 :                         to_be16(vpage->alloc_len, len);
     343                 :            : 
     344                 :       1886 :                         break;
     345                 :            :                 }
     346                 :            : 
     347                 :          0 :                 case SPDK_SPC_VPD_EXTENDED_INQUIRY_DATA: {
     348                 :          0 :                         struct spdk_scsi_vpd_ext_inquiry *vext = (struct spdk_scsi_vpd_ext_inquiry *)vpage;
     349                 :            : 
     350                 :          0 :                         hlen = 4;
     351         [ #  # ]:          0 :                         memset((uint8_t *)vext + hlen, 0, sizeof(*vext) - hlen);
     352                 :            : 
     353                 :            :                         /* RTO(3) GRD_CHK(2) APP_CHK(1) REF_CHK(0) */
     354                 :            : 
     355                 :            :                         /* GROUP_SUP(4) PRIOR_SUP(3) HEADSUP(2) ORDSUP(1) SIMPSUP(0) */
     356                 :          0 :                         vext->sup = SPDK_SCSI_VEXT_HEADSUP | SPDK_SCSI_VEXT_SIMPSUP;
     357                 :            : 
     358                 :            :                         /* NV_SUP(1) V_SUP(0) */
     359                 :            : 
     360                 :            :                         /* Reserved[7-63] */
     361                 :            : 
     362                 :          0 :                         len = 64 - hlen;
     363                 :            : 
     364                 :            :                         /* PAGE LENGTH */
     365                 :          0 :                         to_be16(vpage->alloc_len, len);
     366                 :          0 :                         break;
     367                 :            :                 }
     368                 :            : 
     369                 :          0 :                 case SPDK_SPC_VPD_MANAGEMENT_NETWORK_ADDRESSES:
     370                 :            :                         /* PAGE LENGTH */
     371                 :          0 :                         hlen = 4;
     372                 :            : 
     373                 :          0 :                         to_be16(vpage->alloc_len, len);
     374                 :          0 :                         break;
     375                 :            : 
     376                 :          0 :                 case SPDK_SPC_VPD_MODE_PAGE_POLICY: {
     377                 :          0 :                         struct spdk_scsi_mpage_policy_desc *pdesc =
     378                 :            :                                 (struct spdk_scsi_mpage_policy_desc *)vpage->params;
     379                 :            : 
     380                 :          0 :                         hlen = 4;
     381                 :            : 
     382                 :            :                         /* Mode page policy descriptor 1 */
     383                 :            : 
     384                 :            :                         /* POLICY PAGE CODE(5-0) */
     385                 :            :                         /* all page code */
     386                 :          0 :                         pdesc->page_code = 0x3f;
     387                 :            : 
     388                 :            :                         /* POLICY SUBPAGE CODE */
     389                 :            :                         /* all sub page */
     390                 :          0 :                         pdesc->sub_page_code = 0xff;
     391                 :            : 
     392                 :            :                         /* MLUS(7) MODE PAGE POLICY(1-0) */
     393                 :            :                         /* MLUS own copy */
     394                 :            :                         /* Shared MODE PAGE policy */
     395                 :          0 :                         pdesc->policy = 0;
     396                 :            :                         /* Reserved */
     397                 :          0 :                         pdesc->reserved = 0;
     398                 :            : 
     399                 :          0 :                         len += 4;
     400                 :            : 
     401                 :          0 :                         to_be16(vpage->alloc_len, len);
     402                 :          0 :                         break;
     403                 :            :                 }
     404                 :            : 
     405                 :          0 :                 case SPDK_SPC_VPD_SCSI_PORTS: {
     406                 :            :                         /* PAGE LENGTH */
     407                 :          0 :                         hlen = 4;
     408                 :            : 
     409                 :            :                         /* Identification descriptor list */
     410         [ #  # ]:          0 :                         for (i = 0; i < SPDK_SCSI_DEV_MAX_PORTS; i++) {
     411                 :            :                                 struct spdk_scsi_port_desc *sdesc;
     412                 :            :                                 struct spdk_scsi_tgt_port_desc *pdesc;
     413                 :            : 
     414         [ #  # ]:          0 :                                 if (!dev->port[i].is_used) {
     415                 :          0 :                                         continue;
     416                 :            :                                 }
     417                 :            : 
     418                 :            :                                 /* Identification descriptor N */
     419                 :          0 :                                 sdesc = (struct spdk_scsi_port_desc *)&vpage->params[len];
     420                 :            : 
     421                 :            :                                 /* Reserved */
     422                 :          0 :                                 sdesc->reserved = 0;
     423                 :            : 
     424                 :            :                                 /* RELATIVE PORT IDENTIFIER */
     425                 :          0 :                                 to_be16(&sdesc->rel_port_id, dev->port[i].index);
     426                 :            : 
     427                 :            :                                 /* Reserved */
     428                 :          0 :                                 sdesc->reserved2 = 0;
     429                 :            : 
     430                 :            :                                 /* INITIATOR PORT TRANSPORTID LENGTH */
     431                 :          0 :                                 sdesc->init_port_len = 0;
     432                 :            : 
     433                 :            :                                 /* Reserved */
     434                 :          0 :                                 sdesc->init_port_id = 0;
     435                 :            : 
     436                 :            :                                 /* TARGET PORT DESCRIPTORS LENGTH */
     437                 :          0 :                                 sdesc->tgt_desc_len = 0;
     438                 :            : 
     439                 :          0 :                                 len += 12;
     440                 :            : 
     441                 :          0 :                                 plen2 = 0;
     442                 :            :                                 /* Target port descriptor 1 */
     443                 :          0 :                                 pdesc = (struct spdk_scsi_tgt_port_desc *)sdesc->tgt_desc;
     444                 :            : 
     445                 :            :                                 /* PROTOCOL IDENTIFIER(7-4) CODE SET(3-0) */
     446                 :          0 :                                 pdesc->code_set =
     447                 :            :                                         SPDK_SPC_PROTOCOL_IDENTIFIER_ISCSI << 4 |
     448                 :            :                                         SPDK_SPC_VPD_CODE_SET_UTF8;
     449                 :            : 
     450                 :            :                                 /* PIV(7) ASSOCIATION(5-4) IDENTIFIER TYPE(3-0) */
     451                 :          0 :                                 pdesc->desig_type = SPDK_SPC_VPD_DESIG_PIV |
     452                 :            :                                                     SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT << 4 |
     453                 :            :                                                     SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
     454                 :            : 
     455                 :            :                                 /* Reserved */
     456                 :          0 :                                 pdesc->reserved = 0;
     457                 :            : 
     458                 :            :                                 /* IDENTIFIER */
     459                 :          0 :                                 plen = snprintf((char *)pdesc->designator,
     460                 :            :                                                 SPDK_SCSI_PORT_MAX_NAME_LENGTH, "%s",
     461                 :          0 :                                                 dev->port[i].name);
     462                 :          0 :                                 pdesc->len = plen;
     463                 :            : 
     464                 :          0 :                                 plen2 += 4 + plen;
     465                 :            : 
     466                 :            :                                 /* TARGET PORT DESCRIPTORS LENGTH */
     467                 :          0 :                                 to_be16(&sdesc->tgt_desc_len, plen2);
     468                 :            : 
     469                 :          0 :                                 len += plen2;
     470                 :            :                         }
     471                 :            : 
     472                 :          0 :                         to_be16(vpage->alloc_len, len);
     473                 :          0 :                         break;
     474                 :            :                 }
     475                 :            : 
     476                 :        698 :                 case SPDK_SPC_VPD_BLOCK_LIMITS: {
     477                 :        698 :                         uint32_t block_size = spdk_bdev_get_data_block_size(bdev);
     478                 :            : 
     479                 :            :                         /* PAGE LENGTH */
     480         [ -  + ]:        698 :                         memset(&data[4], 0, 60);
     481                 :            : 
     482                 :        698 :                         hlen = 4;
     483                 :            : 
     484                 :            :                         /* WSNZ(0) */
     485                 :            :                         /* support zero length in WRITE SAME */
     486                 :            : 
     487                 :            :                         /* MAXIMUM COMPARE AND WRITE LENGTH */
     488         [ -  + ]:        698 :                         blocks = SPDK_WORK_ATS_BLOCK_SIZE / block_size;
     489                 :            : 
     490         [ +  - ]:        698 :                         if (blocks > 0xff) {
     491                 :        698 :                                 blocks = 0xff;
     492                 :            :                         }
     493                 :            : 
     494                 :        698 :                         data[5] = (uint8_t)blocks;
     495                 :            : 
     496                 :            :                         /* force align to 4KB */
     497         [ +  + ]:        698 :                         if (block_size < 4096) {
     498         [ -  + ]:        482 :                                 optimal_blocks = 4096 / block_size;
     499                 :            :                         } else {
     500                 :        216 :                                 optimal_blocks = 1;
     501                 :            :                         }
     502                 :            : 
     503                 :            :                         /* OPTIMAL TRANSFER LENGTH GRANULARITY */
     504                 :        698 :                         to_be16(&data[6], optimal_blocks);
     505                 :            : 
     506         [ -  + ]:        698 :                         blocks = SPDK_WORK_BLOCK_SIZE / block_size;
     507                 :            : 
     508                 :            :                         /* MAXIMUM TRANSFER LENGTH */
     509                 :        698 :                         to_be32(&data[8], blocks);
     510                 :            :                         /* OPTIMAL TRANSFER LENGTH */
     511                 :        698 :                         to_be32(&data[12], blocks);
     512                 :            : 
     513                 :            :                         /* MAXIMUM PREFETCH XDREAD XDWRITE TRANSFER LENGTH */
     514                 :            : 
     515         [ +  + ]:        698 :                         if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
     516                 :            :                                 /*
     517                 :            :                                  * MAXIMUM UNMAP LBA COUNT: indicates the
     518                 :            :                                  * maximum  number of LBAs that may be
     519                 :            :                                  * unmapped by an UNMAP command.
     520                 :            :                                  */
     521                 :            :                                 /* For now, choose 4MB as the maximum. */
     522                 :        694 :                                 to_be32(&data[20], 4194304);
     523                 :            : 
     524                 :            :                                 /*
     525                 :            :                                  * MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT:
     526                 :            :                                  * indicates the maximum number of UNMAP
     527                 :            :                                  * block descriptors that shall be contained
     528                 :            :                                  * in the parameter data transferred to the
     529                 :            :                                  * device server for an UNMAP command.
     530                 :            :                                  * The bdev layer automatically splits unmap
     531                 :            :                                  * requests, so pick an arbitrary high number here.
     532                 :            :                                  */
     533                 :        694 :                                 to_be32(&data[24], DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT);
     534                 :            : 
     535                 :            :                                 /*
     536                 :            :                                  * The UGAVALID bit is left as 0 which means neither the
     537                 :            :                                  * OPTIMAL UNMAP GRANULARITY nor the UNMAP GRANULARITY
     538                 :            :                                  * ALIGNMENT fields are valid.
     539                 :            :                                  */
     540                 :            :                         }
     541                 :            : 
     542                 :            :                         /*
     543                 :            :                          * MAXIMUM WRITE SAME LENGTH: indicates the
     544                 :            :                          * maximum number of contiguous logical blocks
     545                 :            :                          * that the device server allows to be unmapped
     546                 :            :                          * or written in a single WRITE SAME command.
     547                 :            :                          */
     548                 :        698 :                         to_be64(&data[36], blocks);
     549                 :            : 
     550                 :            :                         /* Reserved */
     551                 :            :                         /* not specified */
     552                 :        698 :                         len = 64 - hlen;
     553                 :            : 
     554                 :        698 :                         to_be16(vpage->alloc_len, len);
     555                 :        698 :                         break;
     556                 :            :                 }
     557                 :            : 
     558                 :        690 :                 case SPDK_SPC_VPD_BLOCK_DEV_CHARS: {
     559                 :            :                         /* PAGE LENGTH */
     560                 :        690 :                         hlen = 4;
     561                 :        690 :                         len = 64 - hlen;
     562                 :            : 
     563                 :        690 :                         to_be16(&data[4], DEFAULT_DISK_ROTATION_RATE);
     564                 :            : 
     565                 :            :                         /* Reserved */
     566                 :        690 :                         data[6] = 0;
     567                 :            :                         /* NOMINAL FORM FACTOR(3-0) */
     568                 :        690 :                         data[7] = DEFAULT_DISK_FORM_FACTOR << 4;
     569                 :            :                         /* Reserved */
     570         [ -  + ]:        690 :                         memset(&data[8], 0, 64 - 8);
     571                 :            : 
     572                 :        690 :                         to_be16(vpage->alloc_len, len);
     573                 :        690 :                         break;
     574                 :            :                 }
     575                 :            : 
     576                 :        720 :                 case SPDK_SPC_VPD_BLOCK_THIN_PROVISION: {
     577         [ +  + ]:        720 :                         if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
     578                 :          1 :                                 goto inq_error;
     579                 :            :                         }
     580                 :            : 
     581                 :        719 :                         hlen = 4;
     582                 :        719 :                         len = 7;
     583                 :            : 
     584                 :            :                         /*
     585                 :            :                          *  PAGE LENGTH : if the DP bit is set to one, then the
     586                 :            :                          *  page length shall be set  0004h.
     587                 :            :                          */
     588                 :        719 :                         to_be16(&data[2], 0x0004);
     589                 :            : 
     590                 :            :                         /*
     591                 :            :                          * THRESHOLD EXPONENT : it indicates the threshold set
     592                 :            :                          * size in LBAs as a power of 2( i.e., the threshold
     593                 :            :                          * set size  = 2 ^ (threshold exponent).
     594                 :            :                          */
     595                 :        719 :                         data[4] = 0;
     596                 :            : 
     597                 :            :                         /*
     598                 :            :                          * Set the LBPU bit to indicate  the support for UNMAP
     599                 :            :                          * command.
     600                 :            :                          */
     601                 :        719 :                         data[5] |= SPDK_SCSI_UNMAP_LBPU;
     602                 :            : 
     603                 :            :                         /*
     604                 :            :                          * Set the provisioning type to thin provision.
     605                 :            :                          */
     606                 :        719 :                         data[6] = SPDK_SCSI_UNMAP_THIN_PROVISIONING;
     607                 :            : 
     608                 :        719 :                         to_be16(vpage->alloc_len, len);
     609                 :        719 :                         break;
     610                 :            :                 }
     611                 :            : 
     612                 :       1646 :                 default:
     613   [ -  +  -  - ]:       1646 :                         if (pc >= 0xc0 && pc <= 0xff) {
     614   [ #  #  #  # ]:          0 :                                 SPDK_DEBUGLOG(scsi, "Vendor specific INQUIRY VPD page 0x%x\n", pc);
     615                 :            :                         } else {
     616                 :       1646 :                                 SPDK_NOTICELOG("unsupported INQUIRY VPD page 0x%x\n", pc);
     617                 :            :                         }
     618                 :       1646 :                         goto inq_error;
     619                 :            :                 }
     620                 :            :         } else {
     621                 :       3621 :                 struct spdk_scsi_cdb_inquiry_data *inqdata =
     622                 :            :                         (struct spdk_scsi_cdb_inquiry_data *)data;
     623                 :            : 
     624                 :            :                 /* Standard INQUIRY data */
     625                 :            :                 /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
     626                 :       3621 :                 inqdata->peripheral_device_type = pd;
     627                 :       3621 :                 inqdata->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
     628                 :            : 
     629                 :            :                 /* RMB(7) */
     630                 :       3621 :                 inqdata->rmb = 0;
     631                 :            : 
     632                 :            :                 /* VERSION */
     633                 :            :                 /* See SPC3/SBC2/MMC4/SAM2 for more details */
     634                 :       3621 :                 inqdata->version = SPDK_SPC_VERSION_SPC3;
     635                 :            : 
     636                 :            :                 /* NORMACA(5) HISUP(4) RESPONSE DATA FORMAT(3-0) */
     637                 :            :                 /* format 2 */ /* hierarchical support */
     638                 :       3621 :                 inqdata->response = 2 | 1 << 4;
     639                 :            : 
     640                 :       3621 :                 hlen = 5;
     641                 :            : 
     642                 :            :                 /* SCCS(7) ACC(6) TPGS(5-4) 3PC(3) PROTECT(0) */
     643                 :            :                 /* Not support TPGS */
     644                 :       3621 :                 inqdata->flags = 0;
     645                 :            : 
     646                 :            :                 /* MULTIP */
     647                 :       3621 :                 inqdata->flags2 = 0x10;
     648                 :            : 
     649                 :            :                 /* WBUS16(5) SYNC(4) LINKED(3) CMDQUE(1) VS(0) */
     650                 :            :                 /* CMDQUE */
     651                 :       3621 :                 inqdata->flags3 = 0x2;
     652                 :            : 
     653                 :            :                 /* T10 VENDOR IDENTIFICATION */
     654                 :       3621 :                 spdk_strcpy_pad(inqdata->t10_vendor_id, DEFAULT_DISK_VENDOR, 8, ' ');
     655                 :            : 
     656                 :            :                 /* PRODUCT IDENTIFICATION */
     657                 :       3621 :                 spdk_strcpy_pad(inqdata->product_id, spdk_bdev_get_product_name(bdev), 16, ' ');
     658                 :            : 
     659                 :            :                 /* PRODUCT REVISION LEVEL */
     660                 :       3621 :                 spdk_strcpy_pad(inqdata->product_rev, DEFAULT_DISK_REVISION, 4, ' ');
     661                 :            : 
     662                 :            :                 /*
     663                 :            :                  * Standard inquiry data ends here.  Only populate remaining fields if alloc_len
     664                 :            :                  *  indicates enough space to hold it.
     665                 :            :                  */
     666                 :       3621 :                 len = INQUIRY_OFFSET(product_rev) - 5;
     667                 :            : 
     668         [ +  - ]:       3621 :                 if (alloc_len >= INQUIRY_OFFSET(vendor)) {
     669                 :            :                         /* Vendor specific */
     670         [ -  + ]:       3621 :                         memset(inqdata->vendor, 0x20, 20);
     671                 :       3621 :                         len += sizeof(inqdata->vendor);
     672                 :            :                 }
     673                 :            : 
     674         [ +  - ]:       3621 :                 if (alloc_len >= INQUIRY_OFFSET(ius)) {
     675                 :            :                         /* CLOCKING(3-2) QAS(1) IUS(0) */
     676                 :       3621 :                         inqdata->ius = 0;
     677                 :       3621 :                         len += sizeof(inqdata->ius);
     678                 :            :                 }
     679                 :            : 
     680         [ +  - ]:       3621 :                 if (alloc_len >= INQUIRY_OFFSET(reserved)) {
     681                 :            :                         /* Reserved */
     682                 :       3621 :                         inqdata->reserved = 0;
     683                 :       3621 :                         len += sizeof(inqdata->reserved);
     684                 :            :                 }
     685                 :            : 
     686                 :            :                 /* VERSION DESCRIPTOR 1-8 */
     687         [ +  - ]:       3621 :                 if (alloc_len >= INQUIRY_OFFSET(reserved) + 2) {
     688                 :       3621 :                         to_be16(&inqdata->desc[0], 0x0960);
     689                 :       3621 :                         len += 2;
     690                 :            :                 }
     691                 :            : 
     692         [ +  - ]:       3621 :                 if (alloc_len >= INQUIRY_OFFSET(reserved) + 4) {
     693                 :       3621 :                         to_be16(&inqdata->desc[2], 0x0300); /* SPC-3 (no version claimed) */
     694                 :       3621 :                         len += 2;
     695                 :            :                 }
     696                 :            : 
     697         [ +  - ]:       3621 :                 if (alloc_len >= INQUIRY_OFFSET(reserved) + 6) {
     698                 :       3621 :                         to_be16(&inqdata->desc[4], 0x320); /* SBC-2 (no version claimed) */
     699                 :       3621 :                         len += 2;
     700                 :            :                 }
     701                 :            : 
     702         [ +  - ]:       3621 :                 if (alloc_len >= INQUIRY_OFFSET(reserved) + 8) {
     703                 :       3621 :                         to_be16(&inqdata->desc[6], 0x0040); /* SAM-2 (no version claimed) */
     704                 :       3621 :                         len += 2;
     705                 :            :                 }
     706                 :            : 
     707                 :            :                 /*
     708                 :            :                  * We only fill out 4 descriptors, but if the allocation length goes past
     709                 :            :                  *  that, zero the remaining bytes.  This fixes some SCSI compliance tests
     710                 :            :                  *  which expect a full 96 bytes to be returned, including the unpopulated
     711                 :            :                  *  version descriptors 5-8 (4 * 2 = 8 bytes) plus the 22 bytes of reserved
     712                 :            :                  *  space (bytes 74-95) - for a total of 30 bytes.
     713                 :            :                  */
     714         [ +  - ]:       3621 :                 if (alloc_len > INQUIRY_OFFSET(reserved) + 8) {
     715                 :       3621 :                         i = alloc_len - (INQUIRY_OFFSET(reserved) + 8);
     716         [ +  - ]:       3621 :                         if (i > 30) {
     717                 :       3621 :                                 i = 30;
     718                 :            :                         }
     719         [ -  + ]:       3621 :                         memset(&inqdata->desc[8], 0, i);
     720                 :       3621 :                         len += i;
     721                 :            :                 }
     722                 :            : 
     723                 :            :                 /* ADDITIONAL LENGTH */
     724                 :       3621 :                 inqdata->add_len = len;
     725                 :            :         }
     726                 :            : 
     727                 :      12101 :         return hlen + len;
     728                 :            : 
     729                 :       1647 : inq_error:
     730                 :       1647 :         task->data_transferred = 0;
     731                 :       1647 :         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
     732                 :            :                                   SPDK_SCSI_SENSE_NO_SENSE,
     733                 :            :                                   SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
     734                 :            :                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
     735                 :       1647 :         return -1;
     736                 :            : }
     737                 :            : 
     738                 :            : static void
     739                 :      40008 : mode_sense_page_init(uint8_t *buf, int len, int page, int subpage)
     740                 :            : {
     741         [ +  + ]:      40008 :         if (!buf) {
     742                 :      20004 :                 return;
     743                 :            :         }
     744                 :            : 
     745         [ -  + ]:      20004 :         memset(buf, 0, len);
     746         [ -  + ]:      20004 :         if (subpage != 0) {
     747                 :          0 :                 buf[0] = page | 0x40; /* PAGE + SPF=1 */
     748                 :          0 :                 buf[1] = subpage;
     749                 :          0 :                 to_be16(&buf[2], len - 4);
     750                 :            :         } else {
     751                 :      20004 :                 buf[0] = page;
     752                 :      20004 :                 buf[1] = len - 2;
     753                 :            :         }
     754                 :            : }
     755                 :            : 
     756                 :            : static int
     757                 :     260338 : bdev_scsi_mode_sense_page(struct spdk_bdev *bdev,
     758                 :            :                           uint8_t *cdb, int pc, int page, int subpage,
     759                 :            :                           uint8_t *data, struct spdk_scsi_task *task)
     760                 :            : {
     761                 :     260338 :         uint8_t *cp = data;
     762                 :     260338 :         int len = 0;
     763                 :            :         int plen;
     764                 :            :         int i;
     765                 :            : 
     766         [ -  + ]:     260338 :         if (pc == 0x00) {
     767                 :            :                 /* Current values */
     768         [ #  # ]:          0 :         } else if (pc == 0x01) {
     769                 :            :                 /* Changeable values */
     770                 :            :                 /* As we currently do not support changeable values,
     771                 :            :                    all parameters are reported as zero. */
     772         [ #  # ]:          0 :         } else if (pc == 0x02) {
     773                 :            :                 /* Default values */
     774                 :            :         } else {
     775                 :            :                 /* Saved values not supported */
     776                 :          0 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
     777                 :            :                                           SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
     778                 :            :                                           SPDK_SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED,
     779                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
     780                 :          0 :                 return -1;
     781                 :            :         }
     782                 :            : 
     783   [ +  +  +  +  :     260338 :         switch (page) {
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  - ]
     784                 :       4006 :         case 0x00:
     785                 :            :                 /* Vendor specific */
     786                 :       4006 :                 break;
     787                 :       4006 :         case 0x01:
     788                 :            :                 /* Read-Write Error Recovery */
     789   [ -  +  -  + ]:       4006 :                 SPDK_DEBUGLOG(scsi,
     790                 :            :                               "MODE_SENSE Read-Write Error Recovery\n");
     791         [ -  + ]:       4006 :                 if (subpage != 0x00) {
     792                 :          0 :                         break;
     793                 :            :                 }
     794                 :       4006 :                 plen = 0x0a + 2;
     795                 :       4006 :                 mode_sense_page_init(cp, plen, page, subpage);
     796                 :       4006 :                 len += plen;
     797                 :       4006 :                 break;
     798                 :       4006 :         case 0x02:
     799                 :            :                 /* Disconnect-Reconnect */
     800   [ -  +  -  + ]:       4006 :                 SPDK_DEBUGLOG(scsi,
     801                 :            :                               "MODE_SENSE Disconnect-Reconnect\n");
     802         [ -  + ]:       4006 :                 if (subpage != 0x00) {
     803                 :          0 :                         break;
     804                 :            :                 }
     805                 :       4006 :                 plen = 0x0e + 2;
     806                 :       4006 :                 mode_sense_page_init(cp, plen, page, subpage);
     807                 :       4006 :                 len += plen;
     808                 :       4006 :                 break;
     809                 :       4006 :         case 0x03:
     810                 :            :                 /* Obsolete (Format Device) */
     811                 :       4006 :                 break;
     812                 :       4006 :         case 0x04:
     813                 :            :                 /* Obsolete (Rigid Disk Geometry) */
     814                 :       4006 :                 break;
     815                 :       4006 :         case 0x05:
     816                 :            :                 /* Obsolete (Rigid Disk Geometry) */
     817                 :       4006 :                 break;
     818                 :       4006 :         case 0x06:
     819                 :            :                 /* Reserved */
     820                 :       4006 :                 break;
     821                 :       4006 :         case 0x07:
     822                 :            :                 /* Verify Error Recovery */
     823   [ -  +  -  + ]:       4006 :                 SPDK_DEBUGLOG(scsi,
     824                 :            :                               "MODE_SENSE Verify Error Recovery\n");
     825                 :            : 
     826         [ -  + ]:       4006 :                 if (subpage != 0x00) {
     827                 :          0 :                         break;
     828                 :            :                 }
     829                 :            : 
     830                 :       4006 :                 plen = 0x0a + 2;
     831                 :       4006 :                 mode_sense_page_init(cp, plen, page, subpage);
     832                 :       4006 :                 len += plen;
     833                 :       4006 :                 break;
     834                 :      11966 :         case 0x08: {
     835                 :            :                 /* Caching */
     836   [ -  +  -  + ]:      11966 :                 SPDK_DEBUGLOG(scsi, "MODE_SENSE Caching\n");
     837         [ -  + ]:      11966 :                 if (subpage != 0x00) {
     838                 :          0 :                         break;
     839                 :            :                 }
     840                 :            : 
     841                 :      11966 :                 plen = 0x12 + 2;
     842                 :      11966 :                 mode_sense_page_init(cp, plen, page, subpage);
     843                 :            : 
     844   [ +  +  +  +  :      11966 :                 if (cp && spdk_bdev_has_write_cache(bdev) && pc != 0x01) {
                   +  - ]
     845                 :        869 :                         cp[2] |= 0x4;        /* WCE */
     846                 :            :                 }
     847                 :            : 
     848                 :            :                 /* Read Cache Disable (RCD) = 1 */
     849   [ +  +  +  - ]:      11966 :                 if (cp && pc != 0x01) {
     850                 :       5983 :                         cp[2] |= 0x1;
     851                 :            :                 }
     852                 :            : 
     853                 :      11966 :                 len += plen;
     854                 :      11966 :                 break;
     855                 :            :         }
     856                 :       4006 :         case 0x09:
     857                 :            :                 /* Obsolete */
     858                 :       4006 :                 break;
     859   [ +  -  -  - ]:       4006 :         case 0x0a:
     860                 :            :                 switch (subpage) {
     861                 :       4006 :                 case 0x00:
     862                 :            :                         /* Control */
     863   [ -  +  -  + ]:       4006 :                         SPDK_DEBUGLOG(scsi,
     864                 :            :                                       "MODE_SENSE Control\n");
     865                 :       4006 :                         plen = 0x0a + 2;
     866                 :       4006 :                         mode_sense_page_init(cp, plen, page, subpage);
     867                 :       4006 :                         len += plen;
     868                 :       4006 :                         break;
     869                 :          0 :                 case 0x01:
     870                 :            :                         /* Control Extension */
     871   [ #  #  #  # ]:          0 :                         SPDK_DEBUGLOG(scsi,
     872                 :            :                                       "MODE_SENSE Control Extension\n");
     873                 :          0 :                         plen = 0x1c + 4;
     874                 :          0 :                         mode_sense_page_init(cp, plen, page, subpage);
     875                 :          0 :                         len += plen;
     876                 :          0 :                         break;
     877                 :          0 :                 case 0xff:
     878                 :            :                         /* All subpages */
     879         [ #  # ]:          0 :                         len += bdev_scsi_mode_sense_page(bdev,
     880                 :            :                                                          cdb, pc, page,
     881                 :            :                                                          0x00,
     882                 :          0 :                                                          cp ? &cp[len] : NULL, task);
     883         [ #  # ]:          0 :                         len += bdev_scsi_mode_sense_page(bdev,
     884                 :            :                                                          cdb, pc, page,
     885                 :            :                                                          0x01,
     886                 :          0 :                                                          cp ? &cp[len] : NULL, task);
     887                 :          0 :                         break;
     888                 :          0 :                 default:
     889                 :            :                         /* 0x02-0x3e: Reserved */
     890                 :          0 :                         break;
     891                 :            :                 }
     892                 :       4006 :                 break;
     893                 :       4006 :         case 0x0b:
     894                 :            :                 /* Obsolete (Medium Types Supported) */
     895                 :       4006 :                 break;
     896                 :       4006 :         case 0x0c:
     897                 :            :                 /* Obsolete (Notch And Partition) */
     898                 :       4006 :                 break;
     899                 :       4006 :         case 0x0d:
     900                 :            :                 /* Obsolete */
     901                 :       4006 :                 break;
     902                 :       8012 :         case 0x0e:
     903                 :            :         case 0x0f:
     904                 :            :                 /* Reserved */
     905                 :       8012 :                 break;
     906                 :       4006 :         case 0x10:
     907                 :            :                 /* XOR Control */
     908   [ -  +  -  + ]:       4006 :                 SPDK_DEBUGLOG(scsi, "MODE_SENSE XOR Control\n");
     909         [ -  + ]:       4006 :                 if (subpage != 0x00) {
     910                 :          0 :                         break;
     911                 :            :                 }
     912                 :       4006 :                 plen = 0x16 + 2;
     913                 :       4006 :                 mode_sense_page_init(cp, plen, page, subpage);
     914                 :       4006 :                 len += plen;
     915                 :       4006 :                 break;
     916                 :      12018 :         case 0x11:
     917                 :            :         case 0x12:
     918                 :            :         case 0x13:
     919                 :            :                 /* Reserved */
     920                 :      12018 :                 break;
     921                 :       4006 :         case 0x14:
     922                 :            :                 /* Enclosure Services Management */
     923                 :       4006 :                 break;
     924                 :      12018 :         case 0x15:
     925                 :            :         case 0x16:
     926                 :            :         case 0x17:
     927                 :            :                 /* Reserved */
     928                 :      12018 :                 break;
     929                 :       4006 :         case 0x18:
     930                 :            :                 /* Protocol-Specific LUN */
     931                 :       4006 :                 break;
     932                 :       4006 :         case 0x19:
     933                 :            :                 /* Protocol-Specific Port */
     934                 :       4006 :                 break;
     935                 :       4006 :         case 0x1a:
     936                 :            :                 /* Power Condition */
     937   [ -  +  -  + ]:       4006 :                 SPDK_DEBUGLOG(scsi,
     938                 :            :                               "MODE_SENSE Power Condition\n");
     939         [ -  + ]:       4006 :                 if (subpage != 0x00) {
     940                 :          0 :                         break;
     941                 :            :                 }
     942                 :       4006 :                 plen = 0x0a + 2;
     943                 :       4006 :                 mode_sense_page_init(cp, plen, page, subpage);
     944                 :       4006 :                 len += plen;
     945                 :       4006 :                 break;
     946                 :       4006 :         case 0x1b:
     947                 :            :                 /* Reserved */
     948                 :       4006 :                 break;
     949                 :       4006 :         case 0x1c:
     950                 :            :                 /* Informational Exceptions Control */
     951   [ -  +  -  + ]:       4006 :                 SPDK_DEBUGLOG(scsi,
     952                 :            :                               "MODE_SENSE Informational Exceptions Control\n");
     953         [ -  + ]:       4006 :                 if (subpage != 0x00) {
     954                 :          0 :                         break;
     955                 :            :                 }
     956                 :            : 
     957                 :       4006 :                 plen = 0x0a + 2;
     958                 :       4006 :                 mode_sense_page_init(cp, plen, page, subpage);
     959                 :       4006 :                 len += plen;
     960                 :       4006 :                 break;
     961                 :      12018 :         case 0x1d:
     962                 :            :         case 0x1e:
     963                 :            :         case 0x1f:
     964                 :            :                 /* Reserved */
     965                 :      12018 :                 break;
     966                 :     120180 :         case 0x20:
     967                 :            :         case 0x21:
     968                 :            :         case 0x22:
     969                 :            :         case 0x23:
     970                 :            :         case 0x24:
     971                 :            :         case 0x25:
     972                 :            :         case 0x26:
     973                 :            :         case 0x27:
     974                 :            :         case 0x28:
     975                 :            :         case 0x29:
     976                 :            :         case 0x2a:
     977                 :            :         case 0x2b:
     978                 :            :         case 0x2c:
     979                 :            :         case 0x2d:
     980                 :            :         case 0x2e:
     981                 :            :         case 0x2f:
     982                 :            :         case 0x30:
     983                 :            :         case 0x31:
     984                 :            :         case 0x32:
     985                 :            :         case 0x33:
     986                 :            :         case 0x34:
     987                 :            :         case 0x35:
     988                 :            :         case 0x36:
     989                 :            :         case 0x37:
     990                 :            :         case 0x38:
     991                 :            :         case 0x39:
     992                 :            :         case 0x3a:
     993                 :            :         case 0x3b:
     994                 :            :         case 0x3c:
     995                 :            :         case 0x3d:
     996                 :            :         case 0x3e:
     997                 :            :                 /* Vendor-specific */
     998                 :     120180 :                 break;
     999      [ +  -  - ]:       4006 :         case 0x3f:
    1000                 :            :                 switch (subpage) {
    1001                 :       4006 :                 case 0x00:
    1002                 :            :                         /* All mode pages */
    1003         [ +  + ]:     252378 :                         for (i = 0x00; i < 0x3e; i ++) {
    1004         [ +  + ]:     372558 :                                 len += bdev_scsi_mode_sense_page(
    1005                 :            :                                                bdev, cdb, pc, i, 0x00,
    1006                 :     124186 :                                                cp ? &cp[len] : NULL, task);
    1007                 :            :                         }
    1008                 :       4006 :                         break;
    1009                 :          0 :                 case 0xff:
    1010                 :            :                         /* All mode pages and subpages */
    1011         [ #  # ]:          0 :                         for (i = 0x00; i < 0x3e; i ++) {
    1012         [ #  # ]:          0 :                                 len += bdev_scsi_mode_sense_page(
    1013                 :            :                                                bdev, cdb, pc, i, 0x00,
    1014                 :          0 :                                                cp ? &cp[len] : NULL, task);
    1015                 :            :                         }
    1016         [ #  # ]:          0 :                         for (i = 0x00; i < 0x3e; i ++) {
    1017         [ #  # ]:          0 :                                 len += bdev_scsi_mode_sense_page(
    1018                 :            :                                                bdev, cdb, pc, i, 0xff,
    1019                 :          0 :                                                cp ? &cp[len] : NULL, task);
    1020                 :            :                         }
    1021                 :          0 :                         break;
    1022                 :          0 :                 default:
    1023                 :            :                         /* 0x01-0x3e: Reserved */
    1024                 :          0 :                         break;
    1025                 :            :                 }
    1026                 :        504 :         }
    1027                 :            : 
    1028                 :     260338 :         return len;
    1029                 :            : }
    1030                 :            : 
    1031                 :            : static int
    1032                 :      11966 : bdev_scsi_mode_sense(struct spdk_bdev *bdev, int md,
    1033                 :            :                      uint8_t *cdb, int dbd, int llbaa, int pc,
    1034                 :            :                      int page, int subpage, uint8_t *data, struct spdk_scsi_task *task)
    1035                 :            : {
    1036                 :      11966 :         uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
    1037                 :      11966 :         uint32_t block_size = spdk_bdev_get_data_block_size(bdev);
    1038                 :            :         uint8_t *hdr, *bdesc, *pages;
    1039                 :            :         int hlen;
    1040                 :            :         int blen;
    1041                 :            :         int plen, total;
    1042                 :            : 
    1043   [ +  +  -  + ]:      11966 :         assert(md == 6 || md == 10);
    1044                 :            : 
    1045         [ +  + ]:      11966 :         if (md == 6) {
    1046                 :      11954 :                 hlen = 4;
    1047                 :      11954 :                 blen = 8; /* For MODE SENSE 6 only short LBA */
    1048                 :            :         } else {
    1049                 :         12 :                 hlen = 8;
    1050         [ -  + ]:         12 :                 blen = llbaa ? 16 : 8;
    1051                 :            :         }
    1052                 :            : 
    1053         [ -  + ]:      11966 :         if (dbd) {
    1054                 :          0 :                 blen = 0;
    1055                 :            :         }
    1056                 :            : 
    1057         [ +  + ]:      11966 :         pages = data ? &data[hlen + blen] : NULL;
    1058                 :      11966 :         plen = bdev_scsi_mode_sense_page(bdev, cdb, pc, page,
    1059                 :            :                                          subpage,
    1060                 :            :                                          pages, task);
    1061         [ -  + ]:      11966 :         if (plen < 0) {
    1062                 :          0 :                 return -1;
    1063                 :            :         }
    1064                 :            : 
    1065                 :      11966 :         total = hlen + blen + plen;
    1066         [ +  + ]:      11966 :         if (data == NULL) {
    1067                 :       5983 :                 return total;
    1068                 :            :         }
    1069                 :            : 
    1070                 :       5983 :         hdr = &data[0];
    1071         [ +  + ]:       5983 :         if (hlen == 4) {
    1072                 :       5977 :                 hdr[0] = total - 1;            /* Mode Data Length */
    1073                 :       5977 :                 hdr[1] = 0;                    /* Medium Type */
    1074                 :       5977 :                 hdr[2] = 0;                    /* Device-Specific Parameter */
    1075                 :       5977 :                 hdr[3] = blen;                 /* Block Descriptor Length */
    1076                 :            :         } else {
    1077                 :          6 :                 to_be16(&hdr[0], total - 2);   /* Mode Data Length */
    1078                 :          6 :                 hdr[2] = 0;                    /* Medium Type */
    1079                 :          6 :                 hdr[3] = 0;                    /* Device-Specific Parameter */
    1080                 :          6 :                 hdr[4] = llbaa ? 0x1 : 0;      /* Long/short LBA */
    1081                 :          6 :                 hdr[5] = 0;                    /* Reserved */
    1082                 :          6 :                 to_be16(&hdr[6], blen);        /* Block Descriptor Length */
    1083                 :            :         }
    1084                 :            : 
    1085                 :       5983 :         bdesc = &data[hlen];
    1086         [ -  + ]:       5983 :         if (blen == 16) {
    1087                 :            :                 /* Number of Blocks */
    1088                 :          0 :                 to_be64(&bdesc[0], num_blocks);
    1089                 :            :                 /* Reserved */
    1090         [ #  # ]:          0 :                 memset(&bdesc[8], 0, 4);
    1091                 :            :                 /* Block Length */
    1092                 :          0 :                 to_be32(&bdesc[12], block_size);
    1093         [ +  - ]:       5983 :         } else if (blen == 8) {
    1094                 :            :                 /* Number of Blocks */
    1095         [ -  + ]:       5983 :                 if (num_blocks > 0xffffffffULL) {
    1096         [ #  # ]:          0 :                         memset(&bdesc[0], 0xff, 4);
    1097                 :            :                 } else {
    1098                 :       5983 :                         to_be32(&bdesc[0], num_blocks);
    1099                 :            :                 }
    1100                 :            : 
    1101                 :            :                 /* Block Length */
    1102                 :       5983 :                 to_be32(&bdesc[4], block_size);
    1103                 :            :         }
    1104                 :            : 
    1105                 :       5983 :         return total;
    1106                 :            : }
    1107                 :            : 
    1108                 :            : static void
    1109                 :   13559099 : bdev_scsi_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
    1110                 :            :                             void *cb_arg)
    1111                 :            : {
    1112                 :   13559099 :         struct spdk_scsi_task *task = cb_arg;
    1113                 :    1859348 :         int sc, sk, asc, ascq;
    1114                 :            : 
    1115                 :   13559099 :         spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
    1116                 :            : 
    1117                 :   13559099 :         spdk_bdev_free_io(bdev_io);
    1118                 :            : 
    1119                 :   13559099 :         spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
    1120                 :   13559099 :         scsi_lun_complete_task(task->lun, task);
    1121                 :   13559099 : }
    1122                 :            : 
    1123                 :            : static void
    1124                 :   15546929 : bdev_scsi_read_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
    1125                 :            :                                  void *cb_arg)
    1126                 :            : {
    1127                 :   15546929 :         struct spdk_scsi_task *task = cb_arg;
    1128                 :    2324640 :         int sc, sk, asc, ascq;
    1129                 :            : 
    1130                 :   15546929 :         task->bdev_io = bdev_io;
    1131                 :            : 
    1132                 :   15546929 :         spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
    1133                 :            : 
    1134                 :   15546929 :         spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
    1135                 :   15546929 :         scsi_lun_complete_task(task->lun, task);
    1136                 :   15546929 : }
    1137                 :            : 
    1138                 :            : static void
    1139                 :         10 : bdev_scsi_task_complete_reset(struct spdk_bdev_io *bdev_io, bool success,
    1140                 :            :                               void *cb_arg)
    1141                 :            : {
    1142                 :         10 :         struct spdk_scsi_task *task = cb_arg;
    1143                 :            : 
    1144                 :         10 :         spdk_bdev_free_io(bdev_io);
    1145                 :            : 
    1146         [ +  - ]:         10 :         if (success) {
    1147                 :         10 :                 task->response = SPDK_SCSI_TASK_MGMT_RESP_SUCCESS;
    1148                 :            :         }
    1149                 :            : 
    1150                 :         10 :         scsi_lun_complete_reset_task(task->lun, task);
    1151                 :         10 : }
    1152                 :            : 
    1153                 :            : static void
    1154                 :     163658 : bdev_scsi_queue_io(struct spdk_scsi_task *task, spdk_bdev_io_wait_cb cb_fn, void *cb_arg)
    1155                 :            : {
    1156                 :     163658 :         struct spdk_scsi_lun *lun = task->lun;
    1157                 :     163658 :         struct spdk_bdev *bdev = lun->bdev;
    1158                 :     163658 :         struct spdk_io_channel *ch = lun->io_channel;
    1159                 :            :         int rc;
    1160                 :            : 
    1161                 :     163658 :         task->bdev_io_wait.bdev = bdev;
    1162                 :     163658 :         task->bdev_io_wait.cb_fn = cb_fn;
    1163                 :     163658 :         task->bdev_io_wait.cb_arg = cb_arg;
    1164                 :            : 
    1165                 :     163658 :         rc = spdk_bdev_queue_io_wait(bdev, ch, &task->bdev_io_wait);
    1166         [ -  + ]:     163658 :         if (rc != 0) {
    1167                 :          0 :                 assert(false);
    1168                 :            :         }
    1169                 :     163658 : }
    1170                 :            : 
    1171                 :            : static int
    1172                 :    1147083 : bdev_scsi_sync(struct spdk_bdev *bdev, struct spdk_bdev_desc *bdev_desc,
    1173                 :            :                struct spdk_io_channel *bdev_ch, struct spdk_scsi_task *task,
    1174                 :            :                uint64_t lba, uint32_t num_blocks)
    1175                 :            : {
    1176                 :            :         uint64_t bdev_num_blocks;
    1177                 :            :         int rc;
    1178                 :            : 
    1179         [ -  + ]:    1147083 :         if (num_blocks == 0) {
    1180                 :          0 :                 return SPDK_SCSI_TASK_COMPLETE;
    1181                 :            :         }
    1182                 :            : 
    1183                 :    1147083 :         bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
    1184                 :            : 
    1185   [ +  -  +  - ]:    1147083 :         if (lba >= bdev_num_blocks || num_blocks > bdev_num_blocks ||
    1186         [ -  + ]:    1147083 :             lba > (bdev_num_blocks - num_blocks)) {
    1187                 :          0 :                 SPDK_ERRLOG("end of media\n");
    1188                 :          0 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1189                 :            :                                           SPDK_SCSI_SENSE_NO_SENSE,
    1190                 :            :                                           SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
    1191                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1192                 :          0 :                 return SPDK_SCSI_TASK_COMPLETE;
    1193                 :            :         }
    1194                 :            : 
    1195                 :    1147083 :         rc = spdk_bdev_flush_blocks(bdev_desc, bdev_ch, lba, num_blocks,
    1196                 :            :                                     bdev_scsi_task_complete_cmd, task);
    1197                 :            : 
    1198         [ +  + ]:    1147083 :         if (rc) {
    1199         [ +  - ]:      51459 :                 if (rc == -ENOMEM) {
    1200                 :      51459 :                         bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
    1201                 :      51459 :                         return SPDK_SCSI_TASK_PENDING;
    1202                 :            :                 }
    1203                 :          0 :                 SPDK_ERRLOG("spdk_bdev_flush_blocks() failed\n");
    1204                 :          0 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1205                 :            :                                           SPDK_SCSI_SENSE_NO_SENSE,
    1206                 :            :                                           SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
    1207                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1208                 :          0 :                 return SPDK_SCSI_TASK_COMPLETE;
    1209                 :            :         }
    1210                 :    1095624 :         task->data_transferred = 0;
    1211                 :    1095624 :         return SPDK_SCSI_TASK_PENDING;
    1212                 :            : }
    1213                 :            : 
    1214                 :            : static uint64_t
    1215                 :   28085415 : _bytes_to_blocks(uint32_t block_size, uint64_t offset_bytes, uint64_t *offset_blocks,
    1216                 :            :                  uint64_t num_bytes, uint64_t *num_blocks)
    1217                 :            : {
    1218                 :            :         uint8_t shift_cnt;
    1219                 :            : 
    1220                 :            :         /* Avoid expensive div operations if possible. These spdk_u32 functions are very cheap. */
    1221         [ +  - ]:   28085415 :         if (spdk_likely(spdk_u32_is_pow2(block_size))) {
    1222                 :   28085415 :                 shift_cnt = spdk_u32log2(block_size);
    1223         [ -  + ]:   28085415 :                 *offset_blocks = offset_bytes >> shift_cnt;
    1224         [ -  + ]:   28085415 :                 *num_blocks = num_bytes >> shift_cnt;
    1225         [ -  + ]:   28085415 :                 return (offset_bytes - (*offset_blocks << shift_cnt)) |
    1226         [ -  + ]:   28085415 :                        (num_bytes - (*num_blocks << shift_cnt));
    1227                 :            :         } else {
    1228         [ #  # ]:          0 :                 *offset_blocks = offset_bytes / block_size;
    1229         [ #  # ]:          0 :                 *num_blocks = num_bytes / block_size;
    1230   [ #  #  #  # ]:          0 :                 return (offset_bytes % block_size) | (num_bytes % block_size);
    1231                 :            :         }
    1232                 :            : }
    1233                 :            : 
    1234                 :            : static int
    1235                 :   28084929 : bdev_scsi_readwrite(struct spdk_bdev *bdev, struct spdk_bdev_desc *bdev_desc,
    1236                 :            :                     struct spdk_io_channel *bdev_ch, struct spdk_scsi_task *task,
    1237                 :            :                     uint64_t lba, uint32_t xfer_len, bool is_read, bool is_compare)
    1238                 :            : {
    1239                 :    4183995 :         uint64_t bdev_num_blocks, offset_blocks, num_blocks;
    1240                 :            :         uint32_t max_xfer_len, block_size;
    1241                 :   28084929 :         int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
    1242                 :            :         int rc;
    1243                 :            : 
    1244                 :   28084929 :         task->data_transferred = 0;
    1245                 :            : 
    1246   [ +  +  +  +  :   28084929 :         if (spdk_unlikely(task->dxfer_dir != SPDK_SCSI_DIR_NONE &&
                   -  + ]
    1247                 :            :                           task->dxfer_dir != (is_read ? SPDK_SCSI_DIR_FROM_DEV : SPDK_SCSI_DIR_TO_DEV))) {
    1248                 :          0 :                 SPDK_ERRLOG("Incorrect data direction\n");
    1249                 :          0 :                 goto check_condition;
    1250                 :            :         }
    1251                 :            : 
    1252                 :   28084929 :         bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
    1253   [ +  +  +  + ]:   28084929 :         if (spdk_unlikely(bdev_num_blocks <= lba || bdev_num_blocks - lba < xfer_len)) {
    1254   [ -  +  -  + ]:         18 :                 SPDK_DEBUGLOG(scsi, "end of media\n");
    1255                 :         18 :                 sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
    1256                 :         18 :                 asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
    1257                 :         18 :                 goto check_condition;
    1258                 :            :         }
    1259                 :            : 
    1260         [ +  + ]:   28084911 :         if (spdk_unlikely(xfer_len == 0)) {
    1261                 :          6 :                 task->status = SPDK_SCSI_STATUS_GOOD;
    1262                 :          6 :                 return SPDK_SCSI_TASK_COMPLETE;
    1263                 :            :         }
    1264                 :            : 
    1265                 :   28084905 :         block_size = spdk_bdev_get_data_block_size(bdev);
    1266                 :            : 
    1267                 :            :         /* Transfer Length is limited to the Block Limits VPD page Maximum Transfer Length */
    1268         [ -  + ]:   28084905 :         max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
    1269         [ +  + ]:   28084905 :         if (spdk_unlikely(xfer_len > max_xfer_len)) {
    1270                 :          6 :                 SPDK_ERRLOG("xfer_len %" PRIu32 " > maximum transfer length %" PRIu32 "\n",
    1271                 :            :                             xfer_len, max_xfer_len);
    1272                 :          6 :                 sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
    1273                 :          6 :                 asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
    1274                 :          6 :                 goto check_condition;
    1275                 :            :         }
    1276                 :            : 
    1277         [ +  + ]:   28084899 :         if (!is_read) {
    1278                 :            :                 /* Additional check for Transfer Length */
    1279         [ -  + ]:   12497711 :                 if (xfer_len * block_size > task->transfer_len) {
    1280                 :          0 :                         SPDK_ERRLOG("xfer_len %" PRIu32 " * block_size %" PRIu32 " > transfer_len %u\n",
    1281                 :            :                                     xfer_len, block_size, task->transfer_len);
    1282                 :          0 :                         goto check_condition;
    1283                 :            :                 }
    1284                 :            :         }
    1285                 :            : 
    1286         [ -  + ]:   28084899 :         if (_bytes_to_blocks(block_size, task->offset, &offset_blocks, task->length, &num_blocks) != 0) {
    1287                 :          0 :                 SPDK_ERRLOG("task's offset %" PRIu64 " or length %" PRIu32 " is not block multiple\n",
    1288                 :            :                             task->offset, task->length);
    1289                 :          0 :                 goto check_condition;
    1290                 :            :         }
    1291                 :            : 
    1292                 :   28084899 :         offset_blocks += lba;
    1293                 :            : 
    1294   [ -  +  -  +  :   28084899 :         SPDK_DEBUGLOG(scsi,
                   -  - ]
    1295                 :            :                       "%s: lba=%"PRIu64", len=%"PRIu64"\n",
    1296                 :            :                       is_read ? "Read" : "Write", offset_blocks, num_blocks);
    1297                 :            : 
    1298         [ +  + ]:   28084899 :         if (is_read) {
    1299                 :   15587188 :                 rc = spdk_bdev_readv_blocks(bdev_desc, bdev_ch, task->iovs, task->iovcnt,
    1300                 :            :                                             offset_blocks, num_blocks,
    1301                 :            :                                             bdev_scsi_read_task_complete_cmd, task);
    1302         [ -  + ]:   12497711 :         } else if (is_compare) {
    1303                 :            :                 struct iovec *iov;
    1304                 :            :                 size_t len;
    1305                 :            : 
    1306   [ #  #  #  # ]:          0 :                 if (task->iovcnt != 1 || task->iovs[0].iov_len != (block_size * 2)) {
    1307         [ #  # ]:          0 :                         if (task->iovcnt != 1) {
    1308                 :          0 :                                 SPDK_ERRLOG("task's iovcnt %" PRIu32 " is not 1.\n", task->iovcnt);
    1309                 :            :                         } else {
    1310                 :          0 :                                 SPDK_ERRLOG("task's iov len %" PRIu64 " is not 2 * BLOCK_SIZE.\n",
    1311                 :            :                                             task->iovs[0].iov_len);
    1312                 :            :                         }
    1313                 :          0 :                         sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
    1314                 :          0 :                         asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
    1315                 :          0 :                         goto check_condition;
    1316                 :            :                 }
    1317                 :            : 
    1318                 :          0 :                 iov = &task->iovs[0];
    1319                 :          0 :                 len = iov->iov_len >> 1;
    1320                 :          0 :                 task->caw_iov.iov_len = len;
    1321                 :          0 :                 task->caw_iov.iov_base = (uint8_t *)(iov->iov_base) + len;
    1322                 :          0 :                 iov->iov_len = len;
    1323                 :            : 
    1324                 :          0 :                 rc = spdk_bdev_comparev_and_writev_blocks(bdev_desc, bdev_ch, iov, 1,
    1325                 :            :                                 &task->caw_iov, 1, offset_blocks, 1, bdev_scsi_task_complete_cmd, task);
    1326                 :            :         } else {
    1327                 :   12497711 :                 rc = spdk_bdev_writev_blocks(bdev_desc, bdev_ch, task->iovs, task->iovcnt,
    1328                 :            :                                              offset_blocks, num_blocks,
    1329                 :            :                                              bdev_scsi_task_complete_cmd, task);
    1330                 :            :         }
    1331                 :            : 
    1332         [ +  + ]:   28084899 :         if (rc) {
    1333         [ +  - ]:      74513 :                 if (rc == -ENOMEM) {
    1334                 :      74513 :                         bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
    1335                 :      74513 :                         return SPDK_SCSI_TASK_PENDING;
    1336                 :            :                 }
    1337   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("spdk_bdev_%s_blocks() failed: %d\n",
    1338                 :            :                             is_read ? "readv" : (is_compare ? "comparev_and_writev" : "writev"), rc);
    1339                 :          0 :                 goto check_condition;
    1340                 :            :         }
    1341                 :            : 
    1342                 :   28010386 :         task->data_transferred = task->length;
    1343                 :   28010386 :         return SPDK_SCSI_TASK_PENDING;
    1344                 :            : 
    1345                 :         24 : check_condition:
    1346                 :         24 :         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, sk, asc,
    1347                 :            :                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1348                 :         24 :         return SPDK_SCSI_TASK_COMPLETE;
    1349                 :            : }
    1350                 :            : 
    1351                 :            : struct spdk_bdev_scsi_split_ctx {
    1352                 :            :         struct spdk_scsi_task           *task;
    1353                 :            :         union {
    1354                 :            :                 struct spdk_scsi_unmap_bdesc    desc[DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT];
    1355                 :            :                 uint64_t                        start_offset_blocks;    /* used by writesame */
    1356                 :            :         };
    1357                 :            :         uint16_t                        remaining_count;
    1358                 :            :         uint16_t                        current_count;
    1359                 :            :         uint16_t                        outstanding_count;
    1360                 :            :         int     (*fn)(struct spdk_bdev_scsi_split_ctx *ctx);
    1361                 :            : };
    1362                 :            : 
    1363                 :            : static int bdev_scsi_split(struct spdk_bdev_scsi_split_ctx *ctx);
    1364                 :            : 
    1365                 :            : static void
    1366                 :      37686 : bdev_scsi_split_resubmit(void *arg)
    1367                 :            : {
    1368                 :      37686 :         struct spdk_bdev_scsi_split_ctx *ctx = arg;
    1369                 :            : 
    1370                 :      37686 :         bdev_scsi_split(ctx);
    1371                 :      37686 : }
    1372                 :            : 
    1373                 :            : static int
    1374                 :     708808 : bdev_scsi_split(struct spdk_bdev_scsi_split_ctx *ctx)
    1375                 :            : {
    1376                 :     708808 :         struct spdk_scsi_task *task = ctx->task;
    1377                 :     708808 :         uint8_t opcode = task->cdb[0];
    1378                 :            :         int rc;
    1379                 :            : 
    1380         [ +  + ]:    2106164 :         while (ctx->remaining_count != 0) {
    1381                 :    1435084 :                 rc = ctx->fn(ctx);
    1382         [ +  + ]:    1435084 :                 if (rc == 0) {
    1383                 :    1397356 :                         ctx->current_count++;
    1384                 :    1397356 :                         ctx->remaining_count--;
    1385                 :    1397356 :                         ctx->outstanding_count++;
    1386                 :    1397356 :                         continue;
    1387         [ +  - ]:      37728 :                 } else if (rc == -ENOMEM) {
    1388                 :      37728 :                         break;
    1389                 :            :                 }
    1390                 :            : 
    1391                 :          0 :                 SPDK_ERRLOG("SCSI %s failed\n", spdk_scsi_sbc_opcode_string(opcode, 0));
    1392                 :          0 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1393                 :            :                                           SPDK_SCSI_SENSE_NO_SENSE,
    1394                 :            :                                           SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
    1395                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1396                 :            :                 /* If any child I/O failed, stop further splitting process. */
    1397                 :          0 :                 ctx->current_count += ctx->remaining_count;
    1398                 :          0 :                 ctx->remaining_count = 0;
    1399                 :          0 :                 break;
    1400                 :            :         }
    1401                 :            : 
    1402         [ +  + ]:     708808 :         if (ctx->outstanding_count != 0) {
    1403                 :            :                 /* We can't complete here - we may have to wait for previously
    1404                 :            :                  * submitted child I/Os to complete */
    1405                 :     671122 :                 return SPDK_SCSI_TASK_PENDING;
    1406                 :            :         }
    1407                 :            : 
    1408         [ +  - ]:      37686 :         if (rc == -ENOMEM) {
    1409                 :            :                 /* none outstanding child IO submitted, no callback would be involked.
    1410                 :            :                    this is the last chance to resubmit on -ENOMEM */
    1411                 :      37686 :                 bdev_scsi_queue_io(task, bdev_scsi_split_resubmit, ctx);
    1412                 :      37686 :                 return SPDK_SCSI_TASK_PENDING;
    1413                 :            :         }
    1414                 :            : 
    1415                 :          0 :         free(ctx);
    1416                 :          0 :         return SPDK_SCSI_TASK_COMPLETE;
    1417                 :            : }
    1418                 :            : 
    1419                 :            : static void
    1420                 :    1397356 : bdev_scsi_task_complete_split_cmd(struct spdk_bdev_io *bdev_io, bool success,
    1421                 :            :                                   void *cb_arg)
    1422                 :            : {
    1423                 :    1397356 :         struct spdk_bdev_scsi_split_ctx *ctx = cb_arg;
    1424                 :    1397356 :         struct spdk_scsi_task *task = ctx->task;
    1425                 :            : 
    1426                 :    1397356 :         spdk_bdev_free_io(bdev_io);
    1427                 :            : 
    1428         [ +  + ]:    1397356 :         if (!success) {
    1429                 :       4000 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1430                 :            :                                           SPDK_SCSI_SENSE_NO_SENSE,
    1431                 :            :                                           SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
    1432                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1433                 :            :                 /* If any child I/O failed, stop further splitting process. */
    1434                 :       4000 :                 ctx->current_count += ctx->remaining_count;
    1435                 :       4000 :                 ctx->remaining_count = 0;
    1436                 :            :         }
    1437                 :            : 
    1438                 :    1397356 :         ctx->outstanding_count--;
    1439         [ +  + ]:    1397356 :         if (ctx->outstanding_count != 0) {
    1440                 :            :                 /* Any child I/O is still outstanding. */
    1441                 :     726234 :                 return;
    1442                 :            :         }
    1443                 :            : 
    1444         [ +  + ]:     671122 :         if (ctx->remaining_count == 0) {
    1445                 :            :                 /* SCSI task finishes when all descriptors are consumed. */
    1446                 :     671080 :                 scsi_lun_complete_task(task->lun, task);
    1447                 :     671080 :                 free(ctx);
    1448                 :     671080 :                 return;
    1449                 :            :         }
    1450                 :            : 
    1451                 :            :         /* Continue with splitting process. */
    1452                 :         42 :         bdev_scsi_split(ctx);
    1453                 :            : }
    1454                 :            : 
    1455                 :            : static int
    1456                 :     670564 : __copy_desc(struct spdk_bdev_scsi_split_ctx *ctx, uint8_t *data, size_t data_len)
    1457                 :            : {
    1458                 :            :         uint16_t        desc_data_len;
    1459                 :            :         uint16_t        desc_count;
    1460                 :            : 
    1461         [ -  + ]:     670564 :         if (!data) {
    1462                 :          0 :                 return -EINVAL;
    1463                 :            :         }
    1464                 :            : 
    1465         [ -  + ]:     670564 :         if (data_len < 8) {
    1466                 :            :                 /* We can't even get the reported length, so fail. */
    1467                 :          0 :                 return -EINVAL;
    1468                 :            :         }
    1469                 :            : 
    1470                 :     670564 :         desc_data_len = from_be16(&data[2]);
    1471                 :     670564 :         desc_count = desc_data_len / 16;
    1472                 :            : 
    1473         [ -  + ]:     670564 :         if (desc_data_len > (data_len - 8)) {
    1474                 :          0 :                 SPDK_ERRLOG("Error - desc_data_len (%u) > data_len (%zu) - 8\n",
    1475                 :            :                             desc_data_len, data_len);
    1476                 :          0 :                 return -EINVAL;
    1477                 :            :         }
    1478                 :            : 
    1479         [ -  + ]:     670564 :         if (desc_count > DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT) {
    1480                 :          0 :                 SPDK_ERRLOG("desc_count (%u) greater than max allowed (%u)\n",
    1481                 :            :                             desc_count, DEFAULT_MAX_UNMAP_BLOCK_DESCRIPTOR_COUNT);
    1482                 :          0 :                 return -EINVAL;
    1483                 :            :         }
    1484                 :            : 
    1485   [ -  +  -  + ]:     670564 :         memcpy(ctx->desc, &data[8], desc_data_len);
    1486                 :     670564 :         return desc_count;
    1487                 :            : }
    1488                 :            : 
    1489                 :            : static int
    1490                 :     708280 : _bdev_scsi_unmap(struct spdk_bdev_scsi_split_ctx *ctx)
    1491                 :            : {
    1492                 :     708280 :         struct spdk_scsi_task *task = ctx->task;
    1493                 :     708280 :         struct spdk_scsi_lun *lun = task->lun;
    1494                 :            :         struct spdk_scsi_unmap_bdesc    *desc;
    1495                 :            :         uint64_t offset_blocks;
    1496                 :            :         uint64_t num_blocks;
    1497                 :            : 
    1498                 :     708280 :         desc = &ctx->desc[ctx->current_count];
    1499                 :            : 
    1500                 :     708280 :         offset_blocks = from_be64(&desc->lba);
    1501                 :     708280 :         num_blocks = from_be32(&desc->block_count);
    1502                 :            : 
    1503                 :     708280 :         return spdk_bdev_unmap_blocks(lun->bdev_desc,
    1504                 :            :                                       lun->io_channel,
    1505                 :            :                                       offset_blocks,
    1506                 :            :                                       num_blocks,
    1507                 :            :                                       bdev_scsi_task_complete_split_cmd,
    1508                 :            :                                       ctx);
    1509                 :            : }
    1510                 :            : 
    1511                 :            : static int
    1512                 :     670564 : bdev_scsi_unmap(struct spdk_bdev *bdev, struct spdk_scsi_task *task)
    1513                 :            : {
    1514                 :            :         struct spdk_bdev_scsi_split_ctx *ctx;
    1515                 :            :         uint8_t                         *data;
    1516                 :     670564 :         int                             desc_count = -1;
    1517                 :         45 :         int                             data_len;
    1518                 :            : 
    1519         [ -  + ]:     670564 :         assert(task->status == SPDK_SCSI_STATUS_GOOD);
    1520                 :            : 
    1521                 :     670564 :         ctx = calloc(1, sizeof(*ctx));
    1522         [ -  + ]:     670564 :         if (!ctx) {
    1523                 :          0 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1524                 :            :                                           SPDK_SCSI_SENSE_NO_SENSE,
    1525                 :            :                                           SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
    1526                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1527                 :          0 :                 return SPDK_SCSI_TASK_COMPLETE;
    1528                 :            :         }
    1529                 :            : 
    1530                 :     670564 :         ctx->task = task;
    1531                 :     670564 :         ctx->current_count = 0;
    1532                 :     670564 :         ctx->outstanding_count = 0;
    1533                 :     670564 :         ctx->fn = _bdev_scsi_unmap;
    1534                 :            : 
    1535         [ +  - ]:     670564 :         if (task->iovcnt == 1) {
    1536                 :     670564 :                 data = (uint8_t *)task->iovs[0].iov_base;
    1537                 :     670564 :                 data_len = task->iovs[0].iov_len;
    1538                 :     670564 :                 desc_count = __copy_desc(ctx, data, data_len);
    1539                 :            :         } else {
    1540                 :          0 :                 data = spdk_scsi_task_gather_data(task, &data_len);
    1541         [ #  # ]:          0 :                 if (data) {
    1542                 :          0 :                         desc_count = __copy_desc(ctx, data, data_len);
    1543                 :          0 :                         free(data);
    1544                 :            :                 }
    1545                 :            :         }
    1546                 :            : 
    1547         [ +  - ]:     670564 :         if (desc_count > 0) {
    1548                 :     670564 :                 ctx->remaining_count = desc_count;
    1549                 :     670564 :                 return bdev_scsi_split(ctx);
    1550                 :            :         }
    1551                 :            : 
    1552         [ #  # ]:          0 :         if (desc_count < 0) {
    1553                 :          0 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1554                 :            :                                           SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
    1555                 :            :                                           SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
    1556                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1557                 :            :         }
    1558                 :            : 
    1559                 :          0 :         free(ctx);
    1560                 :          0 :         return SPDK_SCSI_TASK_COMPLETE;
    1561                 :            : }
    1562                 :            : 
    1563                 :            : static int
    1564                 :     726804 : _bdev_scsi_write_same(struct spdk_bdev_scsi_split_ctx *ctx)
    1565                 :            : {
    1566                 :     726804 :         struct spdk_scsi_task *task = ctx->task;
    1567                 :     726804 :         struct spdk_scsi_lun *lun = task->lun;
    1568                 :            :         uint64_t offset_blocks;
    1569                 :            : 
    1570                 :     726804 :         offset_blocks = ctx->start_offset_blocks + ctx->current_count;
    1571                 :     726804 :         return spdk_bdev_writev_blocks(lun->bdev_desc, lun->io_channel, task->iovs, task->iovcnt,
    1572                 :            :                                        offset_blocks, 1, bdev_scsi_task_complete_split_cmd, ctx);
    1573                 :            : }
    1574                 :            : 
    1575                 :            : static int
    1576                 :        516 : bdev_scsi_write_same(struct spdk_bdev *bdev, struct spdk_bdev_desc *bdev_desc,
    1577                 :            :                      struct spdk_io_channel *bdev_ch, struct spdk_scsi_task *task,
    1578                 :            :                      uint64_t lba, uint32_t xfer_len, uint8_t flags)
    1579                 :            : {
    1580                 :            :         struct spdk_bdev_scsi_split_ctx *ctx;
    1581                 :         92 :         uint64_t bdev_num_blocks, offset_blocks, num_blocks;
    1582                 :            :         uint32_t max_xfer_len, block_size;
    1583                 :        516 :         int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
    1584                 :            : 
    1585                 :        516 :         task->data_transferred = 0;
    1586                 :            : 
    1587         [ -  + ]:        516 :         if (spdk_unlikely(task->dxfer_dir != SPDK_SCSI_DIR_TO_DEV)) {
    1588                 :          0 :                 SPDK_ERRLOG("Incorrect data direction\n");
    1589                 :          0 :                 goto check_condition;
    1590                 :            :         }
    1591                 :            : 
    1592                 :        516 :         block_size = spdk_bdev_get_data_block_size(bdev);
    1593         [ -  + ]:        516 :         if (spdk_unlikely(task->transfer_len != block_size)) {
    1594                 :          0 :                 SPDK_ERRLOG("Incorrect data length(%d), a single logical block(%d) is required\n",
    1595                 :            :                             task->transfer_len, block_size);
    1596                 :          0 :                 goto check_condition;
    1597                 :            :         }
    1598                 :            : 
    1599         [ -  + ]:        516 :         if (spdk_unlikely(xfer_len == 0)) {
    1600                 :          0 :                 task->status = SPDK_SCSI_STATUS_GOOD;
    1601                 :          0 :                 return SPDK_SCSI_TASK_COMPLETE;
    1602                 :            :         }
    1603                 :            : 
    1604                 :        516 :         bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
    1605   [ +  -  -  + ]:        516 :         if (spdk_unlikely(bdev_num_blocks <= lba || bdev_num_blocks - lba < xfer_len)) {
    1606   [ #  #  #  # ]:          0 :                 SPDK_DEBUGLOG(scsi, "end of media\n");
    1607                 :          0 :                 sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
    1608                 :          0 :                 asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
    1609                 :          0 :                 goto check_condition;
    1610                 :            :         }
    1611                 :            : 
    1612                 :            :         /* see MAXIMUM WRITE SAME LENGTH of SPDK_SPC_VPD_BLOCK_LIMITS */
    1613         [ -  + ]:        516 :         max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
    1614         [ -  + ]:        516 :         if (spdk_unlikely(xfer_len > max_xfer_len)) {
    1615                 :          0 :                 SPDK_ERRLOG("xfer_len %"PRIu32 " > maximum transfer length %" PRIu32 "\n",
    1616                 :            :                             xfer_len, max_xfer_len);
    1617                 :          0 :                 sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
    1618                 :          0 :                 asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
    1619                 :          0 :                 goto check_condition;
    1620                 :            :         }
    1621                 :            : 
    1622         [ -  + ]:        516 :         if (_bytes_to_blocks(block_size, task->offset, &offset_blocks,
    1623                 :        516 :                              (uint64_t)task->length * xfer_len,
    1624                 :            :                              &num_blocks) != 0) {
    1625                 :          0 :                 SPDK_ERRLOG("task's offset %" PRIu64 " or length %" PRIu32 " is not block multiple\n",
    1626                 :            :                             task->offset, task->length);
    1627                 :          0 :                 goto check_condition;
    1628                 :            :         }
    1629                 :            : 
    1630                 :        516 :         offset_blocks += lba;
    1631   [ -  +  -  + ]:        516 :         SPDK_DEBUGLOG(scsi, "Writesame: lba=%"PRIu64", len=%"PRIu64"\n",
    1632                 :            :                       offset_blocks, num_blocks);
    1633                 :            : 
    1634                 :        516 :         ctx = calloc(1, sizeof(*ctx));
    1635         [ -  + ]:        516 :         if (!ctx) {
    1636                 :          0 :                 SPDK_ERRLOG("No enough memory on SCSI WRITE SAME\n");
    1637                 :          0 :                 goto check_condition;
    1638                 :            :         }
    1639                 :            : 
    1640                 :        516 :         ctx->task = task;
    1641                 :        516 :         ctx->start_offset_blocks = offset_blocks;
    1642                 :        516 :         ctx->current_count = 0;
    1643                 :        516 :         ctx->outstanding_count = 0;
    1644                 :        516 :         ctx->remaining_count = xfer_len;
    1645                 :        516 :         ctx->fn = _bdev_scsi_write_same;
    1646                 :            : 
    1647                 :        516 :         task->data_transferred = task->length;
    1648                 :            : 
    1649                 :        516 :         return bdev_scsi_split(ctx);
    1650                 :            : 
    1651                 :          0 : check_condition:
    1652                 :          0 :         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1653                 :            :                                   sk, asc, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1654                 :          0 :         return SPDK_SCSI_TASK_COMPLETE;
    1655                 :            : }
    1656                 :            : 
    1657                 :            : static int
    1658                 :   29927759 : bdev_scsi_process_block(struct spdk_scsi_task *task)
    1659                 :            : {
    1660                 :   29927759 :         struct spdk_scsi_lun *lun = task->lun;
    1661                 :   29927759 :         struct spdk_bdev *bdev = lun->bdev;
    1662                 :            :         uint64_t lba;
    1663                 :            :         uint32_t xfer_len;
    1664                 :   29927759 :         uint32_t len = 0;
    1665                 :   29927759 :         uint8_t *cdb = task->cdb;
    1666                 :            : 
    1667                 :            :         /* XXX: We need to support FUA bit for writes! */
    1668   [ -  +  -  +  :   29927759 :         switch (cdb[0]) {
          -  +  +  +  +  
                +  -  + ]
    1669                 :          0 :         case SPDK_SBC_READ_6:
    1670                 :            :         case SPDK_SBC_WRITE_6:
    1671                 :          0 :                 lba = (uint64_t)cdb[1] << 16;
    1672                 :          0 :                 lba |= (uint64_t)cdb[2] << 8;
    1673                 :          0 :                 lba |= (uint64_t)cdb[3];
    1674                 :          0 :                 xfer_len = cdb[4];
    1675         [ #  # ]:          0 :                 if (xfer_len == 0) {
    1676                 :          0 :                         xfer_len = 256;
    1677                 :            :                 }
    1678                 :          0 :                 return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
    1679                 :            :                                            task, lba, xfer_len,
    1680                 :          0 :                                            cdb[0] == SPDK_SBC_READ_6, false);
    1681                 :            : 
    1682                 :   27076197 :         case SPDK_SBC_READ_10:
    1683                 :            :         case SPDK_SBC_WRITE_10:
    1684                 :   27076197 :                 lba = from_be32(&cdb[2]);
    1685                 :   27076197 :                 xfer_len = from_be16(&cdb[7]);
    1686                 :   27076197 :                 return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
    1687                 :            :                                            task, lba, xfer_len,
    1688                 :   27076197 :                                            cdb[0] == SPDK_SBC_READ_10, false);
    1689                 :            : 
    1690                 :          0 :         case SPDK_SBC_READ_12:
    1691                 :            :         case SPDK_SBC_WRITE_12:
    1692                 :          0 :                 lba = from_be32(&cdb[2]);
    1693                 :          0 :                 xfer_len = from_be32(&cdb[6]);
    1694                 :          0 :                 return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
    1695                 :            :                                            task, lba, xfer_len,
    1696                 :          0 :                                            cdb[0] == SPDK_SBC_READ_12, false);
    1697                 :    1008732 :         case SPDK_SBC_READ_16:
    1698                 :            :         case SPDK_SBC_WRITE_16:
    1699                 :    1008732 :                 lba = from_be64(&cdb[2]);
    1700                 :    1008732 :                 xfer_len = from_be32(&cdb[10]);
    1701                 :    1008732 :                 return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
    1702                 :            :                                            task, lba, xfer_len,
    1703                 :    1008732 :                                            cdb[0] == SPDK_SBC_READ_16, false);
    1704                 :            : 
    1705                 :          0 :         case SPDK_SBC_COMPARE_AND_WRITE: {
    1706                 :          0 :                 uint32_t num_blocks = cdb[13];
    1707                 :          0 :                 uint8_t wrprotect = (cdb[1] >> 5) & 0x07;
    1708                 :          0 :                 bool dpo = cdb[1] & 0x10;
    1709                 :          0 :                 bool fua = cdb[1] & 0x08;
    1710                 :            : 
    1711                 :          0 :                 lba = from_be64(&cdb[2]);
    1712                 :            : 
    1713   [ #  #  #  #  :          0 :                 if (dpo || fua || wrprotect) {
                   #  # ]
    1714                 :          0 :                         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1715                 :            :                                                   SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
    1716                 :            :                                                   SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
    1717                 :            :                                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1718                 :          0 :                         SPDK_ERRLOG("Invalid Task\n");
    1719                 :          0 :                         return SPDK_SCSI_TASK_COMPLETE;
    1720                 :            :                 }
    1721                 :            : 
    1722         [ #  # ]:          0 :                 if (num_blocks != 1)  {
    1723                 :          0 :                         SPDK_ERRLOG("Invalid CAW block count, request block count is %u, limit is : 1\n",
    1724                 :            :                                     num_blocks);
    1725                 :          0 :                         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1726                 :            :                                                   SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
    1727                 :            :                                                   SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
    1728                 :            :                                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1729                 :          0 :                         return SPDK_SCSI_TASK_COMPLETE;
    1730                 :            :                 }
    1731                 :            : 
    1732                 :          0 :                 return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
    1733                 :            :                                            task, lba, num_blocks, false, true);
    1734                 :            :         }
    1735                 :            : 
    1736                 :        185 :         case SPDK_SBC_READ_CAPACITY_10: {
    1737                 :        185 :                 uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
    1738                 :         16 :                 uint8_t buffer[8];
    1739                 :            : 
    1740         [ -  + ]:        185 :                 if (num_blocks - 1 > 0xffffffffULL) {
    1741         [ #  # ]:          0 :                         memset(buffer, 0xff, 4);
    1742                 :            :                 } else {
    1743                 :        185 :                         to_be32(buffer, num_blocks - 1);
    1744                 :            :                 }
    1745                 :        185 :                 to_be32(&buffer[4], spdk_bdev_get_data_block_size(bdev));
    1746                 :            : 
    1747                 :        185 :                 len = spdk_min(task->length, sizeof(buffer));
    1748         [ -  + ]:        185 :                 if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
    1749                 :          0 :                         break;
    1750                 :            :                 }
    1751                 :            : 
    1752                 :        185 :                 task->data_transferred = len;
    1753                 :        185 :                 task->status = SPDK_SCSI_STATUS_GOOD;
    1754                 :        185 :                 break;
    1755                 :            :         }
    1756                 :            : 
    1757                 :       2001 :         case SPDK_SPC_SERVICE_ACTION_IN_16:
    1758         [ +  - ]:       2001 :                 switch (cdb[1] & 0x1f) { /* SERVICE ACTION */
    1759                 :       2001 :                 case SPDK_SBC_SAI_READ_CAPACITY_16: {
    1760                 :       2001 :                         uint8_t buffer[32] = {0};
    1761                 :            :                         uint32_t lbppb, lbppbe;
    1762                 :            : 
    1763                 :       2001 :                         to_be64(&buffer[0], spdk_bdev_get_num_blocks(bdev) - 1);
    1764                 :       2001 :                         to_be32(&buffer[8], spdk_bdev_get_data_block_size(bdev));
    1765         [ -  + ]:       2001 :                         lbppb = spdk_bdev_get_physical_block_size(bdev) / spdk_bdev_get_data_block_size(bdev);
    1766                 :       2001 :                         lbppbe = spdk_u32log2(lbppb);
    1767         [ -  + ]:       2001 :                         if (lbppbe > 0xf) {
    1768                 :          0 :                                 SPDK_ERRLOG("lbppbe(0x%x) > 0xf\n", lbppbe);
    1769                 :            :                         } else {
    1770                 :       2001 :                                 buffer[13] = lbppbe;
    1771                 :            :                         }
    1772                 :            :                         /*
    1773                 :            :                          * Set the TPE bit to 1 to indicate thin provisioning.
    1774                 :            :                          * The position of TPE bit is the 7th bit in 14th byte
    1775                 :            :                          * in READ CAPACITY (16) parameter data.
    1776                 :            :                          */
    1777         [ +  + ]:       2001 :                         if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
    1778                 :       1991 :                                 buffer[14] |= 1 << 7;
    1779                 :            :                         }
    1780                 :            : 
    1781         [ -  + ]:       2001 :                         len = spdk_min(from_be32(&cdb[10]), sizeof(buffer));
    1782         [ -  + ]:       2001 :                         if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
    1783                 :          0 :                                 break;
    1784                 :            :                         }
    1785                 :            : 
    1786                 :       2001 :                         task->data_transferred = len;
    1787                 :       2001 :                         task->status = SPDK_SCSI_STATUS_GOOD;
    1788                 :       2001 :                         break;
    1789                 :            :                 }
    1790                 :            : 
    1791                 :          0 :                 default:
    1792                 :          0 :                         return SPDK_SCSI_TASK_UNKNOWN;
    1793                 :            :                 }
    1794                 :       1854 :                 break;
    1795                 :            : 
    1796                 :    1147083 :         case SPDK_SBC_SYNCHRONIZE_CACHE_10:
    1797                 :            :         case SPDK_SBC_SYNCHRONIZE_CACHE_16:
    1798         [ +  + ]:    1147083 :                 if (cdb[0] == SPDK_SBC_SYNCHRONIZE_CACHE_10) {
    1799                 :     706999 :                         lba = from_be32(&cdb[2]);
    1800                 :     706999 :                         len = from_be16(&cdb[7]);
    1801                 :            :                 } else {
    1802                 :     440084 :                         lba = from_be64(&cdb[2]);
    1803                 :     440084 :                         len = from_be32(&cdb[10]);
    1804                 :            :                 }
    1805                 :            : 
    1806         [ +  + ]:    1147083 :                 if (len == 0) {
    1807                 :     706999 :                         len = spdk_bdev_get_num_blocks(bdev) - lba;
    1808                 :            :                 }
    1809                 :            : 
    1810                 :    1147083 :                 return bdev_scsi_sync(bdev, lun->bdev_desc, lun->io_channel, task, lba, len);
    1811                 :            :                 break;
    1812                 :            : 
    1813                 :     670564 :         case SPDK_SBC_UNMAP:
    1814                 :     670564 :                 return bdev_scsi_unmap(bdev, task);
    1815                 :            : 
    1816                 :        516 :         case SPDK_SBC_WRITE_SAME_10:
    1817                 :        516 :                 lba = from_be32(&cdb[2]);
    1818                 :        516 :                 xfer_len = from_be16(&cdb[7]);
    1819                 :        516 :                 return bdev_scsi_write_same(bdev, lun->bdev_desc, lun->io_channel,
    1820                 :        516 :                                             task, lba, xfer_len, cdb[1]);
    1821                 :            : 
    1822                 :          0 :         case SPDK_SBC_WRITE_SAME_16:
    1823                 :          0 :                 lba = from_be64(&cdb[2]);
    1824                 :          0 :                 xfer_len = from_be32(&cdb[10]);
    1825                 :          0 :                 return bdev_scsi_write_same(bdev, lun->bdev_desc, lun->io_channel,
    1826                 :          0 :                                             task, lba, xfer_len, cdb[1]);
    1827                 :            : 
    1828                 :            : 
    1829                 :      22481 :         default:
    1830                 :      22481 :                 return SPDK_SCSI_TASK_UNKNOWN;
    1831                 :            :         }
    1832                 :            : 
    1833                 :       2186 :         return SPDK_SCSI_TASK_COMPLETE;
    1834                 :            : }
    1835                 :            : 
    1836                 :            : static void
    1837                 :     125972 : bdev_scsi_process_block_resubmit(void *arg)
    1838                 :            : {
    1839                 :     125972 :         struct spdk_scsi_task *task = arg;
    1840                 :            : 
    1841                 :     125972 :         bdev_scsi_process_block(task);
    1842                 :     125972 : }
    1843                 :            : 
    1844                 :            : static int
    1845                 :        193 : bdev_scsi_check_len(struct spdk_scsi_task *task, int len, int min_len)
    1846                 :            : {
    1847         [ +  - ]:        193 :         if (len >= min_len) {
    1848                 :        193 :                 return 0;
    1849                 :            :         }
    1850                 :            : 
    1851                 :            :         /* INVALID FIELD IN CDB */
    1852                 :          0 :         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1853                 :            :                                   SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
    1854                 :            :                                   SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
    1855                 :            :                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1856                 :          0 :         return -1;
    1857                 :            : }
    1858                 :            : 
    1859                 :            : static int
    1860                 :      22481 : bdev_scsi_process_primary(struct spdk_scsi_task *task)
    1861                 :            : {
    1862                 :      22481 :         struct spdk_scsi_lun *lun = task->lun;
    1863                 :      22481 :         struct spdk_bdev *bdev = lun->bdev;
    1864                 :      22481 :         int alloc_len = -1;
    1865                 :      22481 :         int data_len = -1;
    1866                 :      22481 :         uint8_t *cdb = task->cdb;
    1867                 :      22481 :         uint8_t *data = NULL;
    1868                 :      22481 :         int rc = 0;
    1869                 :      22481 :         int pllen, md = 0;
    1870                 :            :         int llba;
    1871                 :            :         int dbd, pc, page, subpage;
    1872                 :      22481 :         int cmd_parsed = 0;
    1873                 :            : 
    1874   [ +  +  +  +  :      22481 :         switch (cdb[0]) {
          +  -  +  -  +  
          -  -  -  -  -  
                      + ]
    1875                 :      13754 :         case SPDK_SPC_INQUIRY:
    1876                 :      13754 :                 alloc_len = from_be16(&cdb[3]);
    1877                 :      13754 :                 data_len = spdk_max(4096, alloc_len);
    1878                 :      13754 :                 data = calloc(1, data_len);
    1879         [ -  + ]:      13754 :                 assert(data != NULL);
    1880                 :      13754 :                 rc = bdev_scsi_inquiry(bdev, task, cdb, data, data_len);
    1881                 :      13754 :                 data_len = spdk_min(rc, data_len);
    1882         [ +  + ]:      13754 :                 if (rc < 0) {
    1883                 :       1653 :                         break;
    1884                 :            :                 }
    1885                 :            : 
    1886   [ -  +  -  + ]:      12101 :                 SPDK_LOGDUMP(scsi, "INQUIRY", data, data_len);
    1887                 :      12101 :                 break;
    1888                 :            : 
    1889                 :        181 :         case SPDK_SPC_REPORT_LUNS: {
    1890                 :            :                 int sel;
    1891                 :            : 
    1892                 :        181 :                 sel = cdb[2];
    1893   [ -  +  -  + ]:        181 :                 SPDK_DEBUGLOG(scsi, "sel=%x\n", sel);
    1894                 :            : 
    1895                 :        181 :                 alloc_len = from_be32(&cdb[6]);
    1896                 :        181 :                 rc = bdev_scsi_check_len(task, alloc_len, 16);
    1897         [ -  + ]:        181 :                 if (rc < 0) {
    1898                 :          0 :                         break;
    1899                 :            :                 }
    1900                 :            : 
    1901                 :        181 :                 data_len = spdk_max(4096, alloc_len);
    1902                 :        181 :                 data = calloc(1, data_len);
    1903         [ -  + ]:        181 :                 assert(data != NULL);
    1904                 :        181 :                 rc = bdev_scsi_report_luns(task->lun, sel, data, data_len);
    1905                 :        181 :                 data_len = rc;
    1906         [ -  + ]:        181 :                 if (rc < 0) {
    1907                 :          0 :                         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1908                 :            :                                                   SPDK_SCSI_SENSE_NO_SENSE,
    1909                 :            :                                                   SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
    1910                 :            :                                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1911                 :          0 :                         break;
    1912                 :            :                 }
    1913                 :            : 
    1914   [ -  +  -  + ]:        181 :                 SPDK_LOGDUMP(scsi, "REPORT LUNS", data, data_len);
    1915                 :        181 :                 break;
    1916                 :            :         }
    1917                 :            : 
    1918                 :         12 :         case SPDK_SPC_MODE_SELECT_6:
    1919                 :            :         case SPDK_SPC_MODE_SELECT_10:
    1920         [ +  - ]:         12 :                 if (cdb[0] == SPDK_SPC_MODE_SELECT_6) {
    1921                 :            :                         /* MODE_SELECT(6) must have at least a 4 byte header. */
    1922                 :         12 :                         md = 4;
    1923                 :         12 :                         pllen = cdb[4];
    1924                 :            :                 } else {
    1925                 :            :                         /* MODE_SELECT(10) must have at least an 8 byte header. */
    1926                 :          0 :                         md = 8;
    1927                 :          0 :                         pllen = from_be16(&cdb[7]);
    1928                 :            :                 }
    1929                 :            : 
    1930         [ +  + ]:         12 :                 if (pllen == 0) {
    1931                 :          6 :                         break;
    1932                 :            :                 }
    1933                 :            : 
    1934                 :          6 :                 rc = bdev_scsi_check_len(task, pllen, md);
    1935         [ -  + ]:          6 :                 if (rc < 0) {
    1936                 :          0 :                         break;
    1937                 :            :                 }
    1938                 :            : 
    1939                 :          6 :                 data = spdk_scsi_task_gather_data(task, &rc);
    1940         [ -  + ]:          6 :                 if (rc < 0) {
    1941                 :          0 :                         break;
    1942                 :            :                 }
    1943                 :          6 :                 data_len = rc;
    1944                 :            : 
    1945                 :          6 :                 rc = bdev_scsi_check_len(task, data_len, spdk_max(pllen, md));
    1946         [ -  + ]:          6 :                 if (rc < 0) {
    1947                 :          0 :                         break;
    1948                 :            :                 }
    1949                 :            : 
    1950                 :          6 :                 rc = pllen;
    1951                 :          6 :                 data_len = 0;
    1952                 :          6 :                 break;
    1953                 :            : 
    1954                 :       5977 :         case SPDK_SPC_MODE_SENSE_6:
    1955                 :       5977 :                 alloc_len = cdb[4];
    1956                 :       5977 :                 md = 6;
    1957                 :            :         /* FALLTHROUGH */
    1958                 :       5983 :         case SPDK_SPC_MODE_SENSE_10:
    1959                 :       5983 :                 llba = 0;
    1960                 :            : 
    1961         [ +  + ]:       5983 :                 if (md == 0) {
    1962                 :          6 :                         alloc_len = from_be16(&cdb[7]);
    1963                 :          6 :                         llba = !!(cdb[1] & 0x10);
    1964                 :          6 :                         md = 10;
    1965                 :            :                 }
    1966                 :            : 
    1967                 :       5983 :                 dbd = !!(cdb[1] & 0x8);
    1968                 :       5983 :                 pc = (cdb[2] & 0xc0) >> 6;
    1969                 :       5983 :                 page = cdb[2] & 0x3f;
    1970                 :       5983 :                 subpage = cdb[3];
    1971                 :            : 
    1972                 :            :                 /* First call with no buffer to discover needed buffer size */
    1973                 :       5983 :                 rc = bdev_scsi_mode_sense(bdev, md,
    1974                 :            :                                           cdb, dbd, llba, pc,
    1975                 :            :                                           page, subpage,
    1976                 :            :                                           NULL, task);
    1977         [ -  + ]:       5983 :                 if (rc < 0) {
    1978                 :          0 :                         break;
    1979                 :            :                 }
    1980                 :            : 
    1981                 :       5983 :                 data_len = rc;
    1982                 :       5983 :                 data = calloc(1, data_len);
    1983         [ -  + ]:       5983 :                 assert(data != NULL);
    1984                 :            : 
    1985                 :            :                 /* First call with no buffer to discover needed buffer size */
    1986                 :       5983 :                 rc = bdev_scsi_mode_sense(bdev, md,
    1987                 :            :                                           cdb, dbd, llba, pc,
    1988                 :            :                                           page, subpage,
    1989                 :            :                                           data, task);
    1990         [ -  + ]:       5983 :                 if (rc < 0) {
    1991                 :            :                         /* INVALID FIELD IN CDB */
    1992                 :          0 :                         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    1993                 :            :                                                   SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
    1994                 :            :                                                   SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
    1995                 :            :                                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1996                 :          0 :                         break;
    1997                 :            :                 }
    1998                 :       5983 :                 break;
    1999                 :            : 
    2000                 :          0 :         case SPDK_SPC_REQUEST_SENSE: {
    2001                 :            :                 int desc;
    2002                 :            :                 int sk, asc, ascq;
    2003                 :            : 
    2004                 :          0 :                 desc = cdb[1] & 0x1;
    2005         [ #  # ]:          0 :                 if (desc != 0) {
    2006                 :            :                         /* INVALID FIELD IN CDB */
    2007                 :          0 :                         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    2008                 :            :                                                   SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
    2009                 :            :                                                   SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
    2010                 :            :                                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    2011                 :          0 :                         break;
    2012                 :            :                 }
    2013                 :            : 
    2014                 :          0 :                 alloc_len = cdb[4];
    2015                 :            : 
    2016                 :            :                 /* NO ADDITIONAL SENSE INFORMATION */
    2017                 :          0 :                 sk = SPDK_SCSI_SENSE_NO_SENSE;
    2018                 :          0 :                 asc = 0x00;
    2019                 :          0 :                 ascq = 0x00;
    2020                 :            : 
    2021                 :          0 :                 spdk_scsi_task_build_sense_data(task, sk, asc, ascq);
    2022                 :            : 
    2023                 :          0 :                 data_len = task->sense_data_len;
    2024                 :          0 :                 data = calloc(1, data_len);
    2025         [ #  # ]:          0 :                 assert(data != NULL);
    2026   [ #  #  #  # ]:          0 :                 memcpy(data, task->sense_data, data_len);
    2027                 :          0 :                 break;
    2028                 :            :         }
    2029                 :            : 
    2030                 :          1 :         case SPDK_SPC_LOG_SELECT:
    2031   [ -  +  -  + ]:          1 :                 SPDK_DEBUGLOG(scsi, "LOG_SELECT\n");
    2032                 :          1 :                 cmd_parsed = 1;
    2033                 :            :         /* FALLTHROUGH */
    2034                 :          1 :         case SPDK_SPC_LOG_SENSE:
    2035         [ -  + ]:          1 :                 if (!cmd_parsed) {
    2036   [ #  #  #  # ]:          0 :                         SPDK_DEBUGLOG(scsi, "LOG_SENSE\n");
    2037                 :            :                 }
    2038                 :            : 
    2039                 :            :                 /* INVALID COMMAND OPERATION CODE */
    2040                 :          1 :                 spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    2041                 :            :                                           SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
    2042                 :            :                                           SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
    2043                 :            :                                           SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    2044                 :          1 :                 rc = -1;
    2045                 :          1 :                 break;
    2046                 :            : 
    2047                 :       2195 :         case SPDK_SPC_TEST_UNIT_READY:
    2048   [ -  +  -  + ]:       2195 :                 SPDK_DEBUGLOG(scsi, "TEST_UNIT_READY\n");
    2049                 :       2195 :                 cmd_parsed = 1;
    2050                 :            :         /* FALLTHROUGH */
    2051                 :       2195 :         case SPDK_SBC_START_STOP_UNIT:
    2052         [ -  + ]:       2195 :                 if (!cmd_parsed) {
    2053   [ #  #  #  # ]:          0 :                         SPDK_DEBUGLOG(scsi, "START_STOP_UNIT\n");
    2054                 :            :                 }
    2055                 :            : 
    2056                 :       2195 :                 rc = 0;
    2057                 :       2195 :                 break;
    2058                 :            : 
    2059                 :          0 :         case SPDK_SPC_PERSISTENT_RESERVE_OUT:
    2060                 :          0 :                 pllen = from_be32(&cdb[5]);
    2061                 :          0 :                 rc = bdev_scsi_check_len(task, pllen, 24);
    2062         [ #  # ]:          0 :                 if (rc < 0) {
    2063                 :          0 :                         break;
    2064                 :            :                 }
    2065                 :            : 
    2066                 :          0 :                 data = spdk_scsi_task_gather_data(task, &rc);
    2067         [ #  # ]:          0 :                 if (rc < 0) {
    2068                 :          0 :                         break;
    2069                 :            :                 }
    2070                 :          0 :                 data_len = rc;
    2071         [ #  # ]:          0 :                 if (data_len < 24) {
    2072                 :          0 :                         rc = -1;
    2073                 :          0 :                         break;
    2074                 :            :                 }
    2075                 :            : 
    2076                 :          0 :                 rc = scsi_pr_out(task, cdb, data, data_len);
    2077         [ #  # ]:          0 :                 if (rc < 0) {
    2078                 :          0 :                         break;
    2079                 :            :                 }
    2080                 :          0 :                 rc = pllen;
    2081                 :          0 :                 data_len = 0;
    2082                 :          0 :                 break;
    2083                 :            : 
    2084                 :          0 :         case SPDK_SPC_PERSISTENT_RESERVE_IN:
    2085                 :          0 :                 alloc_len = from_be16(&cdb[7]);
    2086                 :          0 :                 data_len = alloc_len;
    2087                 :          0 :                 data = calloc(1, data_len);
    2088         [ #  # ]:          0 :                 assert(data != NULL);
    2089                 :          0 :                 rc = scsi_pr_in(task, cdb, data, data_len);
    2090                 :          0 :                 break;
    2091                 :            : 
    2092                 :          0 :         case SPDK_SPC2_RESERVE_6:
    2093                 :            :         case SPDK_SPC2_RESERVE_10:
    2094                 :          0 :                 rc = scsi2_reserve(task, cdb);
    2095         [ #  # ]:          0 :                 if (rc == 0) {
    2096         [ #  # ]:          0 :                         if (cdb[0] == SPDK_SPC2_RESERVE_10) {
    2097                 :          0 :                                 rc = from_be16(&cdb[7]);
    2098                 :            :                         }
    2099                 :          0 :                         data_len = 0;
    2100                 :            :                 }
    2101                 :          0 :                 break;
    2102                 :            : 
    2103                 :          0 :         case SPDK_SPC2_RELEASE_6:
    2104                 :            :         case SPDK_SPC2_RELEASE_10:
    2105                 :          0 :                 rc = scsi2_release(task);
    2106                 :          0 :                 break;
    2107                 :            : 
    2108                 :        355 :         default:
    2109                 :        355 :                 return SPDK_SCSI_TASK_UNKNOWN;
    2110                 :            :         }
    2111                 :            : 
    2112   [ +  +  +  + ]:      22126 :         if (rc >= 0 && data_len > 0) {
    2113         [ -  + ]:      18265 :                 assert(alloc_len >= 0);
    2114                 :      18265 :                 spdk_scsi_task_scatter_data(task, data, spdk_min(alloc_len, data_len));
    2115                 :      18265 :                 rc = spdk_min(data_len, alloc_len);
    2116                 :            :         }
    2117                 :            : 
    2118         [ +  + ]:      22126 :         if (rc >= 0) {
    2119                 :      20472 :                 task->data_transferred = rc;
    2120                 :      20472 :                 task->status = SPDK_SCSI_STATUS_GOOD;
    2121                 :            :         }
    2122                 :            : 
    2123         [ +  + ]:      22126 :         if (data) {
    2124                 :      19924 :                 free(data);
    2125                 :            :         }
    2126                 :            : 
    2127                 :      22126 :         return SPDK_SCSI_TASK_COMPLETE;
    2128                 :            : }
    2129                 :            : 
    2130                 :            : int
    2131                 :   29801787 : bdev_scsi_execute(struct spdk_scsi_task *task)
    2132                 :            : {
    2133                 :            :         int rc;
    2134                 :            : 
    2135         [ +  + ]:   29801787 :         if ((rc = bdev_scsi_process_block(task)) == SPDK_SCSI_TASK_UNKNOWN) {
    2136         [ +  + ]:      22481 :                 if ((rc = bdev_scsi_process_primary(task)) == SPDK_SCSI_TASK_UNKNOWN) {
    2137   [ -  +  -  + ]:        355 :                         SPDK_DEBUGLOG(scsi, "unsupported SCSI OP=0x%x\n", task->cdb[0]);
    2138                 :            :                         /* INVALID COMMAND OPERATION CODE */
    2139                 :        355 :                         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
    2140                 :            :                                                   SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
    2141                 :            :                                                   SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
    2142                 :            :                                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    2143                 :        355 :                         return SPDK_SCSI_TASK_COMPLETE;
    2144                 :            :                 }
    2145                 :            :         }
    2146                 :            : 
    2147                 :   29801432 :         return rc;
    2148                 :            : }
    2149                 :            : 
    2150                 :            : static void
    2151                 :          0 : bdev_scsi_reset_resubmit(void *arg)
    2152                 :            : {
    2153                 :          0 :         struct spdk_scsi_task *task = arg;
    2154                 :            : 
    2155                 :          0 :         bdev_scsi_reset(task);
    2156                 :          0 : }
    2157                 :            : 
    2158                 :            : void
    2159                 :         10 : bdev_scsi_reset(struct spdk_scsi_task *task)
    2160                 :            : {
    2161                 :         10 :         struct spdk_scsi_lun *lun = task->lun;
    2162                 :            :         int rc;
    2163                 :            : 
    2164                 :         10 :         rc = spdk_bdev_reset(lun->bdev_desc, lun->io_channel, bdev_scsi_task_complete_reset,
    2165                 :            :                              task);
    2166         [ -  + ]:         10 :         if (rc == -ENOMEM) {
    2167                 :          0 :                 bdev_scsi_queue_io(task, bdev_scsi_reset_resubmit, task);
    2168                 :            :         }
    2169                 :         10 : }
    2170                 :            : 
    2171                 :            : bool
    2172                 :   23383200 : bdev_scsi_get_dif_ctx(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
    2173                 :            :                       struct spdk_dif_ctx *dif_ctx)
    2174                 :            : {
    2175                 :   23383200 :         uint32_t ref_tag = 0, dif_check_flags = 0, data_offset;
    2176                 :            :         uint8_t *cdb;
    2177                 :            :         int rc;
    2178                 :         15 :         struct spdk_dif_ctx_init_ext_opts dif_opts;
    2179                 :            : 
    2180         [ +  + ]:   23383200 :         if (spdk_likely(spdk_bdev_get_md_size(bdev) == 0)) {
    2181                 :   23383182 :                 return false;
    2182                 :            :         }
    2183                 :            : 
    2184                 :         18 :         cdb = task->cdb;
    2185                 :         18 :         data_offset = task->offset;
    2186                 :            : 
    2187                 :            :         /* We use lower 32 bits of LBA as Reference. Tag */
    2188   [ +  +  +  - ]:         18 :         switch (cdb[0]) {
    2189                 :          6 :         case SPDK_SBC_READ_6:
    2190                 :            :         case SPDK_SBC_WRITE_6:
    2191                 :          6 :                 ref_tag = (uint32_t)cdb[1] << 16;
    2192                 :          6 :                 ref_tag |= (uint32_t)cdb[2] << 8;
    2193                 :          6 :                 ref_tag |= (uint32_t)cdb[3];
    2194                 :          6 :                 break;
    2195                 :          6 :         case SPDK_SBC_READ_10:
    2196                 :            :         case SPDK_SBC_WRITE_10:
    2197                 :            :         case SPDK_SBC_READ_12:
    2198                 :            :         case SPDK_SBC_WRITE_12:
    2199                 :          6 :                 ref_tag = from_be32(&cdb[2]);
    2200                 :          6 :                 break;
    2201                 :          6 :         case SPDK_SBC_READ_16:
    2202                 :            :         case SPDK_SBC_WRITE_16:
    2203                 :          6 :                 ref_tag = (uint32_t)from_be64(&cdb[2]);
    2204                 :          6 :                 break;
    2205                 :          0 :         default:
    2206                 :          0 :                 return false;
    2207                 :            :         }
    2208                 :            : 
    2209         [ -  + ]:         18 :         if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)) {
    2210                 :          0 :                 dif_check_flags |= SPDK_DIF_FLAGS_REFTAG_CHECK;
    2211                 :            :         }
    2212                 :            : 
    2213         [ -  + ]:         18 :         if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)) {
    2214                 :          0 :                 dif_check_flags |= SPDK_DIF_FLAGS_GUARD_CHECK;
    2215                 :            :         }
    2216                 :            : 
    2217                 :         18 :         dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
    2218                 :         18 :         dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
    2219                 :         36 :         rc = spdk_dif_ctx_init(dif_ctx,
    2220                 :            :                                spdk_bdev_get_block_size(bdev),
    2221                 :            :                                spdk_bdev_get_md_size(bdev),
    2222                 :         18 :                                spdk_bdev_is_md_interleaved(bdev),
    2223                 :         18 :                                spdk_bdev_is_dif_head_of_md(bdev),
    2224                 :            :                                spdk_bdev_get_dif_type(bdev),
    2225                 :            :                                dif_check_flags,
    2226                 :            :                                ref_tag, 0, 0, data_offset, 0, &dif_opts);
    2227                 :            : 
    2228                 :         18 :         return (rc == 0) ? true : false;
    2229                 :            : }

Generated by: LCOV version 1.14