Commit f7671f3d authored by Xie Yongji's avatar Xie Yongji Committed by Michael S. Tsirkin
Browse files

libvhost-user: Introduce vu_queue_map_desc()



Introduce vu_queue_map_desc() which should be
independent with vu_queue_pop();

Signed-off-by: default avatarXie Yongji <xieyongji@baidu.com>
Signed-off-by: default avatarZhang Yu <zhangyu31@baidu.com>
Reviewed-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20190228085355.9614-4-xieyongji@baidu.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 792468cc
Loading
Loading
Loading
Loading
+51 −37
Original line number Diff line number Diff line
@@ -1848,49 +1848,20 @@ virtqueue_alloc_element(size_t sz,
    return elem;
}

void *
vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz)
static void *
vu_queue_map_desc(VuDev *dev, VuVirtq *vq, unsigned int idx, size_t sz)
{
    unsigned int i, head, max, desc_len;
    struct vring_desc *desc = vq->vring.desc;
    uint64_t desc_addr, read_len;
    unsigned int desc_len;
    unsigned int max = vq->vring.num;
    unsigned int i = idx;
    VuVirtqElement *elem;
    unsigned out_num, in_num;
    unsigned int out_num = 0, in_num = 0;
    struct iovec iov[VIRTQUEUE_MAX_SIZE];
    struct vring_desc desc_buf[VIRTQUEUE_MAX_SIZE];
    struct vring_desc *desc;
    int rc;

    if (unlikely(dev->broken) ||
        unlikely(!vq->vring.avail)) {
        return NULL;
    }

    if (vu_queue_empty(dev, vq)) {
        return NULL;
    }
    /* Needed after virtio_queue_empty(), see comment in
     * virtqueue_num_heads(). */
    smp_rmb();

    /* When we start there are none of either input nor output. */
    out_num = in_num = 0;

    max = vq->vring.num;
    if (vq->inuse >= vq->vring.num) {
        vu_panic(dev, "Virtqueue size exceeded");
        return NULL;
    }

    if (!virtqueue_get_head(dev, vq, vq->last_avail_idx++, &head)) {
        return NULL;
    }

    if (vu_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) {
        vring_set_avail_event(vq, vq->last_avail_idx);
    }

    i = head;
    desc = vq->vring.desc;
    if (desc[i].flags & VRING_DESC_F_INDIRECT) {
        if (desc[i].len % sizeof(struct vring_desc)) {
            vu_panic(dev, "Invalid size for indirect buffer table");
@@ -1942,12 +1913,13 @@ vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz)
    } while (rc == VIRTQUEUE_READ_DESC_MORE);

    if (rc == VIRTQUEUE_READ_DESC_ERROR) {
        vu_panic(dev, "read descriptor error");
        return NULL;
    }

    /* Now copy what we have collected and mapped */
    elem = virtqueue_alloc_element(sz, out_num, in_num);
    elem->index = head;
    elem->index = idx;
    for (i = 0; i < out_num; i++) {
        elem->out_sg[i] = iov[i];
    }
@@ -1955,6 +1927,48 @@ vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz)
        elem->in_sg[i] = iov[out_num + i];
    }

    return elem;
}

void *
vu_queue_pop(VuDev *dev, VuVirtq *vq, size_t sz)
{
    unsigned int head;
    VuVirtqElement *elem;

    if (unlikely(dev->broken) ||
        unlikely(!vq->vring.avail)) {
        return NULL;
    }

    if (vu_queue_empty(dev, vq)) {
        return NULL;
    }
    /*
     * Needed after virtio_queue_empty(), see comment in
     * virtqueue_num_heads().
     */
    smp_rmb();

    if (vq->inuse >= vq->vring.num) {
        vu_panic(dev, "Virtqueue size exceeded");
        return NULL;
    }

    if (!virtqueue_get_head(dev, vq, vq->last_avail_idx++, &head)) {
        return NULL;
    }

    if (vu_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) {
        vring_set_avail_event(vq, vq->last_avail_idx);
    }

    elem = vu_queue_map_desc(dev, vq, head, sz);

    if (!elem) {
        return NULL;
    }

    vq->inuse++;

    return elem;