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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJW2CuuAAoJEB6aO1+FQIO2RM0QAIRywJ572soT0NoA39XLNo8t avixoEsOCYy1iP8dvzw4Rh/5wdzrXUWsL3oMe99LOTSaupgYDZgA7RAUBrDNTKBV jpE6injeCdhujMAS3vQw0+vCx6nV8XQWGu/jBePxIKa+Rw17Z2QaNnTuiLu84zGo Kwlv17rqQTjI0ynNirLwWCrpCH9wGGqEZS6FIHCDOm2HamF6YqQw4ew3UBf0c2Pw tTuMtxaDh7qn6Np6OlVoD4WkaYyJQO5rg/nxyGKqp6PhpLDeAifKat9gS9jWhmAo nIj7R+qc/CHr7TJNM3BuKJCR/HvdJO4T2foThmOuHhpEI6oOJNqARfwKJgLPrNRg b+DRShhHlBtujpJ/+B9H4PEeZa8GX/9EexC6AFm7Nk8jlKqSvHFC/XnR5GuQlOq6 s6ARZrMR+mNZVrgYp5BE3az8zYcrUnqwAZFhrY2epZ6c3lPSVHK+JvMGj3t3qomX NT6s9A979wp68L1j34KnvqyeZAksV6KY6uEyjC1S05ip+BdOqEoeqUs6fCiCyqnB EBx0V1ZthD5BuQk4Rwnxic2hbOQKGe13nrqbPWL+SyQt317b0uliA3XNibMmTuai R48YIlaT9niaJB1vkXhasfQhTNjn7BCPZDrozd7sOBaZfXPNfRhqZnxi0SZvQs9k 747xXMsv4Zz0XzKYNSOY =vi66 -----END PGP SIGNATURE----- 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: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
2d3b7c0164
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,6 @@ struct RndRandom
|
||||
|
||||
int fd;
|
||||
char *filename;
|
||||
|
||||
EntropyReceiveFunc *receive_func;
|
||||
void *opaque;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -38,36 +34,35 @@ struct RndRandom
|
||||
static void entropy_available(void *opaque)
|
||||
{
|
||||
RndRandom *s = RNG_RANDOM(opaque);
|
||||
uint8_t buffer[s->size];
|
||||
ssize_t len;
|
||||
|
||||
len = read(s->fd, buffer, s->size);
|
||||
if (len < 0 && errno == EAGAIN) {
|
||||
return;
|
||||
while (s->parent.requests != NULL) {
|
||||
RngRequest *req = s->parent.requests->data;
|
||||
ssize_t len;
|
||||
|
||||
len = read(s->fd, req->data, req->size);
|
||||
if (len < 0 && errno == EAGAIN) {
|
||||
return;
|
||||
}
|
||||
g_assert(len != -1);
|
||||
|
||||
req->receive_entropy(req->opaque, req->data, len);
|
||||
|
||||
rng_backend_finalize_request(&s->parent, req);
|
||||
}
|
||||
g_assert(len != -1);
|
||||
|
||||
s->receive_func(s->opaque, buffer, len);
|
||||
s->receive_func = NULL;
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
}
|
||||
|
||||
s->receive_func = receive_entropy;
|
||||
s->opaque = opaque;
|
||||
s->size = size;
|
||||
|
||||
qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
|
||||
}
|
||||
|
||||
static void rng_random_opened(RngBackend *b, Error **errp)
|
||||
|
@ -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);
|
||||
|
||||
if (k->cancel_requests) {
|
||||
k->cancel_requests(s);
|
||||
k->request_entropy(s, req);
|
||||
|
||||
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,
|
||||
|
@ -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)
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define RNG_BACKEND_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(RngBackendClass, (klass), TYPE_RNG_BACKEND)
|
||||
|
||||
typedef struct RngRequest RngRequest;
|
||||
typedef struct RngBackendClass RngBackendClass;
|
||||
typedef struct RngBackend RngBackend;
|
||||
|
||||
@ -31,13 +32,20 @@ typedef void (EntropyReceiveFunc)(void *opaque,
|
||||
const void *data,
|
||||
size_t size);
|
||||
|
||||
struct RngRequest
|
||||
{
|
||||
EntropyReceiveFunc *receive_entropy;
|
||||
uint8_t *data;
|
||||
void *opaque;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct RngBackendClass
|
||||
{
|
||||
ObjectClass parent_class;
|
||||
|
||||
void (*request_entropy)(RngBackend *s, size_t size,
|
||||
EntropyReceiveFunc *receive_entropy, void *opaque);
|
||||
void (*cancel_requests)(RngBackend *s);
|
||||
void (*request_entropy)(RngBackend *s, RngRequest *req);
|
||||
|
||||
void (*opened)(RngBackend *s, Error **errp);
|
||||
};
|
||||
@ -48,8 +56,10 @@ struct RngBackend
|
||||
|
||||
/*< protected >*/
|
||||
bool opened;
|
||||
GSList *requests;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* rng_backend_request_entropy:
|
||||
* @s: the backend to request entropy from
|
||||
@ -70,12 +80,13 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* rng_backend_cancel_requests:
|
||||
* @s: the backend to cancel all pending requests in
|
||||
* rng_backend_free_request:
|
||||
* @s: the backend that created the request
|
||||
* @req: the request to finalize
|
||||
*
|
||||
* Cancels all pending requests submitted by @rng_backend_request_entropy. This
|
||||
* should be used by a device during reset or in preparation for live migration
|
||||
* to stop tracking any request.
|
||||
* Used by child rng backend classes to finalize requests once they've been
|
||||
* processed. The request is removed from the list of active requests and
|
||||
* deleted.
|
||||
*/
|
||||
void rng_backend_cancel_requests(RngBackend *s);
|
||||
void rng_backend_finalize_request(RngBackend *s, RngRequest *req);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user