diff options
-rw-r--r-- | drivers/target/target_core_sbc.c | 2 | ||||
-rw-r--r-- | drivers/target/target_core_transport.c | 16 | ||||
-rw-r--r-- | include/target/target_core_base.h | 5 |
3 files changed, 22 insertions, 1 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: diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 0336d70d0d9f..d28418645b00 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -37,6 +37,9 @@ /* Used by transport_send_check_condition_and_sense() */ #define SPC_SENSE_KEY_OFFSET 2 #define SPC_ADD_SENSE_LEN_OFFSET 7 +#define SPC_DESC_TYPE_OFFSET 8 +#define SPC_ADDITIONAL_DESC_LEN_OFFSET 9 +#define SPC_VALIDITY_OFFSET 10 #define SPC_ASC_KEY_OFFSET 12 #define SPC_ASCQ_KEY_OFFSET 13 #define TRANSPORT_IQN_LEN 224 @@ -560,7 +563,7 @@ struct se_cmd { unsigned int t_prot_nents; enum target_prot_ho prot_handover; sense_reason_t pi_err; - u32 block_num; + sector_t bad_sector; }; struct se_ua { |