summaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2014-01-23 18:29:38 +0100
committerNicholas Bellinger <nab@linux-iscsi.org>2014-01-25 07:58:53 +0100
commit76736db3e291246fbce9db856706af3454b0b078 (patch)
tree0dddd05312db6510a42de37659ccf4203466c9fa /drivers/target
parentiscsi-target: Convert gfp_t parameter to task state bitmask (diff)
downloadlinux-76736db3e291246fbce9db856706af3454b0b078.tar.xz
linux-76736db3e291246fbce9db856706af3454b0b078.zip
target: Report bad sector in sense data for DIF errors
SPC-4 states that data-integrity errors shall also report the failed sector in CHECK_CONDITION response sense data information field. Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_sbc.c2
-rw-r--r--drivers/target/target_core_transport.c16
2 files changed, 18 insertions, 0 deletions
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 75364c7f6219..fa3cae393e13 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -1131,6 +1131,7 @@ sbc_dif_verify_write(struct se_cmd *cmd, sector_t start, unsigned int sectors,
if (rc) {
kunmap_atomic(paddr);
kunmap_atomic(daddr);
+ cmd->bad_sector = sector;
return rc;
}
@@ -1191,6 +1192,7 @@ sbc_dif_verify_read(struct se_cmd *cmd, sector_t start, unsigned int sectors,
if (rc) {
kunmap_atomic(paddr);
kunmap_atomic(daddr);
+ cmd->bad_sector = sector;
return rc;
}
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index aebe0bb3f23b..51a9736be726 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -2493,6 +2493,19 @@ static int transport_get_sense_codes(
return 0;
}
+static
+void transport_err_sector_info(unsigned char *buffer, sector_t bad_sector)
+{
+ /* Place failed LBA in sense data information descriptor 0. */
+ buffer[SPC_ADD_SENSE_LEN_OFFSET] = 0xc;
+ buffer[SPC_DESC_TYPE_OFFSET] = 0; /* Information */
+ buffer[SPC_ADDITIONAL_DESC_LEN_OFFSET] = 0xa;
+ buffer[SPC_VALIDITY_OFFSET] = 0x80;
+
+ /* Descriptor Information: failing sector */
+ put_unaligned_be64(bad_sector, &buffer[12]);
+}
+
int
transport_send_check_condition_and_sense(struct se_cmd *cmd,
sense_reason_t reason, int from_transport)
@@ -2695,6 +2708,7 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
/* LOGICAL BLOCK GUARD CHECK FAILED */
buffer[SPC_ASC_KEY_OFFSET] = 0x10;
buffer[SPC_ASCQ_KEY_OFFSET] = 0x01;
+ transport_err_sector_info(buffer, cmd->bad_sector);
break;
case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
/* CURRENT ERROR */
@@ -2705,6 +2719,7 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
/* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */
buffer[SPC_ASC_KEY_OFFSET] = 0x10;
buffer[SPC_ASCQ_KEY_OFFSET] = 0x02;
+ transport_err_sector_info(buffer, cmd->bad_sector);
break;
case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
/* CURRENT ERROR */
@@ -2715,6 +2730,7 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
/* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
buffer[SPC_ASC_KEY_OFFSET] = 0x10;
buffer[SPC_ASCQ_KEY_OFFSET] = 0x03;
+ transport_err_sector_info(buffer, cmd->bad_sector);
break;
case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE:
default: