1 From c33f9c1b4eb6142f6d49a72465395f111b6c968b Mon Sep 17 00:00:00 2001
2 From: Ladi Prosek <lprosek@redhat.com>
3 Date: Thu, 3 Mar 2016 09:37:18 +0100
4 Subject: [PATCH 4/5] rng: add request queue support to rng-random
6 Requests are now created in the RngBackend parent class and the
7 code path is shared by both rng-egd and rng-random.
9 This commit fixes the rng-random implementation which processed
10 only one request at a time and simply discarded all but the most
11 recent one. In the guest this manifested as delayed completion
12 of reads from virtio-rng, i.e. a read was completed only after
13 another read was issued.
15 By switching rng-random to use the same request queue as rng-egd,
16 the unsafe stack-based allocation of the entropy buffer is
17 eliminated and replaced with g_malloc.
19 Signed-off-by: Ladi Prosek <lprosek@redhat.com>
20 Reviewed-by: Amit Shah <amit.shah@redhat.com>
21 Message-Id: <1456994238-9585-5-git-send-email-lprosek@redhat.com>
22 Signed-off-by: Amit Shah <amit.shah@redhat.com>
24 backends/rng-egd.c | 16 ++--------------
25 backends/rng-random.c | 43 +++++++++++++++++++------------------------
26 backends/rng.c | 13 ++++++++++++-
27 include/sysemu/rng.h | 3 +--
28 4 files changed, 34 insertions(+), 41 deletions(-)
30 diff --git a/backends/rng-egd.c b/backends/rng-egd.c
31 index 08301a7..de6c8d4 100644
32 --- a/backends/rng-egd.c
33 +++ b/backends/rng-egd.c
34 @@ -26,20 +26,10 @@ typedef struct RngEgd
38 -static void rng_egd_request_entropy(RngBackend *b, size_t size,
39 - EntropyReceiveFunc *receive_entropy,
41 +static void rng_egd_request_entropy(RngBackend *b, RngRequest *req)
43 RngEgd *s = RNG_EGD(b);
46 - req = g_malloc(sizeof(*req));
50 - req->receive_entropy = receive_entropy;
51 - req->opaque = opaque;
52 - req->data = g_malloc(req->size);
53 + size_t size = req->size;
57 @@ -53,8 +43,6 @@ static void rng_egd_request_entropy(RngBackend *b, size_t size,
62 - s->parent.requests = g_slist_append(s->parent.requests, req);
65 static int rng_egd_chr_can_read(void *opaque)
66 diff --git a/backends/rng-random.c b/backends/rng-random.c
67 index 4e51f46..c2d8c03 100644
68 --- a/backends/rng-random.c
69 +++ b/backends/rng-random.c
70 @@ -21,10 +21,6 @@ struct RndRandom
75 - EntropyReceiveFunc *receive_func;
81 @@ -37,36 +33,35 @@ struct RndRandom
82 static void entropy_available(void *opaque)
84 RndRandom *s = RNG_RANDOM(opaque);
85 - uint8_t buffer[s->size];
88 - len = read(s->fd, buffer, s->size);
89 - if (len < 0 && errno == EAGAIN) {
92 - g_assert(len != -1);
93 + while (s->parent.requests != NULL) {
94 + RngRequest *req = s->parent.requests->data;
97 + len = read(s->fd, req->data, req->size);
98 + if (len < 0 && errno == EAGAIN) {
101 + g_assert(len != -1);
103 - s->receive_func(s->opaque, buffer, len);
104 - s->receive_func = NULL;
105 + req->receive_entropy(req->opaque, req->data, len);
107 + rng_backend_finalize_request(&s->parent, req);
110 + /* We've drained all requests, the fd handler can be reset. */
111 qemu_set_fd_handler(s->fd, NULL, NULL, NULL);
114 -static void rng_random_request_entropy(RngBackend *b, size_t size,
115 - EntropyReceiveFunc *receive_entropy,
117 +static void rng_random_request_entropy(RngBackend *b, RngRequest *req)
119 RndRandom *s = RNG_RANDOM(b);
121 - if (s->receive_func) {
122 - s->receive_func(s->opaque, NULL, 0);
123 + if (s->parent.requests == NULL) {
124 + /* If there are no pending requests yet, we need to
125 + * install our fd handler. */
126 + qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
129 - s->receive_func = receive_entropy;
130 - s->opaque = opaque;
133 - qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
136 static void rng_random_opened(RngBackend *b, Error **errp)
137 diff --git a/backends/rng.c b/backends/rng.c
138 index 0d9978b..4066268 100644
141 @@ -19,9 +19,20 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
144 RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
147 if (k->request_entropy) {
148 - k->request_entropy(s, size, receive_entropy, opaque);
149 + req = g_malloc(sizeof(*req));
153 + req->receive_entropy = receive_entropy;
154 + req->opaque = opaque;
155 + req->data = g_malloc(req->size);
157 + k->request_entropy(s, req);
159 + s->requests = g_slist_append(s->requests, req);
163 diff --git a/include/sysemu/rng.h b/include/sysemu/rng.h
164 index c2c9035..a7ed580 100644
165 --- a/include/sysemu/rng.h
166 +++ b/include/sysemu/rng.h
167 @@ -46,8 +46,7 @@ struct RngBackendClass
169 ObjectClass parent_class;
171 - void (*request_entropy)(RngBackend *s, size_t size,
172 - EntropyReceiveFunc *receive_entropy, void *opaque);
173 + void (*request_entropy)(RngBackend *s, RngRequest *req);
175 void (*opened)(RngBackend *s, Error **errp);