Commit 2d3b7c01 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/amit-virtio-rng/tags/rng-for-2.6-1' into staging



rng:
- implement a request queue for rng-random so multiple guest requests
  don't result in vq buffers getting forgotten
- remove unused request cancellation code
- a VM with multiple vq buffers, when migrated, could get in a situation
  where not all buffers are handed back to the guest.  This is now
  fixed.

# gpg: Signature made Thu 03 Mar 2016 12:18:54 GMT using RSA key ID 854083B6
# gpg: Good signature from "Amit Shah <amit@amitshah.net>"
# gpg:                 aka "Amit Shah <amit@kernel.org>"
# gpg:                 aka "Amit Shah <amitshah@gmx.net>"

* remotes/amit-virtio-rng/tags/rng-for-2.6-1:
  virtio-rng: ask for more data if queue is not fully drained
  rng: add request queue support to rng-random
  rng: move request queue cleanup from RngEgd to RngBackend
  rng: move request queue from RngEgd to RngBackend
  rng: remove the unused request cancellation code
  MAINTAINERS: Add an entry for the include/sysemu/rng*.h files

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents ed6128eb f8693c2c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -921,6 +921,7 @@ M: Amit Shah <amit.shah@redhat.com>
S: Supported
F: hw/virtio/virtio-rng.c
F: include/hw/virtio/virtio-rng.h
F: include/sysemu/rng*.h
F: backends/rng*.c

nvme
+6 −63
Original line number Diff line number Diff line
@@ -25,33 +25,12 @@ typedef struct RngEgd

    CharDriverState *chr;
    char *chr_name;

    GSList *requests;
} RngEgd;

typedef struct RngRequest
{
    EntropyReceiveFunc *receive_entropy;
    uint8_t *data;
    void *opaque;
    size_t offset;
    size_t size;
} RngRequest;

static void rng_egd_request_entropy(RngBackend *b, size_t size,
                                    EntropyReceiveFunc *receive_entropy,
                                    void *opaque)
static void rng_egd_request_entropy(RngBackend *b, RngRequest *req)
{
    RngEgd *s = RNG_EGD(b);
    RngRequest *req;

    req = g_malloc(sizeof(*req));

    req->offset = 0;
    req->size = size;
    req->receive_entropy = receive_entropy;
    req->opaque = opaque;
    req->data = g_malloc(req->size);
    size_t size = req->size;

    while (size > 0) {
        uint8_t header[2];
@@ -65,14 +44,6 @@ static void rng_egd_request_entropy(RngBackend *b, size_t size,

        size -= len;
    }

    s->requests = g_slist_append(s->requests, req);
}

static void rng_egd_free_request(RngRequest *req)
{
    g_free(req->data);
    g_free(req);
}

static int rng_egd_chr_can_read(void *opaque)
@@ -81,7 +52,7 @@ static int rng_egd_chr_can_read(void *opaque)
    GSList *i;
    int size = 0;

    for (i = s->requests; i; i = i->next) {
    for (i = s->parent.requests; i; i = i->next) {
        RngRequest *req = i->data;
        size += req->size - req->offset;
    }
@@ -94,8 +65,8 @@ static void rng_egd_chr_read(void *opaque, const uint8_t *buf, int size)
    RngEgd *s = RNG_EGD(opaque);
    size_t buf_offset = 0;

    while (size > 0 && s->requests) {
        RngRequest *req = s->requests->data;
    while (size > 0 && s->parent.requests) {
        RngRequest *req = s->parent.requests->data;
        int len = MIN(size, req->size - req->offset);

        memcpy(req->data + req->offset, buf + buf_offset, len);
@@ -104,38 +75,13 @@ static void rng_egd_chr_read(void *opaque, const uint8_t *buf, int size)
        size -= len;

        if (req->offset == req->size) {
            s->requests = g_slist_remove_link(s->requests, s->requests);

            req->receive_entropy(req->opaque, req->data, req->size);

            rng_egd_free_request(req);
            rng_backend_finalize_request(&s->parent, req);
        }
    }
}

static void rng_egd_free_requests(RngEgd *s)
{
    GSList *i;

    for (i = s->requests; i; i = i->next) {
        rng_egd_free_request(i->data);
    }

    g_slist_free(s->requests);
    s->requests = NULL;
}

static void rng_egd_cancel_requests(RngBackend *b)
{
    RngEgd *s = RNG_EGD(b);

    /* We simply delete the list of pending requests.  If there is data in the 
     * queue waiting to be read, this is okay, because there will always be
     * more data than we requested originally
     */
    rng_egd_free_requests(s);
}

static void rng_egd_opened(RngBackend *b, Error **errp)
{
    RngEgd *s = RNG_EGD(b);
@@ -204,8 +150,6 @@ static void rng_egd_finalize(Object *obj)
    }

    g_free(s->chr_name);

    rng_egd_free_requests(s);
}

static void rng_egd_class_init(ObjectClass *klass, void *data)
@@ -213,7 +157,6 @@ static void rng_egd_class_init(ObjectClass *klass, void *data)
    RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);

    rbc->request_entropy = rng_egd_request_entropy;
    rbc->cancel_requests = rng_egd_cancel_requests;
    rbc->opened = rng_egd_opened;
}

