From ace27acf63eb8012900cb8c29ffb595ec4e2c8eb Mon Sep 17 00:00:00 2001
From: Ladi Prosek <lprosek@redhat.com>
Date: Thu, 3 Mar 2016 09:37:17 +0100
Subject: [PATCH] rng: move request queue cleanup from RngEgd to RngBackend

RngBackend is now in charge of cleaning up the linked list on
instance finalization. It also exposes a function to finalize
individual RngRequest instances, called by its child classes.

Signed-off-by: Ladi Prosek <lprosek@redhat.com>
Reviewed-by: Amit Shah <amit.shah@redhat.com>
Message-Id: <1456994238-9585-4-git-send-email-lprosek@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
(cherry picked from commit 9f14b0add1dcdbfa2ee61051d068211fb0a1fcc9)
[BR: support patch for BSC#970036 (source path modified)]
Signed-off-by: Bruce Rogers <brogers@suse.com>

Conflicts:
	backends/rng.c
---
 backends/rng-egd.c | 25 +------------------------
 backends/rng.c     | 32 ++++++++++++++++++++++++++++++++
 include/qemu/rng.h | 11 +++++++++++
 3 files changed, 44 insertions(+), 24 deletions(-)

diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index 64b17c84b9..752924efaa 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -57,12 +57,6 @@ static void rng_egd_request_entropy(RngBackend *b, size_t size,
     s->parent.requests = g_slist_append(s->parent.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)
 {
     RngEgd *s = RNG_EGD(opaque);
@@ -90,28 +84,13 @@ static void rng_egd_chr_read(void *opaque, const uint8_t *buf, int size)
         size -= len;
 
         if (req->offset == req->size) {
-            s->parent.requests = g_slist_remove_link(s->parent.requests,
-                                                     s->parent.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->parent.requests; i; i = i->next) {
-        rng_egd_free_request(i->data);
-    }
-
-    g_slist_free(s->parent.requests);
-    s->parent.requests = NULL;
-}
-
 static void rng_egd_opened(RngBackend *b, Error **errp)
 {
     RngEgd *s = RNG_EGD(b);
@@ -173,8 +152,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)
diff --git a/backends/rng.c b/backends/rng.c
index 36af554da7..b62e9ca41f 100644
--- a/backends/rng.c
+++ b/backends/rng.c
@@ -59,6 +59,30 @@ static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
     }
 }
 
+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",
@@ -67,11 +91,19 @@ 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 const TypeInfo rng_backend_info = {
     .name = TYPE_RNG_BACKEND,
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(RngBackend),
     .instance_init = rng_backend_init,
+    .instance_finalize = rng_backend_finalize,
     .class_size = sizeof(RngBackendClass),
     .abstract = true,
 };
diff --git a/include/qemu/rng.h b/include/qemu/rng.h
index cc92f46f4b..d8121039c9 100644
--- a/include/qemu/rng.h
+++ b/include/qemu/rng.h
@@ -81,6 +81,17 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
                                  void *opaque);
 
 /**
+ * rng_backend_free_request:
+ * @s: the backend that created the request
+ * @req: the request to finalize
+ *
+ * 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_finalize_request(RngBackend *s, RngRequest *req);
+
+/**
  * rng_backend_open:
  * @s: the backend to open
  * @errp: a pointer to return the #Error object if an error occurs.
