[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL v2 for-2.7 02/15] qapi: change QmpInputVisitor to QSL
From: |
Markus Armbruster |
Subject: |
[Qemu-devel] [PULL v2 for-2.7 02/15] qapi: change QmpInputVisitor to QSLIST |
Date: |
Tue, 19 Jul 2016 20:41:45 +0200 |
From: Paolo Bonzini <address@hidden>
This saves a lot of memory compared to a statically-sized array,
or at least 24kb could be considered a lot on an Atari ST.
It also makes the code more similar to QmpOutputVisitor.
This removes the limit on the depth of a QObject that can be processed
into a QAPI tree. This is not a problem because QObjects can be
considered trusted; the text received on the QMP wire is untrusted
input, but the JSON parser already takes pains to limit the QObject tree
it creates. We don't need the QMP input visitor to limit it again.
Signed-off-by: Paolo Bonzini <address@hidden>
Message-Id: <address@hidden>
Reviewed-by: Markus Armbruster <address@hidden>
Reviewed-by: Eric Blake <address@hidden>
[Commit message typo fixed]
Signed-off-by: Markus Armbruster <address@hidden>
---
qapi/qmp-input-visitor.c | 59 ++++++++++++++++++++++++------------------------
1 file changed, 29 insertions(+), 30 deletions(-)
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 21edb39..64dd392 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -30,6 +30,8 @@ typedef struct StackObject
GHashTable *h; /* If obj is dict: unvisited keys */
const QListEntry *entry; /* If obj is list: unvisited tail */
+
+ QSLIST_ENTRY(StackObject) node;
} StackObject;
struct QmpInputVisitor
@@ -41,8 +43,7 @@ struct QmpInputVisitor
/* Stack of objects being visited (all entries will be either
* QDict or QList). */
- StackObject stack[QIV_STACK_SIZE];
- int nb_stack;
+ QSLIST_HEAD(, StackObject) stack;
/* True to reject parse in visit_end_struct() if unvisited keys remain. */
bool strict;
@@ -61,13 +62,13 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
QObject *qobj;
QObject *ret;
- if (!qiv->nb_stack) {
+ if (QSLIST_EMPTY(&qiv->stack)) {
/* Starting at root, name is ignored. */
return qiv->root;
}
/* We are in a container; find the next element. */
- tos = &qiv->stack[qiv->nb_stack - 1];
+ tos = QSLIST_FIRST(&qiv->stack);
qobj = tos->obj;
assert(qobj);
@@ -100,18 +101,11 @@ static const QListEntry *qmp_input_push(QmpInputVisitor
*qiv, QObject *obj,
void *qapi, Error **errp)
{
GHashTable *h;
- StackObject *tos = &qiv->stack[qiv->nb_stack];
+ StackObject *tos = g_new0(StackObject, 1);
assert(obj);
- if (qiv->nb_stack >= QIV_STACK_SIZE) {
- error_setg(errp, "An internal buffer overran");
- return NULL;
- }
-
tos->obj = obj;
tos->qapi = qapi;
- assert(!tos->h);
- assert(!tos->entry);
if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
h = g_hash_table_new(g_str_hash, g_str_equal);
@@ -121,7 +115,7 @@ static const QListEntry *qmp_input_push(QmpInputVisitor
*qiv, QObject *obj,
tos->entry = qlist_first(qobject_to_qlist(obj));
}
- qiv->nb_stack++;
+ QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
return tos->entry;
}
@@ -129,10 +123,9 @@ static const QListEntry *qmp_input_push(QmpInputVisitor
*qiv, QObject *obj,
static void qmp_input_check_struct(Visitor *v, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- StackObject *tos = &qiv->stack[qiv->nb_stack - 1];
-
- assert(qiv->nb_stack > 0);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+ assert(tos && !tos->entry);
if (qiv->strict) {
GHashTable *const top_ht = tos->h;
if (top_ht) {
@@ -147,23 +140,23 @@ static void qmp_input_check_struct(Visitor *v, Error
**errp)
}
}
+static void qmp_input_stack_object_free(StackObject *tos)
+{
+ if (tos->h) {
+ g_hash_table_unref(tos->h);
+ }
+
+ g_free(tos);
+}
+
static void qmp_input_pop(Visitor *v, void **obj)
{
QmpInputVisitor *qiv = to_qiv(v);
- StackObject *tos = &qiv->stack[qiv->nb_stack - 1];
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
- assert(qiv->nb_stack > 0);
- assert(tos->qapi == obj);
-
- if (qiv->strict) {
- GHashTable * const top_ht = qiv->stack[qiv->nb_stack - 1].h;
- if (top_ht) {
- g_hash_table_unref(top_ht);
- }
- tos->h = NULL;
- }
-
- qiv->nb_stack--;
+ assert(tos && tos->qapi == obj);
+ QSLIST_REMOVE_HEAD(&qiv->stack, node);
+ qmp_input_stack_object_free(tos);
}
static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
@@ -224,7 +217,7 @@ static GenericList *qmp_input_next_list(Visitor *v,
GenericList *tail,
size_t size)
{
QmpInputVisitor *qiv = to_qiv(v);
- StackObject *so = &qiv->stack[qiv->nb_stack - 1];
+ StackObject *so = QSLIST_FIRST(&qiv->stack);
if (!so->entry) {
return NULL;
@@ -376,6 +369,12 @@ static void qmp_input_optional(Visitor *v, const char
*name, bool *present)
static void qmp_input_free(Visitor *v)
{
QmpInputVisitor *qiv = to_qiv(v);
+ while (!QSLIST_EMPTY(&qiv->stack)) {
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ QSLIST_REMOVE_HEAD(&qiv->stack, node);
+ qmp_input_stack_object_free(tos);
+ }
qobject_decref(qiv->root);
g_free(qiv);
--
2.5.5
- [Qemu-devel] [PULL v2 for-2.7 00/15] QAPI patches for 2016-07-19, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 05/15] qapi: Special case c_name() for empty type, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 08/15] qapi: Drop useless gen_err_check(), Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 02/15] qapi: change QmpInputVisitor to QSLIST,
Markus Armbruster <=
- [Qemu-devel] [PULL v2 for-2.7 01/15] qapi: change QmpOutputVisitor to QSLIST, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 06/15] qapi: Hide tag_name data member of variants, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 07/15] qapi: Add type.is_empty() helper, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 03/15] net: use Netdev instead of NetClientOptions in client init, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 13/15] block: Simplify drive-mirror, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 04/15] qapi: Require all branches of flat union enum to be covered, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 09/15] qapi-event: Simplify visit of non-implicit data, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 12/15] block: Simplify block_set_io_throttle, Markus Armbruster, 2016/07/19
- [Qemu-devel] [PULL v2 for-2.7 10/15] qapi: Plumb in 'boxed' to qapi generator lower levels, Markus Armbruster, 2016/07/19