aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/target_core_spc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/target/target_core_spc.c')
-rw-r--r--drivers/target/target_core_spc.c48
1 files changed, 13 insertions, 35 deletions
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 388a922c8f6d..9229bd9ad61b 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);
@@ -803,7 +784,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
803 unsigned char *rbuf; 784 unsigned char *rbuf;
804 int type = dev->transport->get_device_type(dev); 785 int type = dev->transport->get_device_type(dev);
805 int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); 786 int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
806 int offset = ten ? 8 : 4; 787 u32 offset = ten ? 8 : 4;
807 int length = 0; 788 int length = 0;
808 unsigned char buf[SE_MODE_PAGE_BUF]; 789 unsigned char buf[SE_MODE_PAGE_BUF];
809 790
@@ -836,6 +817,7 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
836 offset -= 2; 817 offset -= 2;
837 buf[0] = (offset >> 8) & 0xff; 818 buf[0] = (offset >> 8) & 0xff;
838 buf[1] = offset & 0xff; 819 buf[1] = offset & 0xff;
820 offset += 2;
839 821
840 if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || 822 if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
841 (cmd->se_deve && 823 (cmd->se_deve &&
@@ -845,13 +827,10 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
845 if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && 827 if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
846 (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) 828 (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
847 spc_modesense_dpofua(&buf[3], type); 829 spc_modesense_dpofua(&buf[3], type);
848
849 if ((offset + 2) > cmd->data_length)
850 offset = cmd->data_length;
851
852 } else { 830 } else {
853 offset -= 1; 831 offset -= 1;
854 buf[0] = offset & 0xff; 832 buf[0] = offset & 0xff;
833 offset += 1;
855 834
856 if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) || 835 if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
857 (cmd->se_deve && 836 (cmd->se_deve &&
@@ -861,14 +840,13 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
861 if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) && 840 if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
862 (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0)) 841 (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
863 spc_modesense_dpofua(&buf[2], type); 842 spc_modesense_dpofua(&buf[2], type);
864
865 if ((offset + 1) > cmd->data_length)
866 offset = cmd->data_length;
867 } 843 }
868 844
869 rbuf = transport_kmap_data_sg(cmd); 845 rbuf = transport_kmap_data_sg(cmd);
870 memcpy(rbuf, buf, offset); 846 if (rbuf) {
871 transport_kunmap_data_sg(cmd); 847 memcpy(rbuf, buf, min(offset, cmd->data_length));
848 transport_kunmap_data_sg(cmd);
849 }
872 850
873 target_complete_cmd(cmd, GOOD); 851 target_complete_cmd(cmd, GOOD);
874 return 0; 852 return 0;