LCOV - code coverage report
Current view: top level - lib/scsi - scsi_bdev.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 494 1119 44.1 %
Date: 2024-11-05 10:06:02 Functions: 23 30 76.7 %

          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           0 : bdev_scsi_set_naa_ieee_extended(const char *name, uint8_t *buf)
      33             : {
      34             :         int i;
      35           0 :         uint64_t local_value = 0, id_a, seed = 131;
      36             : 
      37           0 :         for (i = 0; name[i] != '\0'; i++) {
      38           0 :                 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           0 :         id_a = local_value & 0x0000000fff000000ull;
      46           0 :         id_a = id_a << 24;
      47             : 
      48           0 :         local_value &= 0x0000000000ffffffull;
      49             :         /* NAA 02, and 00 03 47 for IEEE Intel */
      50           0 :         local_value |= 0x2000000347000000ull;
      51           0 :         local_value |= id_a;
      52             : 
      53           0 :         to_be64((void *)buf, local_value);
      54           0 : }
      55             : 
      56             : static int
      57           0 : 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           0 :         int hlen, len = 0;
      64             : 
      65           0 :         if (alloc_len < 8) {
      66           0 :                 return -1;
      67             :         }
      68             : 
      69           0 :         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           0 :         memset(data, 0, 4);
      81             : 
      82             :         /* Reserved */
      83           0 :         memset(&data[4], 0, 4);
      84           0 :         hlen = 8;
      85             : 
      86           0 :         dev = lun->dev;
      87             : 
      88           0 :         for (tmp_lun = spdk_scsi_dev_get_first_lun(dev); tmp_lun != NULL;
      89           0 :              tmp_lun = spdk_scsi_dev_get_next_lun(tmp_lun)) {
      90           0 :                 if (alloc_len - (hlen + len) < 8) {
      91           0 :                         return -1;
      92             :                 }
      93             : 
      94           0 :                 fmt_lun = spdk_scsi_lun_id_int_to_fmt(tmp_lun->id);
      95             : 
      96             :                 /* LUN */
      97           0 :                 to_be64(&data[hlen + len], fmt_lun);
      98           0 :                 len += 8;
      99             :         }
     100             : 
     101             :         /* LUN LIST LENGTH */
     102           0 :         to_be32(data, len);
     103             : 
     104           0 :         return hlen + len;
     105             : }
     106             : 
     107             : static int
     108           3 : bdev_scsi_pad_scsi_name(char *dst, const char *name)
     109             : {
     110             :         size_t len;
     111             : 
     112           3 :         len = strlen(name);
     113           3 :         memcpy(dst, name, len);
     114             :         do {
     115           6 :                 dst[len++] = '\0';
     116           6 :         } while (len & 3);
     117             : 
     118           3 :         return len;
     119             : }
     120             : 
     121             : static int
     122         258 : 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         258 :         int hlen = 0, plen, plen2;
     130         258 :         uint16_t len = 0;
     131             :         int pc;
     132             :         int pd;
     133             :         int evpd;
     134             :         int i;
     135         258 :         struct spdk_scsi_cdb_inquiry *inq = (struct spdk_scsi_cdb_inquiry *)cdb;
     136             : 
     137             :         /* standard inquiry command at lease with 36 Bytes */
     138         258 :         if (alloc_len < 0x24) {
     139           0 :                 goto inq_error;
     140             :         }
     141             : 
     142         258 :         lun = task->lun;
     143         258 :         dev = lun->dev;
     144         258 :         port = task->target_port;
     145             : 
     146         258 :         pd = SPDK_SPC_PERIPHERAL_DEVICE_TYPE_DISK;
     147         258 :         pc = inq->page_code;
     148         258 :         evpd = inq->evpd & 0x1;
     149             : 
     150         258 :         if (!evpd && pc) {
     151           1 :                 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           1 :                 return -1;
     156             :         }
     157             : 
     158         257 :         if (evpd) {
     159           0 :                 struct spdk_scsi_vpd_page *vpage = (struct spdk_scsi_vpd_page *)data;
     160             : 
     161             :                 /* PERIPHERAL QUALIFIER(7-5) PERIPHERAL DEVICE TYPE(4-0) */
     162           0 :                 vpage->peripheral_device_type = pd;
     163           0 :                 vpage->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
     164             :                 /* PAGE CODE */
     165           0 :                 vpage->page_code = pc;
     166             : 
     167             :                 /* Vital product data */
     168           0 :                 switch (pc) {
     169           0 :                 case SPDK_SPC_VPD_SUPPORTED_VPD_PAGES:
     170           0 :                         hlen = 4;
     171             : 
     172           0 :                         vpage->params[0] = SPDK_SPC_VPD_SUPPORTED_VPD_PAGES;
     173           0 :                         vpage->params[1] = SPDK_SPC_VPD_UNIT_SERIAL_NUMBER;
     174           0 :                         vpage->params[2] = SPDK_SPC_VPD_DEVICE_IDENTIFICATION;
     175           0 :                         vpage->params[3] = SPDK_SPC_VPD_MANAGEMENT_NETWORK_ADDRESSES;
     176           0 :                         vpage->params[4] = SPDK_SPC_VPD_EXTENDED_INQUIRY_DATA;
     177           0 :                         vpage->params[5] = SPDK_SPC_VPD_MODE_PAGE_POLICY;
     178           0 :                         vpage->params[6] = SPDK_SPC_VPD_SCSI_PORTS;
     179           0 :                         vpage->params[7] = SPDK_SPC_VPD_BLOCK_LIMITS;
     180           0 :                         vpage->params[8] = SPDK_SPC_VPD_BLOCK_DEV_CHARS;
     181           0 :                         len = 9;
     182           0 :                         if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
     183           0 :                                 vpage->params[9] = SPDK_SPC_VPD_BLOCK_THIN_PROVISION;
     184           0 :                                 len++;
     185             :                         }
     186             : 
     187             :                         /* PAGE LENGTH */
     188           0 :                         to_be16(vpage->alloc_len, len);
     189           0 :                         break;
     190             : 
     191           0 :                 case SPDK_SPC_VPD_UNIT_SERIAL_NUMBER: {
     192           0 :                         const char *name = spdk_bdev_get_name(bdev);
     193             : 
     194           0 :                         hlen = 4;
     195             : 
     196             :                         /* PRODUCT SERIAL NUMBER */
     197           0 :                         len = strlen(name) + 1;
     198           0 :                         if (len > MAX_SERIAL_STRING) {
     199           0 :                                 len = MAX_SERIAL_STRING;
     200             :                         }
     201             : 
     202           0 :                         memcpy(vpage->params, name, len - 1);
     203           0 :                         vpage->params[len - 1] = 0;
     204             : 
     205             :                         /* PAGE LENGTH */
     206           0 :                         to_be16(vpage->alloc_len, len);
     207           0 :                         break;
     208             :                 }
     209             : 
     210           0 :                 case SPDK_SPC_VPD_DEVICE_IDENTIFICATION: {
     211           0 :                         const char *name = spdk_bdev_get_name(bdev);
     212           0 :                         const char *product_name = spdk_bdev_get_product_name(bdev);
     213           0 :                         uint8_t protocol_id = dev->protocol_id;
     214           0 :                         uint8_t *buf = vpage->params;
     215             :                         struct spdk_scsi_desig_desc *desig;
     216             : 
     217           0 :                         hlen = 4;
     218             : 
     219             :                         /* Check total length by calculated how much space all entries take */
     220           0 :                         len = sizeof(struct spdk_scsi_desig_desc) + 8;
     221           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
     222           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_DEV_MAX_NAME + 1;
     223           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + SPDK_SCSI_PORT_MAX_NAME_LENGTH;
     224           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + 4;
     225           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + 4;
     226           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + 4;
     227           0 :                         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           0 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     239           0 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
     240           0 :                         desig->protocol_id = protocol_id;
     241           0 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_NAA;
     242           0 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
     243           0 :                         desig->reserved0 = 0;
     244           0 :                         desig->piv = 1;
     245           0 :                         desig->reserved1 = 0;
     246           0 :                         desig->len = 8;
     247           0 :                         bdev_scsi_set_naa_ieee_extended(name, desig->desig);
     248           0 :                         len = sizeof(struct spdk_scsi_desig_desc) + 8;
     249             : 
     250           0 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     251             : 
     252             :                         /* T10 Vendor ID designator */
     253           0 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     254           0 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_ASCII;
     255           0 :                         desig->protocol_id = protocol_id;
     256           0 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_T10_VENDOR_ID;
     257           0 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
     258           0 :                         desig->reserved0 = 0;
     259           0 :                         desig->piv = 1;
     260           0 :                         desig->reserved1 = 0;
     261           0 :                         desig->len = 8 + 16 + MAX_SERIAL_STRING;
     262           0 :                         spdk_strcpy_pad(desig->desig, DEFAULT_DISK_VENDOR, 8, ' ');
     263           0 :                         spdk_strcpy_pad(&desig->desig[8], product_name, 16, ' ');
     264           0 :                         spdk_strcpy_pad(&desig->desig[24], name, MAX_SERIAL_STRING, ' ');
     265           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + 8 + 16 + MAX_SERIAL_STRING;
     266             : 
     267           0 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     268             : 
     269             :                         /* SCSI Device Name designator */
     270           0 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     271           0 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
     272           0 :                         desig->protocol_id = protocol_id;
     273           0 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
     274           0 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_DEVICE;
     275           0 :                         desig->reserved0 = 0;
     276           0 :                         desig->piv = 1;
     277           0 :                         desig->reserved1 = 0;
     278           0 :                         desig->len = bdev_scsi_pad_scsi_name(desig->desig, dev->name);
     279           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     280             : 
     281           0 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     282             : 
     283             :                         /* SCSI Port Name designator */
     284           0 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     285           0 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_UTF8;
     286           0 :                         desig->protocol_id = protocol_id;
     287           0 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_SCSI_NAME;
     288           0 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
     289           0 :                         desig->reserved0 = 0;
     290           0 :                         desig->piv = 1;
     291           0 :                         desig->reserved1 = 0;
     292           0 :                         desig->len = snprintf(desig->desig, SPDK_SCSI_PORT_MAX_NAME_LENGTH, "%s", port->name);
     293           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     294             : 
     295           0 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     296             : 
     297             :                         /* Relative Target Port designator */
     298           0 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     299           0 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
     300           0 :                         desig->protocol_id = protocol_id;
     301           0 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_RELATIVE_TARGET_PORT;
     302           0 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
     303           0 :                         desig->reserved0 = 0;
     304           0 :                         desig->piv = 1;
     305           0 :                         desig->reserved1 = 0;
     306           0 :                         desig->len = 4;
     307           0 :                         memset(desig->desig, 0, 2); /* Reserved */
     308           0 :                         to_be16(&desig->desig[2], port->index);
     309           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     310             : 
     311           0 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     312             : 
     313             :                         /* Target port group designator */
     314           0 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     315           0 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
     316           0 :                         desig->protocol_id = protocol_id;
     317           0 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_TARGET_PORT_GROUP;
     318           0 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_TARGET_PORT;
     319           0 :                         desig->reserved0 = 0;
     320           0 :                         desig->piv = 1;
     321           0 :                         desig->reserved1 = 0;
     322           0 :                         desig->len = 4;
     323           0 :                         memset(desig->desig, 0, 4);
     324           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     325             : 
     326           0 :                         buf += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     327             : 
     328             :                         /* Logical unit group designator */
     329           0 :                         desig = (struct spdk_scsi_desig_desc *)buf;
     330           0 :                         desig->code_set = SPDK_SPC_VPD_CODE_SET_BINARY;
     331           0 :                         desig->protocol_id = protocol_id;
     332           0 :                         desig->type = SPDK_SPC_VPD_IDENTIFIER_TYPE_LOGICAL_UNIT_GROUP;
     333           0 :                         desig->association = SPDK_SPC_VPD_ASSOCIATION_LOGICAL_UNIT;
     334           0 :                         desig->reserved0 = 0;
     335           0 :                         desig->piv = 1;
     336           0 :                         desig->reserved1 = 0;
     337           0 :                         desig->len = 4;
     338           0 :                         memset(desig->desig, 0, 2); /* Reserved */
     339           0 :                         to_be16(&desig->desig[2], dev->id);
     340           0 :                         len += sizeof(struct spdk_scsi_desig_desc) + desig->len;
     341             : 
     342           0 :                         to_be16(vpage->alloc_len, len);
     343             : 
     344           0 :                         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           0 :                 case SPDK_SPC_VPD_BLOCK_LIMITS: {
     477           0 :                         uint32_t block_size = spdk_bdev_get_data_block_size(bdev);
     478             : 
     479             :                         /* PAGE LENGTH */
     480           0 :                         memset(&data[4], 0, 60);
     481             : 
     482           0 :                         hlen = 4;
     483             : 
     484             :                         /* WSNZ(0) */
     485             :                         /* support zero length in WRITE SAME */
     486             : 
     487             :                         /* MAXIMUM COMPARE AND WRITE LENGTH */
     488           0 :                         blocks = SPDK_WORK_ATS_BLOCK_SIZE / block_size;
     489             : 
     490           0 :                         if (blocks > 0xff) {
     491           0 :                                 blocks = 0xff;
     492             :                         }
     493             : 
     494           0 :                         data[5] = (uint8_t)blocks;
     495             : 
     496             :                         /* force align to 4KB */
     497           0 :                         if (block_size < 4096) {
     498           0 :                                 optimal_blocks = 4096 / block_size;
     499             :                         } else {
     500           0 :                                 optimal_blocks = 1;
     501             :                         }
     502             : 
     503             :                         /* OPTIMAL TRANSFER LENGTH GRANULARITY */
     504           0 :                         to_be16(&data[6], optimal_blocks);
     505             : 
     506           0 :                         blocks = SPDK_WORK_BLOCK_SIZE / block_size;
     507             : 
     508             :                         /* MAXIMUM TRANSFER LENGTH */
     509           0 :                         to_be32(&data[8], blocks);
     510             :                         /* OPTIMAL TRANSFER LENGTH */
     511           0 :                         to_be32(&data[12], blocks);
     512             : 
     513             :                         /* MAXIMUM PREFETCH XDREAD XDWRITE TRANSFER LENGTH */
     514             : 
     515           0 :                         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           0 :                                 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           0 :                                 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           0 :                         to_be64(&data[36], blocks);
     549             : 
     550             :                         /* Reserved */
     551             :                         /* not specified */
     552           0 :                         len = 64 - hlen;
     553             : 
     554           0 :                         to_be16(vpage->alloc_len, len);
     555           0 :                         break;
     556             :                 }
     557             : 
     558           0 :                 case SPDK_SPC_VPD_BLOCK_DEV_CHARS: {
     559             :                         /* PAGE LENGTH */
     560           0 :                         hlen = 4;
     561           0 :                         len = 64 - hlen;
     562             : 
     563           0 :                         to_be16(&data[4], DEFAULT_DISK_ROTATION_RATE);
     564             : 
     565             :                         /* Reserved */
     566           0 :                         data[6] = 0;
     567             :                         /* NOMINAL FORM FACTOR(3-0) */
     568           0 :                         data[7] = DEFAULT_DISK_FORM_FACTOR << 4;
     569             :                         /* Reserved */
     570           0 :                         memset(&data[8], 0, 64 - 8);
     571             : 
     572           0 :                         to_be16(vpage->alloc_len, len);
     573           0 :                         break;
     574             :                 }
     575             : 
     576           0 :                 case SPDK_SPC_VPD_BLOCK_THIN_PROVISION: {
     577           0 :                         if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
     578           0 :                                 goto inq_error;
     579             :                         }
     580             : 
     581           0 :                         hlen = 4;
     582           0 :                         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           0 :                         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           0 :                         data[4] = 0;
     596             : 
     597             :                         /*
     598             :                          * Set the LBPU bit to indicate  the support for UNMAP
     599             :                          * command.
     600             :                          */
     601           0 :                         data[5] |= SPDK_SCSI_UNMAP_LBPU;
     602             : 
     603             :                         /*
     604             :                          * Set the provisioning type to thin provision.
     605             :                          */
     606           0 :                         data[6] = SPDK_SCSI_UNMAP_THIN_PROVISIONING;
     607             : 
     608           0 :                         to_be16(vpage->alloc_len, len);
     609           0 :                         break;
     610             :                 }
     611             : 
     612           0 :                 default:
     613           0 :                         if (pc >= 0xc0 && pc <= 0xff) {
     614           0 :                                 SPDK_DEBUGLOG(scsi, "Vendor specific INQUIRY VPD page 0x%x\n", pc);
     615             :                         } else {
     616           0 :                                 SPDK_NOTICELOG("unsupported INQUIRY VPD page 0x%x\n", pc);
     617             :                         }
     618           0 :                         goto inq_error;
     619             :                 }
     620             :         } else {
     621         257 :                 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         257 :                 inqdata->peripheral_device_type = pd;
     627         257 :                 inqdata->peripheral_qualifier = SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED;
     628             : 
     629             :                 /* RMB(7) */
     630         257 :                 inqdata->rmb = 0;
     631             : 
     632             :                 /* VERSION */
     633             :                 /* See SPC3/SBC2/MMC4/SAM2 for more details */
     634         257 :                 inqdata->version = SPDK_SPC_VERSION_SPC3;
     635             : 
     636             :                 /* NORMACA(5) HISUP(4) RESPONSE DATA FORMAT(3-0) */
     637             :                 /* format 2 */ /* hierarchical support */
     638         257 :                 inqdata->response = 2 | 1 << 4;
     639             : 
     640         257 :                 hlen = 5;
     641             : 
     642             :                 /* SCCS(7) ACC(6) TPGS(5-4) 3PC(3) PROTECT(0) */
     643             :                 /* Not support TPGS */
     644         257 :                 inqdata->flags = 0;
     645             : 
     646             :                 /* MULTIP */
     647         257 :                 inqdata->flags2 = 0x10;
     648             : 
     649             :                 /* WBUS16(5) SYNC(4) LINKED(3) CMDQUE(1) VS(0) */
     650             :                 /* CMDQUE */
     651         257 :                 inqdata->flags3 = 0x2;
     652             : 
     653             :                 /* T10 VENDOR IDENTIFICATION */
     654         257 :                 spdk_strcpy_pad(inqdata->t10_vendor_id, DEFAULT_DISK_VENDOR, 8, ' ');
     655             : 
     656             :                 /* PRODUCT IDENTIFICATION */
     657         257 :                 spdk_strcpy_pad(inqdata->product_id, spdk_bdev_get_product_name(bdev), 16, ' ');
     658             : 
     659             :                 /* PRODUCT REVISION LEVEL */
     660         257 :                 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         257 :                 len = INQUIRY_OFFSET(product_rev) - 5;
     667             : 
     668         257 :                 if (alloc_len >= INQUIRY_OFFSET(vendor)) {
     669             :                         /* Vendor specific */
     670         257 :                         memset(inqdata->vendor, 0x20, 20);
     671         257 :                         len += sizeof(inqdata->vendor);
     672             :                 }
     673             : 
     674         257 :                 if (alloc_len >= INQUIRY_OFFSET(ius)) {
     675             :                         /* CLOCKING(3-2) QAS(1) IUS(0) */
     676         257 :                         inqdata->ius = 0;
     677         257 :                         len += sizeof(inqdata->ius);
     678             :                 }
     679             : 
     680         257 :                 if (alloc_len >= INQUIRY_OFFSET(reserved)) {
     681             :                         /* Reserved */
     682         257 :                         inqdata->reserved = 0;
     683         257 :                         len += sizeof(inqdata->reserved);
     684             :                 }
     685             : 
     686             :                 /* VERSION DESCRIPTOR 1-8 */
     687         257 :                 if (alloc_len >= INQUIRY_OFFSET(reserved) + 2) {
     688         257 :                         to_be16(&inqdata->desc[0], 0x0960);
     689         257 :                         len += 2;
     690             :                 }
     691             : 
     692         257 :                 if (alloc_len >= INQUIRY_OFFSET(reserved) + 4) {
     693         257 :                         to_be16(&inqdata->desc[2], 0x0300); /* SPC-3 (no version claimed) */
     694         257 :                         len += 2;
     695             :                 }
     696             : 
     697         257 :                 if (alloc_len >= INQUIRY_OFFSET(reserved) + 6) {
     698         257 :                         to_be16(&inqdata->desc[4], 0x320); /* SBC-2 (no version claimed) */
     699         257 :                         len += 2;
     700             :                 }
     701             : 
     702         257 :                 if (alloc_len >= INQUIRY_OFFSET(reserved) + 8) {
     703         257 :                         to_be16(&inqdata->desc[6], 0x0040); /* SAM-2 (no version claimed) */
     704         257 :                         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         257 :                 if (alloc_len > INQUIRY_OFFSET(reserved) + 8) {
     715         257 :                         i = alloc_len - (INQUIRY_OFFSET(reserved) + 8);
     716         257 :                         if (i > 30) {
     717         257 :                                 i = 30;
     718             :                         }
     719         257 :                         memset(&inqdata->desc[8], 0, i);
     720         257 :                         len += i;
     721             :                 }
     722             : 
     723             :                 /* ADDITIONAL LENGTH */
     724         257 :                 inqdata->add_len = len;
     725             :         }
     726             : 
     727         257 :         return hlen + len;
     728             : 
     729           0 : inq_error:
     730           0 :         task->data_transferred = 0;
     731           0 :         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           0 :         return -1;
     736             : }
     737             : 
     738             : static void
     739          32 : mode_sense_page_init(uint8_t *buf, int len, int page, int subpage)
     740             : {
     741          32 :         if (!buf) {
     742          16 :                 return;
     743             :         }
     744             : 
     745          16 :         memset(buf, 0, len);
     746          16 :         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          16 :                 buf[0] = page;
     752          16 :                 buf[1] = len - 2;
     753             :         }
     754             : }
     755             : 
     756             : static int
     757         252 : 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         252 :         uint8_t *cp = data;
     762         252 :         int len = 0;
     763             :         int plen;
     764             :         int i;
     765             : 
     766         252 :         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         252 :         switch (page) {
     784           4 :         case 0x00:
     785             :                 /* Vendor specific */
     786           4 :                 break;
     787           4 :         case 0x01:
     788             :                 /* Read-Write Error Recovery */
     789           4 :                 SPDK_DEBUGLOG(scsi,
     790             :                               "MODE_SENSE Read-Write Error Recovery\n");
     791           4 :                 if (subpage != 0x00) {
     792           0 :                         break;
     793             :                 }
     794           4 :                 plen = 0x0a + 2;
     795           4 :                 mode_sense_page_init(cp, plen, page, subpage);
     796           4 :                 len += plen;
     797           4 :                 break;
     798           4 :         case 0x02:
     799             :                 /* Disconnect-Reconnect */
     800           4 :                 SPDK_DEBUGLOG(scsi,
     801             :                               "MODE_SENSE Disconnect-Reconnect\n");
     802           4 :                 if (subpage != 0x00) {
     803           0 :                         break;
     804             :                 }
     805           4 :                 plen = 0x0e + 2;
     806           4 :                 mode_sense_page_init(cp, plen, page, subpage);
     807           4 :                 len += plen;
     808           4 :                 break;
     809           4 :         case 0x03:
     810             :                 /* Obsolete (Format Device) */
     811           4 :                 break;
     812           4 :         case 0x04:
     813             :                 /* Obsolete (Rigid Disk Geometry) */
     814           4 :                 break;
     815           4 :         case 0x05:
     816             :                 /* Obsolete (Rigid Disk Geometry) */
     817           4 :                 break;
     818           4 :         case 0x06:
     819             :                 /* Reserved */
     820           4 :                 break;
     821           4 :         case 0x07:
     822             :                 /* Verify Error Recovery */
     823           4 :                 SPDK_DEBUGLOG(scsi,
     824             :                               "MODE_SENSE Verify Error Recovery\n");
     825             : 
     826           4 :                 if (subpage != 0x00) {
     827           0 :                         break;
     828             :                 }
     829             : 
     830           4 :                 plen = 0x0a + 2;
     831           4 :                 mode_sense_page_init(cp, plen, page, subpage);
     832           4 :                 len += plen;
     833           4 :                 break;
     834           4 :         case 0x08: {
     835             :                 /* Caching */
     836           4 :                 SPDK_DEBUGLOG(scsi, "MODE_SENSE Caching\n");
     837           4 :                 if (subpage != 0x00) {
     838           0 :                         break;
     839             :                 }
     840             : 
     841           4 :                 plen = 0x12 + 2;
     842           4 :                 mode_sense_page_init(cp, plen, page, subpage);
     843             : 
     844           4 :                 if (cp && spdk_bdev_has_write_cache(bdev) && pc != 0x01) {
     845           0 :                         cp[2] |= 0x4;        /* WCE */
     846             :                 }
     847             : 
     848             :                 /* Read Cache Disable (RCD) = 1 */
     849           4 :                 if (cp && pc != 0x01) {
     850           2 :                         cp[2] |= 0x1;
     851             :                 }
     852             : 
     853           4 :                 len += plen;
     854           4 :                 break;
     855             :         }
     856           4 :         case 0x09:
     857             :                 /* Obsolete */
     858           4 :                 break;
     859           4 :         case 0x0a:
     860           4 :                 switch (subpage) {
     861           4 :                 case 0x00:
     862             :                         /* Control */
     863           4 :                         SPDK_DEBUGLOG(scsi,
     864             :                                       "MODE_SENSE Control\n");
     865           4 :                         plen = 0x0a + 2;
     866           4 :                         mode_sense_page_init(cp, plen, page, subpage);
     867           4 :                         len += plen;
     868           4 :                         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           4 :                 break;
     893           4 :         case 0x0b:
     894             :                 /* Obsolete (Medium Types Supported) */
     895           4 :                 break;
     896           4 :         case 0x0c:
     897             :                 /* Obsolete (Notch And Partition) */
     898           4 :                 break;
     899           4 :         case 0x0d:
     900             :                 /* Obsolete */
     901           4 :                 break;
     902           8 :         case 0x0e:
     903             :         case 0x0f:
     904             :                 /* Reserved */
     905           8 :                 break;
     906           4 :         case 0x10:
     907             :                 /* XOR Control */
     908           4 :                 SPDK_DEBUGLOG(scsi, "MODE_SENSE XOR Control\n");
     909           4 :                 if (subpage != 0x00) {
     910           0 :                         break;
     911             :                 }
     912           4 :                 plen = 0x16 + 2;
     913           4 :                 mode_sense_page_init(cp, plen, page, subpage);
     914           4 :                 len += plen;
     915           4 :                 break;
     916          12 :         case 0x11:
     917             :         case 0x12:
     918             :         case 0x13:
     919             :                 /* Reserved */
     920          12 :                 break;
     921           4 :         case 0x14:
     922             :                 /* Enclosure Services Management */
     923           4 :                 break;
     924          12 :         case 0x15:
     925             :         case 0x16:
     926             :         case 0x17:
     927             :                 /* Reserved */
     928          12 :                 break;
     929           4 :         case 0x18:
     930             :                 /* Protocol-Specific LUN */
     931           4 :                 break;
     932           4 :         case 0x19:
     933             :                 /* Protocol-Specific Port */
     934           4 :                 break;
     935           4 :         case 0x1a:
     936             :                 /* Power Condition */
     937           4 :                 SPDK_DEBUGLOG(scsi,
     938             :                               "MODE_SENSE Power Condition\n");
     939           4 :                 if (subpage != 0x00) {
     940           0 :                         break;
     941             :                 }
     942           4 :                 plen = 0x0a + 2;
     943           4 :                 mode_sense_page_init(cp, plen, page, subpage);
     944           4 :                 len += plen;
     945           4 :                 break;
     946           4 :         case 0x1b:
     947             :                 /* Reserved */
     948           4 :                 break;
     949           4 :         case 0x1c:
     950             :                 /* Informational Exceptions Control */
     951           4 :                 SPDK_DEBUGLOG(scsi,
     952             :                               "MODE_SENSE Informational Exceptions Control\n");
     953           4 :                 if (subpage != 0x00) {
     954           0 :                         break;
     955             :                 }
     956             : 
     957           4 :                 plen = 0x0a + 2;
     958           4 :                 mode_sense_page_init(cp, plen, page, subpage);
     959           4 :                 len += plen;
     960           4 :                 break;
     961          12 :         case 0x1d:
     962             :         case 0x1e:
     963             :         case 0x1f:
     964             :                 /* Reserved */
     965          12 :                 break;
     966         120 :         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         120 :                 break;
     999           4 :         case 0x3f:
    1000           4 :                 switch (subpage) {
    1001           4 :                 case 0x00:
    1002             :                         /* All mode pages */
    1003         252 :                         for (i = 0x00; i < 0x3e; i ++) {
    1004         372 :                                 len += bdev_scsi_mode_sense_page(
    1005             :                                                bdev, cdb, pc, i, 0x00,
    1006         124 :                                                cp ? &cp[len] : NULL, task);
    1007             :                         }
    1008           4 :                         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             :         }
    1027             : 
    1028         252 :         return len;
    1029             : }
    1030             : 
    1031             : static int
    1032           4 : 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           4 :         uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
    1037           4 :         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           4 :         assert(md == 6 || md == 10);
    1044             : 
    1045           4 :         if (md == 6) {
    1046           2 :                 hlen = 4;
    1047           2 :                 blen = 8; /* For MODE SENSE 6 only short LBA */
    1048             :         } else {
    1049           2 :                 hlen = 8;
    1050           2 :                 blen = llbaa ? 16 : 8;
    1051             :         }
    1052             : 
    1053           4 :         if (dbd) {
    1054           0 :                 blen = 0;
    1055             :         }
    1056             : 
    1057           4 :         pages = data ? &data[hlen + blen] : NULL;
    1058           4 :         plen = bdev_scsi_mode_sense_page(bdev, cdb, pc, page,
    1059             :                                          subpage,
    1060             :                                          pages, task);
    1061           4 :         if (plen < 0) {
    1062           0 :                 return -1;
    1063             :         }
    1064             : 
    1065           4 :         total = hlen + blen + plen;
    1066           4 :         if (data == NULL) {
    1067           2 :                 return total;
    1068             :         }
    1069             : 
    1070           2 :         hdr = &data[0];
    1071           2 :         if (hlen == 4) {
    1072           1 :                 hdr[0] = total - 1;            /* Mode Data Length */
    1073           1 :                 hdr[1] = 0;                    /* Medium Type */
    1074           1 :                 hdr[2] = 0;                    /* Device-Specific Parameter */
    1075           1 :                 hdr[3] = blen;                 /* Block Descriptor Length */
    1076             :         } else {
    1077           1 :                 to_be16(&hdr[0], total - 2);   /* Mode Data Length */
    1078           1 :                 hdr[2] = 0;                    /* Medium Type */
    1079           1 :                 hdr[3] = 0;                    /* Device-Specific Parameter */
    1080           1 :                 hdr[4] = llbaa ? 0x1 : 0;      /* Long/short LBA */
    1081           1 :                 hdr[5] = 0;                    /* Reserved */
    1082           1 :                 to_be16(&hdr[6], blen);        /* Block Descriptor Length */
    1083             :         }
    1084             : 
    1085           2 :         bdesc = &data[hlen];
    1086           2 :         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           2 :         } else if (blen == 8) {
    1094             :                 /* Number of Blocks */
    1095           2 :                 if (num_blocks > 0xffffffffULL) {
    1096           0 :                         memset(&bdesc[0], 0xff, 4);
    1097             :                 } else {
    1098           2 :                         to_be32(&bdesc[0], num_blocks);
    1099             :                 }
    1100             : 
    1101             :                 /* Block Length */
    1102           2 :                 to_be32(&bdesc[4], block_size);
    1103             :         }
    1104             : 
    1105           2 :         return total;
    1106             : }
    1107             : 
    1108             : static void
    1109           7 : bdev_scsi_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
    1110             :                             void *cb_arg)
    1111             : {
    1112           7 :         struct spdk_scsi_task *task = cb_arg;
    1113           7 :         int sc, sk, asc, ascq;
    1114             : 
    1115           7 :         spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
    1116             : 
    1117           7 :         spdk_bdev_free_io(bdev_io);
    1118             : 
    1119           7 :         spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
    1120           7 :         scsi_lun_complete_task(task->lun, task);
    1121           7 : }
    1122             : 
    1123             : static void
    1124           6 : bdev_scsi_read_task_complete_cmd(struct spdk_bdev_io *bdev_io, bool success,
    1125             :                                  void *cb_arg)
    1126             : {
    1127           6 :         struct spdk_scsi_task *task = cb_arg;
    1128           6 :         int sc, sk, asc, ascq;
    1129             : 
    1130           6 :         task->bdev_io = bdev_io;
    1131             : 
    1132           6 :         spdk_bdev_io_get_scsi_status(bdev_io, &sc, &sk, &asc, &ascq);
    1133             : 
    1134           6 :         spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
    1135           6 :         scsi_lun_complete_task(task->lun, task);
    1136           6 : }
    1137             : 
    1138             : static void
    1139           0 : bdev_scsi_task_complete_reset(struct spdk_bdev_io *bdev_io, bool success,
    1140             :                               void *cb_arg)
    1141             : {
    1142           0 :         struct spdk_scsi_task *task = cb_arg;
    1143             : 
    1144           0 :         spdk_bdev_free_io(bdev_io);
    1145             : 
    1146           0 :         if (success) {
    1147           0 :                 task->response = SPDK_SCSI_TASK_MGMT_RESP_SUCCESS;
    1148             :         }
    1149             : 
    1150           0 :         scsi_lun_complete_reset_task(task->lun, task);
    1151           0 : }
    1152             : 
    1153             : static void
    1154           7 : bdev_scsi_queue_io(struct spdk_scsi_task *task, spdk_bdev_io_wait_cb cb_fn, void *cb_arg)
    1155             : {
    1156           7 :         struct spdk_scsi_lun *lun = task->lun;
    1157           7 :         struct spdk_bdev *bdev = lun->bdev;
    1158           7 :         struct spdk_io_channel *ch = lun->io_channel;
    1159             :         int rc;
    1160             : 
    1161           7 :         task->bdev_io_wait.bdev = bdev;
    1162           7 :         task->bdev_io_wait.cb_fn = cb_fn;
    1163           7 :         task->bdev_io_wait.cb_arg = cb_arg;
    1164             : 
    1165           7 :         rc = spdk_bdev_queue_io_wait(bdev, ch, &task->bdev_io_wait);
    1166           7 :         if (rc != 0) {
    1167           0 :                 assert(false);
    1168             :         }
    1169           7 : }
    1170             : 
    1171             : static int
    1172           3 : 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           3 :         if (num_blocks == 0) {
    1180           0 :                 return SPDK_SCSI_TASK_COMPLETE;
    1181             :         }
    1182             : 
    1183           3 :         bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
    1184             : 
    1185           3 :         if (lba >= bdev_num_blocks || num_blocks > bdev_num_blocks ||
    1186           3 :             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           3 :         rc = spdk_bdev_flush_blocks(bdev_desc, bdev_ch, lba, num_blocks,
    1196             :                                     bdev_scsi_task_complete_cmd, task);
    1197             : 
    1198           3 :         if (rc) {
    1199           1 :                 if (rc == -ENOMEM) {
    1200           1 :                         bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
    1201           1 :                         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           2 :         task->data_transferred = 0;
    1211           2 :         return SPDK_SCSI_TASK_PENDING;
    1212             : }
    1213             : 
    1214             : static uint64_t
    1215          10 : _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          10 :         if (spdk_likely(spdk_u32_is_pow2(block_size))) {
    1222          10 :                 shift_cnt = spdk_u32log2(block_size);
    1223          10 :                 *offset_blocks = offset_bytes >> shift_cnt;
    1224          10 :                 *num_blocks = num_bytes >> shift_cnt;
    1225          10 :                 return (offset_bytes - (*offset_blocks << shift_cnt)) |
    1226          10 :                        (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          15 : 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          15 :         uint64_t bdev_num_blocks, offset_blocks, num_blocks;
    1240             :         uint32_t max_xfer_len, block_size;
    1241          15 :         int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
    1242             :         int rc;
    1243             : 
    1244          15 :         task->data_transferred = 0;
    1245             : 
    1246          15 :         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          15 :         bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
    1253          15 :         if (spdk_unlikely(bdev_num_blocks <= lba || bdev_num_blocks - lba < xfer_len)) {
    1254           3 :                 SPDK_DEBUGLOG(scsi, "end of media\n");
    1255           3 :                 sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
    1256           3 :                 asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
    1257           3 :                 goto check_condition;
    1258             :         }
    1259             : 
    1260          12 :         if (spdk_unlikely(xfer_len == 0)) {
    1261           1 :                 task->status = SPDK_SCSI_STATUS_GOOD;
    1262           1 :                 return SPDK_SCSI_TASK_COMPLETE;
    1263             :         }
    1264             : 
    1265          11 :         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          11 :         max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
    1269          11 :         if (spdk_unlikely(xfer_len > max_xfer_len)) {
    1270           1 :                 SPDK_ERRLOG("xfer_len %" PRIu32 " > maximum transfer length %" PRIu32 "\n",
    1271             :                             xfer_len, max_xfer_len);
    1272           1 :                 sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
    1273           1 :                 asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
    1274           1 :                 goto check_condition;
    1275             :         }
    1276             : 
    1277          10 :         if (!is_read) {
    1278             :                 /* Additional check for Transfer Length */
    1279           3 :                 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          10 :         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          10 :         offset_blocks += lba;
    1293             : 
    1294          10 :         SPDK_DEBUGLOG(scsi,
    1295             :                       "%s: lba=%"PRIu64", len=%"PRIu64"\n",
    1296             :                       is_read ? "Read" : "Write", offset_blocks, num_blocks);
    1297             : 
    1298          10 :         if (is_read) {
    1299           7 :                 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           3 :         } 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           3 :                 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          10 :         if (rc) {
    1333           2 :                 if (rc == -ENOMEM) {
    1334           2 :                         bdev_scsi_queue_io(task, bdev_scsi_process_block_resubmit, task);
    1335           2 :                         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           8 :         task->data_transferred = task->length;
    1343           8 :         return SPDK_SCSI_TASK_PENDING;
    1344             : 
    1345           4 : check_condition:
    1346           4 :         spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION, sk, asc,
    1347             :                                   SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
    1348           4 :         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           4 : bdev_scsi_split_resubmit(void *arg)
    1367             : {
    1368           4 :         struct spdk_bdev_scsi_split_ctx *ctx = arg;
    1369             : 
    1370           4 :         bdev_scsi_split(ctx);
    1371           4 : }
    1372             : 
    1373             : static int
    1374           9 : bdev_scsi_split(struct spdk_bdev_scsi_split_ctx *ctx)
    1375             : {
    1376           9 :         struct spdk_scsi_task *task = ctx->task;
    1377           9 :         uint8_t opcode = task->cdb[0];
    1378             :         int rc;
    1379             : 
    1380          19 :         while (ctx->remaining_count != 0) {
    1381          16 :                 rc = ctx->fn(ctx);
    1382          16 :                 if (rc == 0) {
    1383          10 :                         ctx->current_count++;
    1384          10 :                         ctx->remaining_count--;
    1385          10 :                         ctx->outstanding_count++;
    1386          10 :                         continue;
    1387           6 :                 } else if (rc == -ENOMEM) {
    1388           6 :                         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           9 :         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           5 :                 return SPDK_SCSI_TASK_PENDING;
    1406             :         }
    1407             : 
    1408           4 :         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           4 :                 bdev_scsi_queue_io(task, bdev_scsi_split_resubmit, ctx);
    1412           4 :                 return SPDK_SCSI_TASK_PENDING;
    1413             :         }
    1414             : 
    1415           0 :         free(ctx);
    1416           0 :         return SPDK_SCSI_TASK_COMPLETE;
    1417             : }
    1418             : 
    1419             : static void
    1420          10 : bdev_scsi_task_complete_split_cmd(struct spdk_bdev_io *bdev_io, bool success,
    1421             :                                   void *cb_arg)
    1422             : {
    1423          10 :         struct spdk_bdev_scsi_split_ctx *ctx = cb_arg;
    1424          10 :         struct spdk_scsi_task *task = ctx->task;
    1425             : 
    1426          10 :         spdk_bdev_free_io(bdev_io);
    1427             : 
    1428          10 :         if (!success) {
    1429           0 :                 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           0 :                 ctx->current_count += ctx->remaining_count;
    1435           0 :                 ctx->remaining_count = 0;
    1436             :         }
    1437             : 
    1438          10 :         ctx->outstanding_count--;
    1439          10 :         if (ctx->outstanding_count != 0) {
    1440             :                 /* Any child I/O is still outstanding. */
    1441           5 :                 return;
    1442             :         }
    1443             : 
    1444           5 :         if (ctx->remaining_count == 0) {
    1445             :                 /* SCSI task finishes when all descriptors are consumed. */
    1446           3 :                 scsi_lun_complete_task(task->lun, task);
    1447           3 :                 free(ctx);
    1448           3 :                 return;
    1449             :         }
    1450             : 
    1451             :         /* Continue with splitting process. */
    1452           2 :         bdev_scsi_split(ctx);
    1453             : }
    1454             : 
    1455             : static int
    1456           3 : __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           3 :         if (!data) {
    1462           0 :                 return -EINVAL;
    1463             :         }
    1464             : 
    1465           3 :         if (data_len < 8) {
    1466             :                 /* We can't even get the reported length, so fail. */
    1467           0 :                 return -EINVAL;
    1468             :         }
    1469             : 
    1470           3 :         desc_data_len = from_be16(&data[2]);
    1471           3 :         desc_count = desc_data_len / 16;
    1472             : 
    1473           3 :         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           3 :         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           3 :         memcpy(ctx->desc, &data[8], desc_data_len);
    1486           3 :         return desc_count;
    1487             : }
    1488             : 
    1489             : static int
    1490          16 : _bdev_scsi_unmap(struct spdk_bdev_scsi_split_ctx *ctx)
    1491             : {
    1492          16 :         struct spdk_scsi_task *task = ctx->task;
    1493          16 :         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          16 :         desc = &ctx->desc[ctx->current_count];
    1499             : 
    1500          16 :         offset_blocks = from_be64(&desc->lba);
    1501          16 :         num_blocks = from_be32(&desc->block_count);
    1502             : 
    1503          16 :         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           3 : 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           3 :         int                             desc_count = -1;
    1517           3 :         int                             data_len;
    1518             : 
    1519           3 :         assert(task->status == SPDK_SCSI_STATUS_GOOD);
    1520             : 
    1521           3 :         ctx = calloc(1, sizeof(*ctx));
    1522           3 :         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           3 :         ctx->task = task;
    1531           3 :         ctx->current_count = 0;
    1532           3 :         ctx->outstanding_count = 0;
    1533           3 :         ctx->fn = _bdev_scsi_unmap;
    1534             : 
    1535           3 :         if (task->iovcnt == 1) {
    1536           3 :                 data = (uint8_t *)task->iovs[0].iov_base;
    1537           3 :                 data_len = task->iovs[0].iov_len;
    1538           3 :                 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           3 :         if (desc_count > 0) {
    1548           3 :                 ctx->remaining_count = desc_count;
    1549           3 :                 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           0 : _bdev_scsi_write_same(struct spdk_bdev_scsi_split_ctx *ctx)
    1565             : {
    1566           0 :         struct spdk_scsi_task *task = ctx->task;
    1567           0 :         struct spdk_scsi_lun *lun = task->lun;
    1568             :         uint64_t offset_blocks;
    1569             : 
    1570           0 :         offset_blocks = ctx->start_offset_blocks + ctx->current_count;
    1571           0 :         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           0 : 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           0 :         uint64_t bdev_num_blocks, offset_blocks, num_blocks;
    1582             :         uint32_t max_xfer_len, block_size;
    1583           0 :         int sk = SPDK_SCSI_SENSE_NO_SENSE, asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
    1584             : 
    1585           0 :         task->data_transferred = 0;
    1586             : 
    1587           0 :         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           0 :         block_size = spdk_bdev_get_data_block_size(bdev);
    1593           0 :         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           0 :         if (spdk_unlikely(xfer_len == 0)) {
    1600           0 :                 task->status = SPDK_SCSI_STATUS_GOOD;
    1601           0 :                 return SPDK_SCSI_TASK_COMPLETE;
    1602             :         }
    1603             : 
    1604           0 :         bdev_num_blocks = spdk_bdev_get_num_blocks(bdev);
    1605           0 :         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           0 :         max_xfer_len = SPDK_WORK_BLOCK_SIZE / block_size;
    1614           0 :         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           0 :         if (_bytes_to_blocks(block_size, task->offset, &offset_blocks,
    1623           0 :                              (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           0 :         offset_blocks += lba;
    1631           0 :         SPDK_DEBUGLOG(scsi, "Writesame: lba=%"PRIu64", len=%"PRIu64"\n",
    1632             :                       offset_blocks, num_blocks);
    1633             : 
    1634           0 :         ctx = calloc(1, sizeof(*ctx));
    1635           0 :         if (!ctx) {
    1636           0 :                 SPDK_ERRLOG("No enough memory on SCSI WRITE SAME\n");
    1637           0 :                 goto check_condition;
    1638             :         }
    1639             : 
    1640           0 :         ctx->task = task;
    1641           0 :         ctx->start_offset_blocks = offset_blocks;
    1642           0 :         ctx->current_count = 0;
    1643           0 :         ctx->outstanding_count = 0;
    1644           0 :         ctx->remaining_count = xfer_len;
    1645           0 :         ctx->fn = _bdev_scsi_write_same;
    1646             : 
    1647           0 :         task->data_transferred = task->length;
    1648             : 
    1649           0 :         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         283 : bdev_scsi_process_block(struct spdk_scsi_task *task)
    1659             : {
    1660         283 :         struct spdk_scsi_lun *lun = task->lun;
    1661         283 :         struct spdk_bdev *bdev = lun->bdev;
    1662             :         uint64_t lba;
    1663             :         uint32_t xfer_len;
    1664         283 :         uint32_t len = 0;
    1665         283 :         uint8_t *cdb = task->cdb;
    1666             : 
    1667             :         /* XXX: We need to support FUA bit for writes! */
    1668         283 :         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           0 :         case SPDK_SBC_READ_10:
    1683             :         case SPDK_SBC_WRITE_10:
    1684           0 :                 lba = from_be32(&cdb[2]);
    1685           0 :                 xfer_len = from_be16(&cdb[7]);
    1686           0 :                 return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
    1687             :                                            task, lba, xfer_len,
    1688           0 :                                            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          15 :         case SPDK_SBC_READ_16:
    1698             :         case SPDK_SBC_WRITE_16:
    1699          15 :                 lba = from_be64(&cdb[2]);
    1700          15 :                 xfer_len = from_be32(&cdb[10]);
    1701          15 :                 return bdev_scsi_readwrite(bdev, lun->bdev_desc, lun->io_channel,
    1702             :                                            task, lba, xfer_len,
    1703          15 :                                            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           0 :         case SPDK_SBC_READ_CAPACITY_10: {
    1737           0 :                 uint64_t num_blocks = spdk_bdev_get_num_blocks(bdev);
    1738           0 :                 uint8_t buffer[8];
    1739             : 
    1740           0 :                 if (num_blocks - 1 > 0xffffffffULL) {
    1741           0 :                         memset(buffer, 0xff, 4);
    1742             :                 } else {
    1743           0 :                         to_be32(buffer, num_blocks - 1);
    1744             :                 }
    1745           0 :                 to_be32(&buffer[4], spdk_bdev_get_data_block_size(bdev));
    1746             : 
    1747           0 :                 len = spdk_min(task->length, sizeof(buffer));
    1748           0 :                 if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
    1749           0 :                         break;
    1750             :                 }
    1751             : 
    1752           0 :                 task->data_transferred = len;
    1753           0 :                 task->status = SPDK_SCSI_STATUS_GOOD;
    1754           0 :                 break;
    1755             :         }
    1756             : 
    1757           0 :         case SPDK_SPC_SERVICE_ACTION_IN_16:
    1758           0 :                 switch (cdb[1] & 0x1f) { /* SERVICE ACTION */
    1759           0 :                 case SPDK_SBC_SAI_READ_CAPACITY_16: {
    1760           0 :                         uint8_t buffer[32] = {0};
    1761             :                         uint32_t lbppb, lbppbe;
    1762             : 
    1763           0 :                         to_be64(&buffer[0], spdk_bdev_get_num_blocks(bdev) - 1);
    1764           0 :                         to_be32(&buffer[8], spdk_bdev_get_data_block_size(bdev));
    1765           0 :                         lbppb = spdk_bdev_get_physical_block_size(bdev) / spdk_bdev_get_data_block_size(bdev);
    1766           0 :                         lbppbe = spdk_u32log2(lbppb);
    1767           0 :                         if (lbppbe > 0xf) {
    1768           0 :                                 SPDK_ERRLOG("lbppbe(0x%x) > 0xf\n", lbppbe);
    1769             :                         } else {
    1770           0 :                                 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           0 :                         if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
    1778           0 :                                 buffer[14] |= 1 << 7;
    1779             :                         }
    1780             : 
    1781           0 :                         len = spdk_min(from_be32(&cdb[10]), sizeof(buffer));
    1782           0 :                         if (spdk_scsi_task_scatter_data(task, buffer, len) < 0) {
    1783           0 :                                 break;
    1784             :                         }
    1785             : 
    1786           0 :                         task->data_transferred = len;
    1787           0 :                         task->status = SPDK_SCSI_STATUS_GOOD;
    1788           0 :                         break;
    1789             :                 }
    1790             : 
    1791           0 :                 default:
    1792           0 :                         return SPDK_SCSI_TASK_UNKNOWN;
    1793             :                 }
    1794             :                 break;
    1795             : 
    1796           3 :         case SPDK_SBC_SYNCHRONIZE_CACHE_10:
    1797             :         case SPDK_SBC_SYNCHRONIZE_CACHE_16:
    1798           3 :                 if (cdb[0] == SPDK_SBC_SYNCHRONIZE_CACHE_10) {
    1799           0 :                         lba = from_be32(&cdb[2]);
    1800           0 :                         len = from_be16(&cdb[7]);
    1801             :                 } else {
    1802           3 :                         lba = from_be64(&cdb[2]);
    1803           3 :                         len = from_be32(&cdb[10]);
    1804             :                 }
    1805             : 
    1806           3 :                 if (len == 0) {
    1807           0 :                         len = spdk_bdev_get_num_blocks(bdev) - lba;
    1808             :                 }
    1809             : 
    1810           3 :                 return bdev_scsi_sync(bdev, lun->bdev_desc, lun->io_channel, task, lba, len);
    1811             :                 break;
    1812             : 
    1813           3 :         case SPDK_SBC_UNMAP:
    1814           3 :                 return bdev_scsi_unmap(bdev, task);
    1815             : 
    1816           0 :         case SPDK_SBC_WRITE_SAME_10:
    1817           0 :                 lba = from_be32(&cdb[2]);
    1818           0 :                 xfer_len = from_be16(&cdb[7]);
    1819           0 :                 return bdev_scsi_write_same(bdev, lun->bdev_desc, lun->io_channel,
    1820           0 :                                             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         262 :         default:
    1830         262 :                 return SPDK_SCSI_TASK_UNKNOWN;
    1831             :         }
    1832             : 
    1833           0 :         return SPDK_SCSI_TASK_COMPLETE;
    1834             : }
    1835             : 
    1836             : static void
    1837           3 : bdev_scsi_process_block_resubmit(void *arg)
    1838             : {
    1839           3 :         struct spdk_scsi_task *task = arg;
    1840             : 
    1841           3 :         bdev_scsi_process_block(task);
    1842           3 : }
    1843             : 
    1844             : static int
    1845           2 : bdev_scsi_check_len(struct spdk_scsi_task *task, int len, int min_len)
    1846             : {
    1847           2 :         if (len >= min_len) {
    1848           2 :                 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         262 : bdev_scsi_process_primary(struct spdk_scsi_task *task)
    1861             : {
    1862         262 :         struct spdk_scsi_lun *lun = task->lun;
    1863         262 :         struct spdk_bdev *bdev = lun->bdev;
    1864         262 :         int alloc_len = -1;
    1865         262 :         int data_len = -1;
    1866         262 :         uint8_t *cdb = task->cdb;
    1867         262 :         uint8_t *data = NULL;
    1868         262 :         int rc = 0;
    1869         262 :         int pllen, md = 0;
    1870             :         int llba;
    1871             :         int dbd, pc, page, subpage;
    1872         262 :         int cmd_parsed = 0;
    1873             : 
    1874         262 :         switch (cdb[0]) {
    1875         258 :         case SPDK_SPC_INQUIRY:
    1876         258 :                 alloc_len = from_be16(&cdb[3]);
    1877         258 :                 data_len = spdk_max(4096, alloc_len);
    1878         258 :                 data = calloc(1, data_len);
    1879         258 :                 assert(data != NULL);
    1880         258 :                 rc = bdev_scsi_inquiry(bdev, task, cdb, data, data_len);
    1881         258 :                 data_len = spdk_min(rc, data_len);
    1882         258 :                 if (rc < 0) {
    1883           1 :                         break;
    1884             :                 }
    1885             : 
    1886         257 :                 SPDK_LOGDUMP(scsi, "INQUIRY", data, data_len);
    1887         257 :                 break;
    1888             : 
    1889           0 :         case SPDK_SPC_REPORT_LUNS: {
    1890             :                 int sel;
    1891             : 
    1892           0 :                 sel = cdb[2];
    1893           0 :                 SPDK_DEBUGLOG(scsi, "sel=%x\n", sel);
    1894             : 
    1895           0 :                 alloc_len = from_be32(&cdb[6]);
    1896           0 :                 rc = bdev_scsi_check_len(task, alloc_len, 16);
    1897           0 :                 if (rc < 0) {
    1898           0 :                         break;
    1899             :                 }
    1900             : 
    1901           0 :                 data_len = spdk_max(4096, alloc_len);
    1902           0 :                 data = calloc(1, data_len);
    1903           0 :                 assert(data != NULL);
    1904           0 :                 rc = bdev_scsi_report_luns(task->lun, sel, data, data_len);
    1905           0 :                 data_len = rc;
    1906           0 :                 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           0 :                 SPDK_LOGDUMP(scsi, "REPORT LUNS", data, data_len);
    1915           0 :                 break;
    1916             :         }
    1917             : 
    1918           2 :         case SPDK_SPC_MODE_SELECT_6:
    1919             :         case SPDK_SPC_MODE_SELECT_10:
    1920           2 :                 if (cdb[0] == SPDK_SPC_MODE_SELECT_6) {
    1921             :                         /* MODE_SELECT(6) must have at least a 4 byte header. */
    1922           2 :                         md = 4;
    1923           2 :                         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           2 :                 if (pllen == 0) {
    1931           1 :                         break;
    1932             :                 }
    1933             : 
    1934           1 :                 rc = bdev_scsi_check_len(task, pllen, md);
    1935           1 :                 if (rc < 0) {
    1936           0 :                         break;
    1937             :                 }
    1938             : 
    1939           1 :                 data = spdk_scsi_task_gather_data(task, &rc);
    1940           1 :                 if (rc < 0) {
    1941           0 :                         break;
    1942             :                 }
    1943           1 :                 data_len = rc;
    1944             : 
    1945           1 :                 rc = bdev_scsi_check_len(task, data_len, spdk_max(pllen, md));
    1946           1 :                 if (rc < 0) {
    1947           0 :                         break;
    1948             :                 }
    1949             : 
    1950           1 :                 rc = pllen;
    1951           1 :                 data_len = 0;
    1952           1 :                 break;
    1953             : 
    1954           1 :         case SPDK_SPC_MODE_SENSE_6:
    1955           1 :                 alloc_len = cdb[4];
    1956           1 :                 md = 6;
    1957             :         /* FALLTHROUGH */
    1958           2 :         case SPDK_SPC_MODE_SENSE_10:
    1959           2 :                 llba = 0;
    1960             : 
    1961           2 :                 if (md == 0) {
    1962           1 :                         alloc_len = from_be16(&cdb[7]);
    1963           1 :                         llba = !!(cdb[1] & 0x10);
    1964           1 :                         md = 10;
    1965             :                 }
    1966             : 
    1967           2 :                 dbd = !!(cdb[1] & 0x8);
    1968           2 :                 pc = (cdb[2] & 0xc0) >> 6;
    1969           2 :                 page = cdb[2] & 0x3f;
    1970           2 :                 subpage = cdb[3];
    1971             : 
    1972             :                 /* First call with no buffer to discover needed buffer size */
    1973           2 :                 rc = bdev_scsi_mode_sense(bdev, md,
    1974             :                                           cdb, dbd, llba, pc,
    1975             :                                           page, subpage,
    1976             :                                           NULL, task);
    1977           2 :                 if (rc < 0) {
    1978           0 :                         break;
    1979             :                 }
    1980             : 
    1981           2 :                 data_len = rc;
    1982           2 :                 data = calloc(1, data_len);
    1983           2 :                 assert(data != NULL);
    1984             : 
    1985             :                 /* First call with no buffer to discover needed buffer size */
    1986           2 :                 rc = bdev_scsi_mode_sense(bdev, md,
    1987             :                                           cdb, dbd, llba, pc,
    1988             :                                           page, subpage,
    1989             :                                           data, task);
    1990           2 :                 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           2 :                 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           0 :         case SPDK_SPC_LOG_SELECT:
    2031           0 :                 SPDK_DEBUGLOG(scsi, "LOG_SELECT\n");
    2032           0 :                 cmd_parsed = 1;
    2033             :         /* FALLTHROUGH */
    2034           0 :         case SPDK_SPC_LOG_SENSE:
    2035           0 :                 if (!cmd_parsed) {
    2036           0 :                         SPDK_DEBUGLOG(scsi, "LOG_SENSE\n");
    2037             :                 }
    2038             : 
    2039             :                 /* INVALID COMMAND OPERATION CODE */
    2040           0 :                 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           0 :                 rc = -1;
    2045           0 :                 break;
    2046             : 
    2047           0 :         case SPDK_SPC_TEST_UNIT_READY:
    2048           0 :                 SPDK_DEBUGLOG(scsi, "TEST_UNIT_READY\n");
    2049           0 :                 cmd_parsed = 1;
    2050             :         /* FALLTHROUGH */
    2051           0 :         case SPDK_SBC_START_STOP_UNIT:
    2052           0 :                 if (!cmd_parsed) {
    2053           0 :                         SPDK_DEBUGLOG(scsi, "START_STOP_UNIT\n");
    2054             :                 }
    2055             : 
    2056           0 :                 rc = 0;
    2057           0 :                 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           0 :         default:
    2109           0 :                 return SPDK_SCSI_TASK_UNKNOWN;
    2110             :         }
    2111             : 
    2112         262 :         if (rc >= 0 && data_len > 0) {
    2113         259 :                 assert(alloc_len >= 0);
    2114         259 :                 spdk_scsi_task_scatter_data(task, data, spdk_min(alloc_len, data_len));
    2115         259 :                 rc = spdk_min(data_len, alloc_len);
    2116             :         }
    2117             : 
    2118         262 :         if (rc >= 0) {
    2119         261 :                 task->data_transferred = rc;
    2120         261 :                 task->status = SPDK_SCSI_STATUS_GOOD;
    2121             :         }
    2122             : 
    2123         262 :         if (data) {
    2124         261 :                 free(data);
    2125             :         }
    2126             : 
    2127         262 :         return SPDK_SCSI_TASK_COMPLETE;
    2128             : }
    2129             : 
    2130             : int
    2131         280 : bdev_scsi_execute(struct spdk_scsi_task *task)
    2132             : {
    2133             :         int rc;
    2134             : 
    2135         280 :         if ((rc = bdev_scsi_process_block(task)) == SPDK_SCSI_TASK_UNKNOWN) {
    2136         262 :                 if ((rc = bdev_scsi_process_primary(task)) == SPDK_SCSI_TASK_UNKNOWN) {
    2137           0 :                         SPDK_DEBUGLOG(scsi, "unsupported SCSI OP=0x%x\n", task->cdb[0]);
    2138             :                         /* INVALID COMMAND OPERATION CODE */
    2139           0 :                         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           0 :                         return SPDK_SCSI_TASK_COMPLETE;
    2144             :                 }
    2145             :         }
    2146             : 
    2147         280 :         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           0 : bdev_scsi_reset(struct spdk_scsi_task *task)
    2160             : {
    2161           0 :         struct spdk_scsi_lun *lun = task->lun;
    2162             :         int rc;
    2163             : 
    2164           0 :         rc = spdk_bdev_reset(lun->bdev_desc, lun->io_channel, bdev_scsi_task_complete_reset,
    2165             :                              task);
    2166           0 :         if (rc == -ENOMEM) {
    2167           0 :                 bdev_scsi_queue_io(task, bdev_scsi_reset_resubmit, task);
    2168             :         }
    2169           0 : }
    2170             : 
    2171             : bool
    2172           3 : bdev_scsi_get_dif_ctx(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
    2173             :                       struct spdk_dif_ctx *dif_ctx)
    2174             : {
    2175           3 :         uint32_t ref_tag = 0, dif_check_flags = 0, data_offset;
    2176             :         uint8_t *cdb;
    2177             :         int rc;
    2178           3 :         struct spdk_dif_ctx_init_ext_opts dif_opts;
    2179             : 
    2180           3 :         if (spdk_likely(spdk_bdev_get_md_size(bdev) == 0)) {
    2181           0 :                 return false;
    2182             :         }
    2183             : 
    2184           3 :         cdb = task->cdb;
    2185           3 :         data_offset = task->offset;
    2186             : 
    2187             :         /* We use lower 32 bits of LBA as Reference. Tag */
    2188           3 :         switch (cdb[0]) {
    2189           1 :         case SPDK_SBC_READ_6:
    2190             :         case SPDK_SBC_WRITE_6:
    2191           1 :                 ref_tag = (uint32_t)cdb[1] << 16;
    2192           1 :                 ref_tag |= (uint32_t)cdb[2] << 8;
    2193           1 :                 ref_tag |= (uint32_t)cdb[3];
    2194           1 :                 break;
    2195           1 :         case SPDK_SBC_READ_10:
    2196             :         case SPDK_SBC_WRITE_10:
    2197             :         case SPDK_SBC_READ_12:
    2198             :         case SPDK_SBC_WRITE_12:
    2199           1 :                 ref_tag = from_be32(&cdb[2]);
    2200           1 :                 break;
    2201           1 :         case SPDK_SBC_READ_16:
    2202             :         case SPDK_SBC_WRITE_16:
    2203           1 :                 ref_tag = (uint32_t)from_be64(&cdb[2]);
    2204           1 :                 break;
    2205           0 :         default:
    2206           0 :                 return false;
    2207             :         }
    2208             : 
    2209           3 :         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           3 :         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           3 :         dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
    2218           3 :         dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
    2219           6 :         rc = spdk_dif_ctx_init(dif_ctx,
    2220             :                                spdk_bdev_get_block_size(bdev),
    2221             :                                spdk_bdev_get_md_size(bdev),
    2222           3 :                                spdk_bdev_is_md_interleaved(bdev),
    2223           3 :                                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           3 :         return (rc == 0) ? true : false;
    2229             : }

Generated by: LCOV version 1.15