aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-09-24 22:07:59 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2017-10-11 22:36:55 -0400
commit2f240c4ae8869907d4c8161ee015bedb366512e2 (patch)
treec5d4a0f96711386df3da29beca154b553cbb4ca8
parent11d49e9d089ccec81be87c2386dfdd010d7f7f6e (diff)
vhost/scsi: switch to iov_iter_get_pages()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--drivers/vhost/scsi.c68
1 files changed, 20 insertions, 48 deletions
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index e47c5bc3ddca..e5b18320f1a3 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -210,12 +210,6 @@ static struct workqueue_struct *vhost_scsi_workqueue;
210static DEFINE_MUTEX(vhost_scsi_mutex); 210static DEFINE_MUTEX(vhost_scsi_mutex);
211static LIST_HEAD(vhost_scsi_list); 211static LIST_HEAD(vhost_scsi_list);
212 212
213static int iov_num_pages(void __user *iov_base, size_t iov_len)
214{
215 return (PAGE_ALIGN((unsigned long)iov_base + iov_len) -
216 ((unsigned long)iov_base & PAGE_MASK)) >> PAGE_SHIFT;
217}
218
219static void vhost_scsi_done_inflight(struct kref *kref) 213static void vhost_scsi_done_inflight(struct kref *kref)
220{ 214{
221 struct vhost_scsi_inflight *inflight; 215 struct vhost_scsi_inflight *inflight;
@@ -618,48 +612,31 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
618 */ 612 */
619static int 613static int
620vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd, 614vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd,
621 void __user *ptr, 615 struct iov_iter *iter,
622 size_t len,
623 struct scatterlist *sgl, 616 struct scatterlist *sgl,
624 bool write) 617 bool write)
625{ 618{
626 unsigned int npages = 0, offset, nbytes;
627 unsigned int pages_nr = iov_num_pages(ptr, len);
628 struct scatterlist *sg = sgl;
629 struct page **pages = cmd->tvc_upages; 619 struct page **pages = cmd->tvc_upages;
630 int ret, i; 620 struct scatterlist *sg = sgl;
631 621 ssize_t bytes;
632 if (pages_nr > VHOST_SCSI_PREALLOC_UPAGES) { 622 size_t offset;
633 pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than" 623 unsigned int npages = 0;
634 " preallocated VHOST_SCSI_PREALLOC_UPAGES: %u\n",
635 pages_nr, VHOST_SCSI_PREALLOC_UPAGES);
636 return -ENOBUFS;
637 }
638 624
639 ret = get_user_pages_fast((unsigned long)ptr, pages_nr, write, pages); 625 bytes = iov_iter_get_pages(iter, pages, LONG_MAX,
626 VHOST_SCSI_PREALLOC_UPAGES, &offset);
640 /* No pages were pinned */ 627 /* No pages were pinned */
641 if (ret < 0) 628 if (bytes <= 0)
642 goto out; 629 return bytes < 0 ? bytes : -EFAULT;
643 /* Less pages pinned than wanted */
644 if (ret != pages_nr) {
645 for (i = 0; i < ret; i++)
646 put_page(pages[i]);
647 ret = -EFAULT;
648 goto out;
649 }
650 630
651 while (len > 0) { 631 iov_iter_advance(iter, bytes);
652 offset = (uintptr_t)ptr & ~PAGE_MASK;
653 nbytes = min_t(unsigned int, PAGE_SIZE - offset, len);
654 sg_set_page(sg, pages[npages], nbytes, offset);
655 ptr += nbytes;
656 len -= nbytes;
657 sg++;
658 npages++;
659 }
660 632
661out: 633 while (bytes) {
662 return ret; 634 unsigned n = min_t(unsigned, PAGE_SIZE - offset, bytes);
635 sg_set_page(sg++, pages[npages++], n, offset);
636 bytes -= n;
637 offset = 0;
638 }
639 return npages;
663} 640}
664 641
665static int 642static int
@@ -687,15 +664,11 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write,
687 struct iov_iter *iter, 664 struct iov_iter *iter,
688 struct scatterlist *sg, int sg_count) 665 struct scatterlist *sg, int sg_count)
689{ 666{
690 size_t off = iter->iov_offset;
691 struct scatterlist *p = sg; 667 struct scatterlist *p = sg;
692 int i, ret; 668 int ret;
693
694 for (i = 0; i < iter->nr_segs; i++) {
695 void __user *base = iter->iov[i].iov_base + off;
696 size_t len = iter->iov[i].iov_len - off;
697 669
698 ret = vhost_scsi_map_to_sgl(cmd, base, len, sg, write); 670 while (iov_iter_count(iter)) {
671 ret = vhost_scsi_map_to_sgl(cmd, iter, sg, write);
699 if (ret < 0) { 672 if (ret < 0) {
700 while (p < sg) { 673 while (p < sg) {
701 struct page *page = sg_page(p++); 674 struct page *page = sg_page(p++);
@@ -705,7 +678,6 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write,
705 return ret; 678 return ret;
706 } 679 }
707 sg += ret; 680 sg += ret;
708 off = 0;
709 } 681 }
710 return 0; 682 return 0;
711} 683}