diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-01-29 17:10:01 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-01-29 17:24:20 -0500 |
commit | cab9609b449ae5a6875d7d4cef32a814527a3baa (patch) | |
tree | c07eb1b9d9b5758e300177de0faae75dff7e5304 /drivers/target | |
parent | 49df9fc9b9fd41e5749c5a9be2d2076328f75fc7 (diff) |
target: Fix zero-length MODE_SENSE regression
This patch fixes a regression introduced in v3.8-rc1 code where
a zero-length MODE_SENSE was no longer returning GOOD status, but
instead returning TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE to generate
a CHECK_CONDITION status.
This regression was introduced with the following commit:
commit de103c93aff0bed0ae984274e5dc8b95899badab
Author: Christoph Hellwig <hch@lst.de>
Date: Tue Nov 6 12:24:09 2012 -0800
target: pass sense_reason as a return value
and this patch has been tested with the following zero-length CDB:
sg_raw /dev/sdd 5a 00 0a 00 00 00 00 00 00 00
SCSI Status: Good
Sense Information:
sense buffer empty
Cc: Christoph Hellwig <hch@lst.de>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Roland Dreier <roland@purestorage.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_spc.c | 35 |
1 files changed, 7 insertions, 28 deletions
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index f8857d4eac66..2d88f087d961 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c | |||
@@ -850,7 +850,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | |||
850 | { | 850 | { |
851 | struct se_device *dev = cmd->se_dev; | 851 | struct se_device *dev = cmd->se_dev; |
852 | char *cdb = cmd->t_task_cdb; | 852 | char *cdb = cmd->t_task_cdb; |
853 | unsigned char *buf, *map_buf; | 853 | unsigned char buf[SE_MODE_PAGE_BUF], *rbuf; |
854 | int type = dev->transport->get_device_type(dev); | 854 | int type = dev->transport->get_device_type(dev); |
855 | int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); | 855 | int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); |
856 | bool dbd = !!(cdb[1] & 0x08); | 856 | bool dbd = !!(cdb[1] & 0x08); |
@@ -862,26 +862,8 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | |||
862 | int ret; | 862 | int ret; |
863 | int i; | 863 | int i; |
864 | 864 | ||
865 | map_buf = transport_kmap_data_sg(cmd); | 865 | memset(buf, 0, SE_MODE_PAGE_BUF); |
866 | if (!map_buf) | 866 | |
867 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
868 | /* | ||
869 | * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we | ||
870 | * know we actually allocated a full page. Otherwise, if the | ||
871 | * data buffer is too small, allocate a temporary buffer so we | ||
872 | * don't have to worry about overruns in all our INQUIRY | ||
873 | * emulation handling. | ||
874 | */ | ||
875 | if (cmd->data_length < SE_MODE_PAGE_BUF && | ||
876 | (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) { | ||
877 | buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL); | ||
878 | if (!buf) { | ||
879 | transport_kunmap_data_sg(cmd); | ||
880 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
881 | } | ||
882 | } else { | ||
883 | buf = map_buf; | ||
884 | } | ||
885 | /* | 867 | /* |
886 | * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for | 868 | * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for |
887 | * MODE_SENSE_10 and byte 2 for MODE_SENSE (6). | 869 | * MODE_SENSE_10 and byte 2 for MODE_SENSE (6). |
@@ -933,8 +915,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | |||
933 | if (page == 0x3f) { | 915 | if (page == 0x3f) { |
934 | if (subpage != 0x00 && subpage != 0xff) { | 916 | if (subpage != 0x00 && subpage != 0xff) { |
935 | pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage); | 917 | pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage); |
936 | kfree(buf); | ||
937 | transport_kunmap_data_sg(cmd); | ||
938 | return TCM_INVALID_CDB_FIELD; | 918 | return TCM_INVALID_CDB_FIELD; |
939 | } | 919 | } |
940 | 920 | ||
@@ -971,7 +951,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | |||
971 | pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", | 951 | pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", |
972 | page, subpage); | 952 | page, subpage); |
973 | 953 | ||
974 | transport_kunmap_data_sg(cmd); | ||
975 | return TCM_UNKNOWN_MODE_PAGE; | 954 | return TCM_UNKNOWN_MODE_PAGE; |
976 | 955 | ||
977 | set_length: | 956 | set_length: |
@@ -980,12 +959,12 @@ set_length: | |||
980 | else | 959 | else |
981 | buf[0] = length - 1; | 960 | buf[0] = length - 1; |
982 | 961 | ||
983 | if (buf != map_buf) { | 962 | rbuf = transport_kmap_data_sg(cmd); |
984 | memcpy(map_buf, buf, cmd->data_length); | 963 | if (rbuf) { |
985 | kfree(buf); | 964 | memcpy(rbuf, buf, min_t(u32, SE_MODE_PAGE_BUF, cmd->data_length)); |
965 | transport_kunmap_data_sg(cmd); | ||
986 | } | 966 | } |
987 | 967 | ||
988 | transport_kunmap_data_sg(cmd); | ||
989 | target_complete_cmd(cmd, GOOD); | 968 | target_complete_cmd(cmd, GOOD); |
990 | return 0; | 969 | return 0; |
991 | } | 970 | } |