[RFCv2 02/12] vhost: Isolate reusable vring related functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Prepare for moving virtio ring code out to a separate
file by isolating vring related functions. The function
vring_add_used_user() and vring_avail_desc_user() that
are handling virtio rings from user space are prepared
to be moved out.

Signed-off-by: Sjur Brændeland <sjur.brandeland@xxxxxxxxxxxxxx>
---
 drivers/vhost/vhost.c |  119 ++++++++++++++++++++++++++++--------------------
 1 files changed, 69 insertions(+), 50 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 0a676f1..5e91048 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1100,7 +1100,7 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
 /* Each buffer in the virtqueues is actually a chain of descriptors.  This
  * function returns the next descriptor in the chain,
  * or -1U if we're at the end. */
-static unsigned next_desc(struct vring_desc *desc)
+unsigned vring_next_desc(struct vring_desc *desc)
 {
 	unsigned int next;
 
@@ -1202,46 +1202,29 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
 			}
 			*out_num += ret;
 		}
-	} while ((i = next_desc(&desc)) != -1);
+	} while ((i = vring_next_desc(&desc)) != -1);
 	return 0;
 }
 
-/* This looks in the virtqueue and for the first available buffer, and converts
- * it to an iovec for convenient access.  Since descriptors consist of some
- * number of output then some number of input descriptors, it's actually two
- * iovecs, but we pack them into one and note how many of each there were.
- *
- * This function returns the descriptor number found, or vq->num (which is
- * never a valid descriptor number) if none was found.  A negative code is
- * returned on error. */
-int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
-		      struct iovec iov[], unsigned int iov_size,
-		      unsigned int *out_num, unsigned int *in_num,
-		      struct vhost_log *log, unsigned int *log_num)
+static int vring_avail_desc_user(struct vring_host *vh)
 {
-	struct vring_desc desc;
-	unsigned int i, head, found = 0;
+	int head;
 	u16 last_avail_idx;
-	int ret;
 
 	/* Check it isn't doing very strange things with descriptor numbers. */
-	last_avail_idx = vq->hst.last_avail_idx;
-	if (unlikely(__get_user(vq->hst.avail_idx, &vq->hst.vr.avail->idx))) {
-		vq_err(vq, "Failed to access avail idx at %p\n",
-		       &vq->hst.vr.avail->idx);
+	last_avail_idx = vh->last_avail_idx;
+	if (unlikely(__get_user(vh->avail_idx, &vh->vr.avail->idx))) {
+		pr_debug("Failed to access avail idx at %p\n",
+		       &vh->vr.avail->idx);
 		return -EFAULT;
 	}
 
-	if (unlikely((u16)(vq->hst.avail_idx -
-			   last_avail_idx) > vq->hst.vr.num)) {
-		vq_err(vq, "Guest moved used index from %u to %u",
-		       last_avail_idx, vq->hst.avail_idx);
+	if (unlikely((u16)(vh->avail_idx - last_avail_idx) > vh->vr.num))
 		return -EFAULT;
-	}
 
 	/* If there's nothing new since last we looked, return invalid. */
-	if (vq->hst.avail_idx == last_avail_idx)
-		return vq->hst.vr.num;
+	if (vh->avail_idx == last_avail_idx)
+		return vh->vr.num;
 
 	/* Only get avail ring entries after they have been exposed by guest. */
 	smp_rmb();
@@ -1249,22 +1232,46 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
 	/* Grab the next descriptor number they're advertising, and increment
 	 * the index we've seen. */
 	if (unlikely(__get_user(head,
-				&vq->hst.vr.avail->ring[last_avail_idx %
-							vq->hst.vr.num]))) {
-		vq_err(vq, "Failed to read head: idx %d address %p\n",
-		       last_avail_idx,
-		       &vq->hst.vr.avail->ring[last_avail_idx %
-					       vq->hst.vr.num]);
+				&vh->vr.avail->ring[last_avail_idx %
+							vh->vr.num]))) {
+		pr_debug("Failed to read head: idx %d address %p\n",
+			 last_avail_idx,
+		       &vh->vr.avail->ring[last_avail_idx %
+					       vh->vr.num]);
 		return -EFAULT;
 	}
 
 	/* If their number is silly, that's an error. */
