summaryrefslogtreecommitdiffstats
path: root/drivers/target/loopback/tcm_loop.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-11-06 19:00:42 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-11-06 19:00:42 -0800
commit6aad3738f6a79fd0ca480eaceefe064cc471f6eb (patch)
tree08fb9ec4824bf3320af01f29fe84b75f814c0fa0 /drivers/target/loopback/tcm_loop.c
parent02ebbbd481635fd3ce7018e5bb19c18c0f1e4561 (diff)
parent5bda90c8f20f0af93375721533f4081a40fa6f41 (diff)
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: target: use ->exectute_task for all CDB emulation target: remove SCF_EMULATE_CDB_ASYNC target: refactor transport_emulate_control_cdb target: pass the se_task to the CDB emulation callback target: split core_scsi3_emulate_pr target: split core_scsi2_emulate_crh target: Add generic active I/O shutdown logic target: add back error handling in transport_complete_task target/pscsi: blk_make_request() returns an ERR_PTR() target: Remove core TRANSPORT_FREE_CMD_INTR usage target: Make TFO->check_stop_free return free status iscsi-target: Fix non-immediate TMR handling iscsi-target: Add missing CMDSN_LOWER_THAN_EXP check in iscsit_handle_scsi_cmd target: Avoid double list_del for aborted se_tmr_req target: Minor cleanups to core_tmr_drain_tmr_list target: Fix wrong se_tmr being added to drain_tmr_list target: Fix incorrect se_cmd assignment in core_tmr_drain_tmr_list target: Check -ENOMEM to signal QUEUE_FULL from fabric callbacks tcm_loop: Add explict read buffer memset for SCF_SCSI_CONTROL_SG_IO_CDB target: Fix compile warning w/ missing module.h include
Diffstat (limited to 'drivers/target/loopback/tcm_loop.c')
-rw-r--r--drivers/target/loopback/tcm_loop.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index b15d8cbf630..3df1c9b8ae6 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -174,6 +174,24 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
sgl_bidi = sdb->table.sgl;
sgl_bidi_count = sdb->table.nents;
}
+ /*
+ * Because some userspace code via scsi-generic do not memset their
+ * associated read buffers, go ahead and do that here for type
+ * SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently
+ * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
+ * by target core in transport_generic_allocate_tasks() ->
+ * transport_generic_cmd_sequencer().
+ */
+ if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
+ se_cmd->data_direction == DMA_FROM_DEVICE) {
+ struct scatterlist *sg = scsi_sglist(sc);
+ unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
+
+ if (buf != NULL) {
+ memset(buf, 0, sg->length);
+ kunmap(sg_page(sg));
+ }
+ }
/* Tell the core about our preallocated memory */
ret = transport_generic_map_mem_to_cmd(se_cmd, scsi_sglist(sc),
@@ -187,7 +205,7 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd)
/*
* Called from struct target_core_fabric_ops->check_stop_free()
*/
-static void tcm_loop_check_stop_free(struct se_cmd *se_cmd)
+static int tcm_loop_check_stop_free(struct se_cmd *se_cmd)
{
/*
* Do not release struct se_cmd's containing a valid TMR
@@ -195,12 +213,13 @@ static void tcm_loop_check_stop_free(struct se_cmd *se_cmd)
* with transport_generic_free_cmd().
*/
if (se_cmd->se_tmr_req)
- return;
+ return 0;
/*
* Release the struct se_cmd, which will make a callback to release
* struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd()
*/
transport_generic_free_cmd(se_cmd, 0);
+ return 1;
}
static void tcm_loop_release_cmd(struct se_cmd *se_cmd)