target: Return descriptor format sense data in case the LU spans 64bit sectors
authorSagi Grimberg <sagig@mellanox.com>
Thu, 16 Jul 2015 07:28:05 +0000 (10:28 +0300)
committerNicholas Bellinger <nab@linux-iscsi.org>
Fri, 24 Jul 2015 05:54:21 +0000 (22:54 -0700)
In case a LU spans 64bit sectors, fixed size sense data information
field is only 32 bits which means the sector information will be truncated.

Thus, if the LU spans 64bit sectors, use descriptor format sense data to
correctly report sector information.

Reported-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/target_core_hba.c
drivers/target/target_core_spc.c
drivers/target/target_core_transport.c
include/target/target_core_backend.h

index 62ea4e8e70a8935398f2a0e86fc44627dfa3368e..d746a3a4a623c306a533bed561a4ec07dd072141 100644 (file)
@@ -176,3 +176,8 @@ core_delete_hba(struct se_hba *hba)
        kfree(hba);
        return 0;
 }
+
+bool target_sense_desc_format(struct se_device *dev)
+{
+       return dev->transport->get_blocks(dev) > U32_MAX;
+}
index c43dcbf2d48e50fd9f5ab43b34e7d1d8a71b4e4b..b949d335a6ba8c7037f6993b8f6196f494a1258f 100644 (file)
@@ -761,7 +761,12 @@ static int spc_modesense_control(struct se_cmd *cmd, u8 pc, u8 *p)
        if (pc == 1)
                goto out;
 
-       p[2] = 2;
+       /* GLTSD: No implicit save of log parameters */
+       p[2] = (1 << 1);
+       if (target_sense_desc_format(dev))
+               /* D_SENSE: Descriptor format sense data for 64bit sectors */
+               p[2] |= (1 << 2);
+
        /*
         * From spc4r23, 7.4.7 Control mode page
         *
@@ -1144,6 +1149,7 @@ static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd)
        unsigned char *rbuf;
        u8 ua_asc = 0, ua_ascq = 0;
        unsigned char buf[SE_SENSE_BUF];
+       bool desc_format = target_sense_desc_format(cmd->se_dev);
 
        memset(buf, 0, SE_SENSE_BUF);
 
@@ -1158,10 +1164,10 @@ static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd)
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
        if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq))
-               scsi_build_sense_buffer(0, buf, UNIT_ATTENTION,
+               scsi_build_sense_buffer(desc_format, buf, UNIT_ATTENTION,
                                        ua_asc, ua_ascq);
        else
-               scsi_build_sense_buffer(0, buf, NO_SENSE, 0x0, 0x0);
+               scsi_build_sense_buffer(desc_format, buf, NO_SENSE, 0x0, 0x0);
 
        memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
        transport_kunmap_data_sg(cmd);
index 7fb031bbcc8d142f6e489e912587cb1b83d83e6d..98155db28365bcaf836c12a0256283e03e0af52d 100644 (file)
@@ -2735,6 +2735,7 @@ static int translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason)
        u8 *buffer = cmd->sense_buffer;
        int r = (__force int)reason;
        u8 asc, ascq;
+       bool desc_format = target_sense_desc_format(cmd->se_dev);
 
        if (r < ARRAY_SIZE(sense_info_table) && sense_info_table[r].key)
                si = &sense_info_table[r];
@@ -2754,7 +2755,7 @@ static int translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason)
                ascq = si->ascq;
        }
 
-       scsi_build_sense_buffer(0, buffer, si->key, asc, ascq);
+       scsi_build_sense_buffer(desc_format, buffer, si->key, asc, ascq);
        if (si->add_sector_info)
                return scsi_set_sense_information(buffer,
                                                  cmd->scsi_sense_length,
index 1e5c8f949bae4947b8645bd1cf9d7d8966708713..56cf8e485ef22101ac22b1120704664bf599eaef 100644 (file)
@@ -93,4 +93,6 @@ bool  target_lun_is_rdonly(struct se_cmd *);
 sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd,
        sense_reason_t (*exec_cmd)(struct se_cmd *cmd));
 
+bool target_sense_desc_format(struct se_device *dev);
+
 #endif /* TARGET_CORE_BACKEND_H */