-	if (unlikely(head >= vq->hst.vr.num)) {
-		vq_err(vq, "Guest says index %u > %u is available",
-		       head, vq->hst.vr.num);
+	if (unlikely(head >= vh->vr.num)) {
+		pr_debug("Guest says index %u > %u is available",
+		       head, vh->vr.num);
 		return -EINVAL;
 	}
 
+	return head;
+}
+
+/* This looks in the virtqueue and for the first available buffer, and converts
+ * it to an iovec for convenient access.  Since descriptors consist of some
+ * number of output then some number of input descriptors, it's actually two
+ * iovecs, but we pack them into one and note how many of each there were.
+ *
+ * This function returns the descriptor number found, or vq->num (which is
+ * never a valid descriptor number) if none was found.  A negative code is
+ * returned on error. */
+int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
+		      struct iovec iov[], unsigned int iov_size,
+		      unsigned int *out_num, unsigned int *in_num,
+		      struct vhost_log *log, unsigned int *log_num)
+{
+	struct vring_desc desc;
+	unsigned int i, head, found = 0;
+	int ret;
+
+	head = vring_avail_desc_user(&vq->hst);
+	if (head < 0)
+		vq_err(vq, "virtqueue_next_avail failed\n");
+
 	/* When we start there are none of either input nor output. */
 	*out_num = *in_num = 0;
 	if (unlikely(log))
@@ -1328,7 +1335,7 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
 			}
 			*out_num += ret;
 		}
-	} while ((i = next_desc(&desc)) != -1);
+	} while ((i = vring_next_desc(&desc)) != -1);
 
 	/* On success, increment avail index. */
 	vq->hst.last_avail_idx++;
@@ -1345,29 +1352,41 @@ void vhost_discard_vq_desc(struct vhost_virtqueue *vq, int n)
 	vq->hst.last_avail_idx -= n;
 }
 
-/* After we've used one of their buffers, we tell them about it.  We'll then
- * want to notify the guest, using eventfd. */
-int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len)
+struct vring_used_elem *vring_add_used_user(struct vring_host *vh,
+				     unsigned int head, int len)
 {
-	struct vring_used_elem __user *used;
+	struct vring_used_elem  *used;
 
 	/* The virtqueue contains a ring of used buffers.  Get a pointer to the
 	 * next entry in that used ring. */
-	used = &vq->hst.vr.used->ring[vq->hst.last_used_idx % vq->hst.vr.num];
+	used = &vh->vr.used->ring[vh->last_used_idx % vh->vr.num];
 	if (__put_user(head, &used->id)) {
-		vq_err(vq, "Failed to write used id");
-		return -EFAULT;
+		pr_debug("Failed to write used id");
+		return NULL;
 	}
 	if (__put_user(len, &used->len)) {
-		vq_err(vq, "Failed to write used len");
-		return -EFAULT;
+		pr_debug("Failed to write used len");
+		return NULL;
 	}
 	/* Make sure buffer is written before we update index. */
 	smp_wmb();
-	if (__put_user(vq->hst.last_used_idx + 1, &vq->hst.vr.used->idx)) {
-		vq_err(vq, "Failed to increment used idx");
-		return -EFAULT;
+	if (__put_user(vh->last_used_idx + 1, &vh->vr.used->idx)) {
+		pr_debug("Failed to increment used idx");
+		return NULL;
 	}
+	vh->last_used_idx++;
+	return used;
+}
+
+/* After we've used one of their buffers, we tell them about it.  We'll then
+ * want to notify the guest, using eventfd. */
+int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len)
+{
+	struct vring_used_elem  *used;
+	used = vring_add_used_user(&vq->hst, head, len);
+	if (!used)
+		vq_err(vq, "Failed to write to vring");
+
 	if (unlikely(vq->log_used)) {
 		/* Make sure data is seen before log. */
 		smp_wmb();
-- 
1.7.5.4

_______________________________________________
Virtualization mailing list
Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linuxfoundation.org/mailman/listinfo/virtualization



[Index of Archives]     [KVM Development]     [Libvirt Development]     [Libvirt Users]     [CentOS Virtualization]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux