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