aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2012-01-13 15:01:34 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2012-01-18 03:30:22 -0500
commit91ec1d3535b2acf12c599045cc19ad9be3c6a47b (patch)
tree12a312b34c2a932832ca02d28c082e86ab7d2813
parent9fbc8909876a2160044e71d376848973b9bfdc3f (diff)
target: Add workaround for zero-length control CDB handling
This patch adds a work-around for handling zero allocation length control CDBs (type SCF_SCSI_CONTROL_SG_IO_CDB) that was causing an OOPs with the following raw calls: # sg_raw -v /dev/sdd 3 0 0 0 0 0 # sg_raw -v /dev/sdd 0x1a 0 1 0 0 0 This patch will follow existing zero-length handling for data I/O and silently return with GOOD status. This addresses the zero length issue, but the proper long-term resolution for handling arbitary allocation lengths will be to refactor out data-phase handling in individual CDB emulation logic within target_core_cdb.c Reported-by: Roland Dreier <roland@purestorage.com> Cc: <stable@vger.kernel.org> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_transport.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 2869fb7d2c05..50d6911d4120 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -3759,6 +3759,11 @@ transport_allocate_control_task(struct se_cmd *cmd)
3759 struct se_task *task; 3759 struct se_task *task;
3760 unsigned long flags; 3760 unsigned long flags;
3761 3761
3762 /* Workaround for handling zero-length control CDBs */
3763 if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
3764 !cmd->data_length)
3765 return 0;
3766
3762 task = transport_generic_get_task(cmd, cmd->data_direction); 3767 task = transport_generic_get_task(cmd, cmd->data_direction);
3763 if (!task) 3768 if (!task)
3764 return -ENOMEM; 3769 return -ENOMEM;
@@ -3830,6 +3835,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
3830 else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) { 3835 else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) {
3831 cmd->t_state = TRANSPORT_COMPLETE; 3836 cmd->t_state = TRANSPORT_COMPLETE;
3832 atomic_set(&cmd->t_transport_active, 1); 3837 atomic_set(&cmd->t_transport_active, 1);
3838
3839 if (cmd->t_task_cdb[0] == REQUEST_SENSE) {
3840 u8 ua_asc = 0, ua_ascq = 0;
3841
3842 core_scsi3_ua_clear_for_request_sense(cmd,
3843 &ua_asc, &ua_ascq);
3844 }
3845
3833 INIT_WORK(&cmd->work, target_complete_ok_work); 3846 INIT_WORK(&cmd->work, target_complete_ok_work);
3834 queue_work(target_completion_wq, &cmd->work); 3847 queue_work(target_completion_wq, &cmd->work);
3835 return 0; 3848 return 0;