diff options
Diffstat (limited to 'drivers/target/target_core_spc.c')
-rw-r--r-- | drivers/target/target_core_spc.c | 48 |
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 | ||
657 | out: | 638 | out: |
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; |