Преглед изворни кода

vhost/scsi: switch to iov_iter_get_pages()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Al Viro пре 7 година
родитељ
комит
2f240c4ae8
1 измењених фајлова са 20 додато и 48 уклоњено
  1. 20 48
      drivers/vhost/scsi.c

+ 20 - 48
drivers/vhost/scsi.c

@@ -210,12 +210,6 @@ static struct workqueue_struct *vhost_scsi_workqueue;
 static DEFINE_MUTEX(vhost_scsi_mutex);
 static DEFINE_MUTEX(vhost_scsi_mutex);
 static LIST_HEAD(vhost_scsi_list);
 static LIST_HEAD(vhost_scsi_list);
 
 
-static int iov_num_pages(void __user *iov_base, size_t iov_len)
-{
-	return (PAGE_ALIGN((unsigned long)iov_base + iov_len) -
-	       ((unsigned long)iov_base & PAGE_MASK)) >> PAGE_SHIFT;
-}
-
 static void vhost_scsi_done_inflight(struct kref *kref)
 static void vhost_scsi_done_inflight(struct kref *kref)
 {
 {
 	struct vhost_scsi_inflight *inflight;
 	struct vhost_scsi_inflight *inflight;
@@ -618,48 +612,31 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
  */
  */
 static int
 static int
 vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd,
 vhost_scsi_map_to_sgl(struct vhost_scsi_cmd *cmd,
-		      void __user *ptr,
-		      size_t len,
+		      struct iov_iter *iter,
 		      struct scatterlist *sgl,
 		      struct scatterlist *sgl,
 		      bool write)
 		      bool write)
 {
 {
-	unsigned int npages = 0, offset, nbytes;
-	unsigned int pages_nr = iov_num_pages(ptr, len);
-	struct scatterlist *sg = sgl;
 	struct page **pages = cmd->tvc_upages;
 	struct page **pages = cmd->tvc_upages;
-	int ret, i;
-
-	if (pages_nr > VHOST_SCSI_PREALLOC_UPAGES) {
-		pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than"
-		       " preallocated VHOST_SCSI_PREALLOC_UPAGES: %u\n",
-			pages_nr, VHOST_SCSI_PREALLOC_UPAGES);
-		return -ENOBUFS;
-	}
+	struct scatterlist *sg = sgl;
+	ssize_t bytes;
+	size_t offset;
+	unsigned int npages = 0;
 
 
-	ret = get_user_pages_fast((unsigned long)ptr, pages_nr, write, pages);
+	bytes = iov_iter_get_pages(iter, pages, LONG_MAX,
+				VHOST_SCSI_PREALLOC_UPAGES, &offset);
 	/* No pages were pinned */
 	/* No pages were pinned */
-	if (ret < 0)
-		goto out;
-	/* Less pages pinned than wanted */
-	if (ret != pages_nr) {
-		for (i = 0; i < ret; i++)
-			put_page(pages[i]);
-		ret = -EFAULT;
-		goto out;
-	}
+	if (bytes <= 0)
+		return bytes < 0 ? bytes : -EFAULT;
 
 
-	while (len > 0) {
-		offset = (uintptr_t)ptr & ~PAGE_MASK;
-		nbytes = min_t(unsigned int, PAGE_SIZE - offset, len);
-		sg_set_page(sg, pages[npages], nbytes, offset);
-		ptr += nbytes;
-		len -= nbytes;
-		sg++;
-		npages++;
-	}
+	iov_iter_advance(iter, bytes);
 
 
-out:
-	return ret;
+	while (bytes) {
+		unsigned n = min_t(unsigned, PAGE_SIZE - offset, bytes);
+		sg_set_page(sg++, pages[npages++], n, offset);
+		bytes -= n;
+		offset = 0;
+	}
+	return npages;
 }
 }
 
 
 static int
 static int
@@ -687,15 +664,11 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write,
 		      struct iov_iter *iter,
 		      struct iov_iter *iter,
 		      struct scatterlist *sg, int sg_count)
 		      struct scatterlist *sg, int sg_count)
 {
 {
-	size_t off = iter->iov_offset;
 	struct scatterlist *p = sg;
 	struct scatterlist *p = sg;
-	int i, ret;
-
-	for (i = 0; i < iter->nr_segs; i++) {
-		void __user *base = iter->iov[i].iov_base + off;
-		size_t len = iter->iov[i].iov_len - off;
+	int ret;
 
 
-		ret = vhost_scsi_map_to_sgl(cmd, base, len, sg, write);
+	while (iov_iter_count(iter)) {
+		ret = vhost_scsi_map_to_sgl(cmd, iter, sg, write);
 		if (ret < 0) {
 		if (ret < 0) {
 			while (p < sg) {
 			while (p < sg) {
 				struct page *page = sg_page(p++);
 				struct page *page = sg_page(p++);
@@ -705,7 +678,6 @@ vhost_scsi_iov_to_sgl(struct vhost_scsi_cmd *cmd, bool write,
 			return ret;
 			return ret;
 		}
 		}
 		sg += ret;
 		sg += ret;
-		off = 0;
 	}
 	}
 	return 0;
 	return 0;
 }
 }