+19 −24
Original line number Diff line number Diff line
@@ -22,10 +22,6 @@ struct RndRandom

    int fd;
    char *filename;

    EntropyReceiveFunc *receive_func;
    void *opaque;
    size_t size;
};

/**
@@ -38,37 +34,36 @@ struct RndRandom
static void entropy_available(void *opaque)
{
    RndRandom *s = RNG_RANDOM(opaque);
    uint8_t buffer[s->size];

    while (s->parent.requests != NULL) {
        RngRequest *req = s->parent.requests->data;
        ssize_t len;

    len = read(s->fd, buffer, s->size);
        len = read(s->fd, req->data, req->size);
        if (len < 0 && errno == EAGAIN) {
            return;
        }
        g_assert(len != -1);

    s->receive_func(s->opaque, buffer, len);
    s->receive_func = NULL;
        req->receive_entropy(req->opaque, req->data, len);

        rng_backend_finalize_request(&s->parent, req);
    }

    /* We've drained all requests, the fd handler can be reset. */
    qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
}

static void rng_random_request_entropy(RngBackend *b, size_t size,
                                        EntropyReceiveFunc *receive_entropy,
                                        void *opaque)
static void rng_random_request_entropy(RngBackend *b, RngRequest *req)
{
    RndRandom *s = RNG_RANDOM(b);

    if (s->receive_func) {
        s->receive_func(s->opaque, NULL, 0);
    }

    s->receive_func = receive_entropy;
    s->opaque = opaque;
    s->size = size;

    if (s->parent.requests == NULL) {
        /* If there are no pending requests yet, we need to
         * install our fd handler. */
        qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
    }
}

static void rng_random_opened(RngBackend *b, Error **errp)
{
+42 −8
Original line number Diff line number Diff line
@@ -20,18 +20,20 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
                                 void *opaque)
{
    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
    RngRequest *req;

    if (k->request_entropy) {
        k->request_entropy(s, size, receive_entropy, opaque);
    }
}
        req = g_malloc(sizeof(*req));

void rng_backend_cancel_requests(RngBackend *s)
{
    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
        req->offset = 0;
        req->size = size;
        req->receive_entropy = receive_entropy;
        req->opaque = opaque;
        req->data = g_malloc(req->size);

        k->request_entropy(s, req);

    if (k->cancel_requests) {
        k->cancel_requests(s);
        s->requests = g_slist_append(s->requests, req);
    }
}

@@ -73,6 +75,30 @@ static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
    s->opened = true;
}

static void rng_backend_free_request(RngRequest *req)
{
    g_free(req->data);
    g_free(req);
}

static void rng_backend_free_requests(RngBackend *s)
{
    GSList *i;

    for (i = s->requests; i; i = i->next) {
        rng_backend_free_request(i->data);
    }

    g_slist_free(s->requests);
    s->requests = NULL;
}

void rng_backend_finalize_request(RngBackend *s, RngRequest *req)
{
    s->requests = g_slist_remove(s->requests, req);
    rng_backend_free_request(req);
}

static void rng_backend_init(Object *obj)
{
    object_property_add_bool(obj, "opened",
@@ -81,6 +107,13 @@ static void rng_backend_init(Object *obj)
                             NULL);
}

static void rng_backend_finalize(Object *obj)
{
    RngBackend *s = RNG_BACKEND(obj);

    rng_backend_free_requests(s);
}

static void rng_backend_class_init(ObjectClass *oc, void *data)
{
    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
@@ -93,6 +126,7 @@ static const TypeInfo rng_backend_info = {
    .parent = TYPE_OBJECT,
    .instance_size = sizeof(RngBackend),
    .instance_init = rng_backend_init,
    .instance_finalize = rng_backend_finalize,
    .class_size = sizeof(RngBackendClass),
    .class_init = rng_backend_class_init,
    .abstract = true,
+7 −0
Original line number Diff line number Diff line
@@ -69,6 +69,13 @@ static void chr_read(void *opaque, const void *buf, size_t size)
        g_free(elem);
    }
    virtio_notify(vdev, vrng->vq);

    if (!virtio_queue_empty(vrng->vq)) {
        /* If we didn't drain the queue, call virtio_rng_process
         * to take care of asking for more data as appropriate.
         */
        virtio_rng_process(vrng);
    }
}

static void virtio_rng_process(VirtIORNG *vrng)
Loading