diff options
author | Sagi Grimberg <sagig@mellanox.com> | 2014-01-23 19:29:38 +0200 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-01-25 06:58:53 +0000 |
commit | 76736db3e291246fbce9db856706af3454b0b078 (patch) | |
tree | 0dddd05312db6510a42de37659ccf4203466c9fa /drivers/target | |
parent | 676687c69697d2081d25afd14ee90937d1fb0c8e (diff) | |
download | linux-76736db3e291246fbce9db856706af3454b0b078.tar.gz |
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.c | 2 | ||||
-rw-r--r-- | drivers/target/target_core_transport.c | 16 |
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: |