aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2012-09-07 11:30:38 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2012-09-17 20:13:36 -0400
commitffe7b0e9326d9c68f5688bef691dd49f1e0d3651 (patch)
treef180001bbe2685c8388c372766e6884f2cb7845e /drivers/target
parentbf11eefcb1dc1326341ebdc44566ad08bee3f539 (diff)
target: support zero allocation length in INQUIRY
INQUIRY processing already uses an on-heap bounce buffer for loopback, but not for other fabrics. Switch this to a cheaper on-stack bounce buffer, similar to the one used by MODE SENSE and REQUEST SENSE, and use it unconditionally. With this in place, zero allocation length is handled simply by checking the return address of transport_kmap_data_sg. Testcase: sg_raw /dev/sdb 12 00 83 00 00 00 should fail with ILLEGAL REQUEST / INVALID FIELD IN CDB sense does not fail without the patch fails correctly with the series Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_spc.c31
1 files changed, 6 insertions, 25 deletions
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 388a922c8f6d..b3d8fd260374 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -600,30 +600,11 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
600{ 600{
601 struct se_device *dev = cmd->se_dev; 601 struct se_device *dev = cmd->se_dev;
602 struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; 602 struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
603 unsigned char *buf, *map_buf; 603 unsigned char *rbuf;
604 unsigned char *cdb = cmd->t_task_cdb; 604 unsigned char *cdb = cmd->t_task_cdb;
605 unsigned char buf[SE_INQUIRY_BUF];
605 int p, ret; 606 int p, ret;
606 607
607 map_buf = transport_kmap_data_sg(cmd);
608 /*
609 * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
610 * know we actually allocated a full page. Otherwise, if the
611 * data buffer is too small, allocate a temporary buffer so we
612 * don't have to worry about overruns in all our INQUIRY
613 * emulation handling.
614 */
615 if (cmd->data_length < SE_INQUIRY_BUF &&
616 (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
617 buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
618 if (!buf) {
619 transport_kunmap_data_sg(cmd);
620 cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
621 return -ENOMEM;
622 }
623 } else {
624 buf = map_buf;
625 }
626
627 if (dev == tpg->tpg_virt_lun0.lun_se_dev) 608 if (dev == tpg->tpg_virt_lun0.lun_se_dev)
628 buf[0] = 0x3f; /* Not connected */ 609 buf[0] = 0x3f; /* Not connected */
629 else 610 else
@@ -655,11 +636,11 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
655 ret = -EINVAL; 636 ret = -EINVAL;
656 637
657out: 638out:
658 if (buf != map_buf) { 639 rbuf = transport_kmap_data_sg(cmd);
659 memcpy(map_buf, buf, cmd->data_length); 640 if (rbuf) {
660 kfree(buf); 641 memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
642 transport_kunmap_data_sg(cmd);
661 } 643 }
662 transport_kunmap_data_sg(cmd);
663 644
664 if (!ret) 645 if (!ret)
665 target_complete_cmd(cmd, GOOD); 646 target_complete_cmd(cmd, GOOD);