aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-01-29 17:10:01 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2013-01-29 17:24:20 -0500
commitcab9609b449ae5a6875d7d4cef32a814527a3baa (patch)
treec07eb1b9d9b5758e300177de0faae75dff7e5304 /drivers/target
parent49df9fc9b9fd41e5749c5a9be2d2076328f75fc7 (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.c35
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
977set_length: 956set_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}