aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vhost
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2014-02-22 21:34:08 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-06-02 15:41:54 -0400
commit5a01d08217e39f3d36d3ca160361c7b019ff1598 (patch)
tree15d4b1d9b66bd8e6dce24569c93f718cac1d8bab /drivers/vhost
parent1b49dcf3d7c765ad18ca7167a0e441824eb1f7af (diff)
vhost/scsi: Move sanity check into vhost_scsi_map_iov_to_sgl
Move the overflow check for sgl_count > TCM_VHOST_PREALLOC_SGLS into vhost_scsi_map_iov_to_sgl() so that it's based on the total number of SGLs for all IOVs, instead of single IOVs. Also, rename TCM_VHOST_PREALLOC_PAGES -> TCM_VHOST_PREALLOC_UPAGES to better describe pointers to user-space pages. Cc: Michael S. Tsirkin <mst@redhat.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Martin K. Petersen <martin.petersen@oracle.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Hannes Reinecke <hare@suse.de> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/vhost')
-rw-r--r--drivers/vhost/scsi.c59
1 files changed, 25 insertions, 34 deletions
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index cf50ce93975b..ae434db2d384 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -57,7 +57,7 @@
57#define TCM_VHOST_MAX_CDB_SIZE 32 57#define TCM_VHOST_MAX_CDB_SIZE 32
58#define TCM_VHOST_DEFAULT_TAGS 256 58#define TCM_VHOST_DEFAULT_TAGS 256
59#define TCM_VHOST_PREALLOC_SGLS 2048 59#define TCM_VHOST_PREALLOC_SGLS 2048
60#define TCM_VHOST_PREALLOC_PAGES 2048 60#define TCM_VHOST_PREALLOC_UPAGES 2048
61 61
62struct vhost_scsi_inflight { 62struct vhost_scsi_inflight {
63 /* Wait for the flush operation to finish */ 63 /* Wait for the flush operation to finish */
@@ -767,35 +767,28 @@ vhost_scsi_map_to_sgl(struct tcm_vhost_cmd *tv_cmd,
767 struct scatterlist *sgl, 767 struct scatterlist *sgl,
768 unsigned int sgl_count, 768 unsigned int sgl_count,
769 struct iovec *iov, 769 struct iovec *iov,
770 int write) 770 struct page **pages,
771 bool write)
771{ 772{
772 unsigned int npages = 0, pages_nr, offset, nbytes; 773 unsigned int npages = 0, pages_nr, offset, nbytes;
773 struct scatterlist *sg = sgl; 774 struct scatterlist *sg = sgl;
774 void __user *ptr = iov->iov_base; 775 void __user *ptr = iov->iov_base;
775 size_t len = iov->iov_len; 776 size_t len = iov->iov_len;
776 struct page **pages;
777 int ret, i; 777 int ret, i;
778 778
779 if (sgl_count > TCM_VHOST_PREALLOC_SGLS) {
780 pr_err("vhost_scsi_map_to_sgl() psgl_count: %u greater than"
781 " preallocated TCM_VHOST_PREALLOC_SGLS: %u\n",
782 sgl_count, TCM_VHOST_PREALLOC_SGLS);
783 return -ENOBUFS;
784 }
785
786 pages_nr = iov_num_pages(iov); 779 pages_nr = iov_num_pages(iov);
787 if (pages_nr > sgl_count) 780 if (pages_nr > sgl_count) {
781 pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than"
782 " sgl_count: %u\n", pages_nr, sgl_count);
788 return -ENOBUFS; 783 return -ENOBUFS;
789 784 }
790 if (pages_nr > TCM_VHOST_PREALLOC_PAGES) { 785 if (pages_nr > TCM_VHOST_PREALLOC_UPAGES) {
791 pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than" 786 pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than"
792 " preallocated TCM_VHOST_PREALLOC_PAGES: %u\n", 787 " preallocated TCM_VHOST_PREALLOC_UPAGES: %u\n",
793 pages_nr, TCM_VHOST_PREALLOC_PAGES); 788 pages_nr, TCM_VHOST_PREALLOC_UPAGES);
794 return -ENOBUFS; 789 return -ENOBUFS;
795 } 790 }
796 791
797 pages = tv_cmd->tvc_upages;
798
799 ret = get_user_pages_fast((unsigned long)ptr, pages_nr, write, pages); 792 ret = get_user_pages_fast((unsigned long)ptr, pages_nr, write, pages);
800 /* No pages were pinned */ 793 /* No pages were pinned */
801 if (ret < 0) 794 if (ret < 0)
@@ -825,33 +818,32 @@ out:
825static int 818static int
826vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd, 819vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
827 struct iovec *iov, 820 struct iovec *iov,
828 unsigned int niov, 821 int niov,
829 int write) 822 bool write)
830{ 823{
831 int ret; 824 struct scatterlist *sg = cmd->tvc_sgl;
832 unsigned int i; 825 unsigned int sgl_count = 0;
833 u32 sgl_count; 826 int ret, i;
834 struct scatterlist *sg;
835 827
836 /*
837 * Find out how long sglist needs to be
838 */
839 sgl_count = 0;
840 for (i = 0; i < niov; i++) 828 for (i = 0; i < niov; i++)
841 sgl_count += iov_num_pages(&iov[i]); 829 sgl_count += iov_num_pages(&iov[i]);
842 830
843 /* TODO overflow checking */ 831 if (sgl_count > TCM_VHOST_PREALLOC_SGLS) {
832 pr_err("vhost_scsi_map_iov_to_sgl() sgl_count: %u greater than"
833 " preallocated TCM_VHOST_PREALLOC_SGLS: %u\n",
834 sgl_count, TCM_VHOST_PREALLOC_SGLS);
835 return -ENOBUFS;
836 }
844 837
845 sg = cmd->tvc_sgl;
846 pr_debug("%s sg %p sgl_count %u\n", __func__, sg, sgl_count); 838 pr_debug("%s sg %p sgl_count %u\n", __func__, sg, sgl_count);
847 sg_init_table(sg, sgl_count); 839 sg_init_table(sg, sgl_count);
848
849 cmd->tvc_sgl_count = sgl_count; 840 cmd->tvc_sgl_count = sgl_count;
850 841
851 pr_debug("Mapping %u iovecs for %u pages\n", niov, sgl_count); 842 pr_debug("Mapping iovec %p for %u pages\n", &iov[0], sgl_count);
843
852 for (i = 0; i < niov; i++) { 844 for (i = 0; i < niov; i++) {
853 ret = vhost_scsi_map_to_sgl(cmd, sg, sgl_count, &iov[i], 845 ret = vhost_scsi_map_to_sgl(cmd, sg, sgl_count, &iov[i],
854 write); 846 cmd->tvc_upages, write);
855 if (ret < 0) { 847 if (ret < 0) {
856 for (i = 0; i < cmd->tvc_sgl_count; i++) 848 for (i = 0; i < cmd->tvc_sgl_count; i++)
857 put_page(sg_page(&cmd->tvc_sgl[i])); 849 put_page(sg_page(&cmd->tvc_sgl[i]));
@@ -859,7 +851,6 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
859 cmd->tvc_sgl_count = 0; 851 cmd->tvc_sgl_count = 0;
860 return ret; 852 return ret;
861 } 853 }
862
863 sg += ret; 854 sg += ret;
864 sgl_count -= ret; 855 sgl_count -= ret;
865 } 856 }
@@ -1765,7 +1756,7 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tpg,
1765 } 1756 }
1766 1757
1767 tv_cmd->tvc_upages = kzalloc(sizeof(struct page *) * 1758 tv_cmd->tvc_upages = kzalloc(sizeof(struct page *) *
1768 TCM_VHOST_PREALLOC_PAGES, GFP_KERNEL); 1759 TCM_VHOST_PREALLOC_UPAGES, GFP_KERNEL);
1769 if (!tv_cmd->tvc_upages) { 1760 if (!tv_cmd->tvc_upages) {
1770 mutex_unlock(&tpg->tv_tpg_mutex); 1761 mutex_unlock(&tpg->tv_tpg_mutex);
1771 pr_err("Unable to allocate tv_cmd->tvc_upages\n"); 1762 pr_err("Unable to allocate tv_cmd->tvc_upages\n");