All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: qemu-devel@nongnu.org
Cc: armbru@redhat.com, Michael Roth <mdroth@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH v7 17/31] qapi: Document visitor interfaces, add assertions
Date: Mon,  7 Dec 2015 20:55:07 -0700	[thread overview]
Message-ID: <1449546921-6378-18-git-send-email-eblake@redhat.com> (raw)
In-Reply-To: <1449546921-6378-1-git-send-email-eblake@redhat.com>

The visitor interface for mapping between QObject/QemuOpts/string
and qapi has formerly been documented only by reading source code,
making it difficult to propose changes to either scripts/qapi*.py
or to clients without knowing whether those changes would be safe.
This adds documentation, including mentioning when parameters can
be NULL, and where there are still some interface warts that would
be nice to remove.  In particular, I have plans to remove
visit_start_union() in a future patch.

Add some asserts to strengthen the claims of the assertions; some
of these were only made possible by recent cleanup commits.  These
were made easier with the addition of a new visit_is_output()
helper (since all 2 output visitors of our 6 overall visitors use
the same .type_enum() callback).

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v7: retitle; more wording changes, add asserts to enforce the
wording, place later in series to rebase on fixes that would
otherwise trip the new assertions
v6: mention that input visitors blindly assign over *obj; wording
improvements
---
 include/qapi/visitor-impl.h |  31 +++++-
 include/qapi/visitor.h      | 223 ++++++++++++++++++++++++++++++++++++++++++--
 qapi/qapi-visit-core.c      |  39 +++++++-
 3 files changed, 280 insertions(+), 13 deletions(-)

diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index c3c6323..27f776f 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -15,23 +15,37 @@
 #include "qapi/error.h"
 #include "qapi/visitor.h"

+/* This file describes the callback interface for implementing a
+ * QObject visitor.  For the client interface, see visitor.h.  When
+ * implementing the callbacks, it is easiest to declare a struct with
+ * 'Visitor visitor;' as the first member.  Semantics for the
+ * callbacks are generally similar to the counterpart public
+ * interface.  */
+
 struct Visitor
 {
-    /* Must be set */
+    /* Must be provided to visit structs (the string visitors do not
+     * currently visit structs). */
     void (*start_struct)(Visitor *v, void **obj, size_t size,
                          const char *name, Error **errp);
+    /* Must be provided if start_struct is present. */
     void (*end_struct)(Visitor *v, Error **errp);

+    /* May be NULL; most useful for input visitors. */
     void (*start_implicit_struct)(Visitor *v, void **obj, size_t size,
                                   Error **errp);
     /* May be NULL */
     void (*end_implicit_struct)(Visitor *v);

+    /* Must be set */
     void (*start_list)(Visitor *v, const char *name, Error **errp);
+    /* Must be set */
     GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp);
     /* Must be set */
     void (*end_list)(Visitor *v);

+    /* Must be set, although the helpers input_type_enum() and
+     * output_type_enum() should be used if appropriate.  */
     void (*type_enum)(Visitor *v, int *obj, const char *const strings[],
                       const char *name, Error **errp);
     /* May be NULL; only needed for input visitors. */
@@ -47,23 +61,38 @@ struct Visitor
     /* Optional; fallback is type_uint64().  */
     void (*type_size)(Visitor *v, uint64_t *obj, const char *name,
                       Error **errp);
+
     /* Must be set. */
     void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp);
+    /* Must be set */
     void (*type_str)(Visitor *v, char **obj, const char *name, Error **errp);
+
+    /* Must be provided to visit numbers (the opts visitor does not
+     * currently visit non-integers). */
     void (*type_number)(Visitor *v, double *obj, const char *name,
                         Error **errp);
+    /* Must be provided to visit arbitrary QTypes (the opts and string
+     * visitors do not currently visit arbitrary types).  */
     void (*type_any)(Visitor *v, QObject **obj, const char *name,
                      Error **errp);

     /* May be NULL; most useful for input visitors. */
     void (*optional)(Visitor *v, bool *present, const char *name);

+    /* FIXME - needs to be removed */
     bool (*start_union)(Visitor *v, bool data_present, Error **errp);
+    /* FIXME - needs to be removed */
     void (*end_union)(Visitor *v, bool data_present, Error **errp);
 };

+/**
+ * A generic visitor.type_enum suitable for input visitors.
+ */
 void input_type_enum(Visitor *v, int *obj, const char *const strings[],
                      const char *name, Error **errp);
+/**
+ * A generic visitor.type_enum suitable for output visitors.
+ */
 void output_type_enum(Visitor *v, int *obj, const char *const strings[],
                       const char *name, Error **errp);

diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 21c09b4..96a9535 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -18,6 +18,20 @@
 #include "qapi/error.h"
 #include <stdlib.h>

+/* This file describes the client view for visiting a map between
+ * generated QAPI C structs and another representation (command line
+ * options, strings, or QObjects).  An input visitor converts from
+ * some other form into QAPI representation; an output visitor
+ * converts from QAPI back into another form.  In the descriptions
+ * below, an object or dictionary refers to a JSON '{}', and a list
+ * refers to a JSON '[]'.  These functions seldom need to be called
+ * directly, but are instead used by code generated by
+ * scripts/qapi-visit.py.  For the visitor callback contracts, see
+ * visitor-impl.h.
+ */
+
+/* This struct is layout-compatible with all other *List structs
+ * created by the qapi generator. */
 typedef struct GenericList
 {
     union {
@@ -27,15 +41,101 @@ typedef struct GenericList
     struct GenericList *next;
 } GenericList;

+/**
+ * Prepare to visit an object tied to key @name.
+ * @name will be NULL if this is visited as part of a list.  The
+ * caller then makes a series of visit calls for each key expected in
+ * the object, where those visits set their respective obj parameter
+ * to the address of a member of the qapi struct, and follows
+ * everything by a call to visit_end_struct() to clean up resources.
+ *
+ * @obj can be NULL (in which case @size should also be 0) to indicate
+ * that there is no qapi C struct, and that the upcoming visit calls
+ * are parsing input to or creating output from some other
+ * representation.
+ *
+ * If @obj is not NULL, then input visitors malloc a qapi struct of
+ * @size bytes into *@obj on success, and output visitors expect *@obj
+ * to be a fully-populated qapi struct.
+ *
+ * Set *@errp on failure; for example, if the input stream does not
+ * have a member @name or if the member is not an object.
+ *
+ * FIXME: For input visitors, *@obj can be assigned here even if later
+ * visits will fail; this can lead to memory leaks if clients aren't
+ * careful.
+ */
 void visit_start_struct(Visitor *v, void **obj, size_t size,
                         const char *name, Error **errp);
+/**
+ * Complete a struct visit started earlier.
+ * Must be called after any successful use of visit_start_struct(),
+ * even if intermediate processing was skipped due to errors, to allow
+ * the backend to release any resources.
+ */
 void visit_end_struct(Visitor *v, Error **errp);
+
+/**
+ * Prepare to visit an implicit struct.
+ * Similar to visit_start_struct(), except that an implicit struct
+ * represents a subset of keys that are present at the same nesting level
+ * of a common object but as a separate qapi C struct, rather than a new
+ * object at a deeper nesting level.
+ *
+ * @obj must not be NULL, since this function is only called when
+ * visiting with qapi structs.
+ *
+ * FIXME: For input visitors, *@obj can be assigned here even if later
+ * visits will fail; this can lead to memory leaks if clients aren't
+ * careful.
+ */
 void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
                                  Error **errp);
+/**
+ * Complete an implicit struct visit started earlier.
+ * Must be called after any successful use of visit_start_implicit_struct(),
+ * even if intermediate processing was skipped due to errors, to allow
+ * the backend to release any resources.  Unlike visit_end_struct(), this
+ * does not need to check for errors (detection of unused keys is only
+ * possible for the overall struct, not a subset).
+ */
 void visit_end_implicit_struct(Visitor *v);

+/**
+ * Prepare to visit a list tied to an object key @name.
+ * @name will be NULL if this is visited as part of another list.
+ * After calling this, the elements must be collected until
+ * visit_next_list() returns NULL, then visit_end_list() must be
+ * used to complete the visit.
+ */
 void visit_start_list(Visitor *v, const char *name, Error **errp);
+/**
+ * Iterate over a GenericList during a list visit.
+ * @list must not be NULL; on the first call, @list contains the
+ * address of the list head, and on subsequent calls *@list must be
+ * the previously returned value.  Must be called in a loop until a
+ * NULL return or error occurs; for each non-NULL return, the caller
+ * must then call the appropriate visit_type_*() for the element type
+ * of the list, with that function's name parameter set to NULL.
+ *
+ * Note that for some visitors (qapi-dealloc and qmp-output), when a
+ * qapi GenericList linked list is not being used (comparable to when
+ * a NULL obj is used for visit_start_struct()), it is acceptable to
+ * bypass the use of visit_next_list() and just directly call the
+ * appropriate visit_type_*() for each element in between the
+ * visit_start_list() and visit_end_list() calls.
+ *
+ * FIXME: For input visitors, *@list can be assigned here even if
+ * later visits will fail; this can lead to memory leaks if clients
+ * aren't careful.
+ */
 GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
+/**
+ * Complete the list started earlier.
+ * Must be called after any successful use of visit_start_list(),
+ * even if intermediate processing was skipped due to errors, to allow
+ * the backend to release any resources.
+ */
 void visit_end_list(Visitor *v);

 /**
@@ -54,23 +154,128 @@ bool visit_optional(Visitor *v, bool *present, const char *name);
  */
 void visit_get_next_type(Visitor *v, QType *type, bool promote_int,
                          const char *name, Error **errp);
+
+/**
+ * Visit an enum value tied to @name in the current object visit.
+ * @name will be NULL if this is visited as part of a list.
+ * For input visitors, parse a string and set *@obj to the numeric
+ * value of the enum type using @strings as the mapping, leaving @obj
+ * unchanged on error; for output visitors, reverse the mapping and
+ * visit the output string determined by *@obj.
+ */
 void visit_type_enum(Visitor *v, int *obj, const char *const strings[],
                      const char *name, Error **errp);
+
+/**
+ * Visit an integer value tied to @name in the current object visit.
+ * @name will be NULL if this is visited as part of a list.
+ * For input visitors, set *@obj to the parsed value; for other visitors,
+ * leave *@obj unchanged.
+ */
 void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
-void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp);
-void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp);
-void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp);
-void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+/**
+ * Visit a uint8_t value tied to @name in the current object visit.
+ * Like visit_type_int(), except clamps the value to uint8_t range.
+ */
+void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name,
+                      Error **errp);
+/**
+ * Visit a uint16_t value tied to @name in the current object visit.
+ * Like visit_type_int(), except clamps the value to uint16_t range.
+ */
+void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name,
+                       Error **errp);
+/**
+ * Visit a uint32_t value tied to @name in the current object visit.
+ * Like visit_type_int(), except clamps the value to uint32_t range.
+ */
+void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name,
+                       Error **errp);
+/**
+ * Visit a uint64_t value tied to @name in the current object visit.
+ * Like visit_type_int(), except clamps the value to uint64_t range
+ * (that is, ensures it is unsigned).
+ */
+void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name,
+                       Error **errp);
+/**
+ * Visit an int8_t value tied to @name in the current object visit.
+ * Like visit_type_int(), except clamps the value to int8_t range.
+ */
 void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp);
-void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp);
-void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp);
-void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp);
-void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp);
+/**
+ * Visit an int16_t value tied to @name in the current object visit.
+ * Like visit_type_int(), except clamps the value to int16_t range.
+ */
+void visit_type_int16(Visitor *v, int16_t *obj, const char *name,
+                      Error **errp);
+/**
+ * Visit an int32_t value tied to @name in the current object visit.
+ * Like visit_type_int(), except clamps the value to int32_t range.
+ */
+void visit_type_int32(Visitor *v, int32_t *obj, const char *name,
+                      Error **errp);
+/**
+ * Visit an int64_t value tied to @name in the current object visit.
+ * Identical to visit_type_int().
+ */
+void visit_type_int64(Visitor *v, int64_t *obj, const char *name,
+                      Error **errp);
+/**
+ * Visit a uint64_t value tied to @name in the current object visit.
+ * Like visit_type_uint64(), except that some visitors may choose to
+ * recognize additional suffixes for easily scaling input values.
+ */
+void visit_type_size(Visitor *v, uint64_t *obj, const char *name,
+                     Error **errp);
+
+/**
+ * Visit a boolean value tied to @name in the current object visit.
+ * @name will be NULL if this is visited as part of a list.
+ * Input visitors set *@obj to the value; other visitors will leave
+ * *@obj unchanged.
+ */
 void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
+
+/**
+ * Visit a string value tied to @name in the current object visit.
+ * @name will be NULL if this is visited as part of a list.
+ * @obj must be non-NULL.  Input visitors set *@obj to the parsed
+ * string (never NULL); while output visitors leave *@obj unchanged,
+ * except that a NULL *@obj will be treated the same as "".
+ *
+ * FIXME: Unfortunately not const-correct for output visitors.
+ * FIXME: Callers that try to output NULL *obj should not be allowed.
+ */
 void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
-void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
+
+/**
+ * Visit a number value tied to @name in the current object visit.
+ * @name will be NULL if this is visited as part of a list.
+ * Input visitors set *@obj to the value; other visitors will leave
+ * *@obj unchanged.
+ */
+void visit_type_number(Visitor *v, double *obj, const char *name,
+                       Error **errp);
+
+/**
+ * Visit an arbitrary qtype value tied to @name in the current object visit.
+ * @name will be NULL if this is visited as part of a list.
+ * Input visitors set *@obj to the value; other visitors will leave
+ * *@obj (which must not be NULL) unchanged.
+ */
 void visit_type_any(Visitor *v, QObject **obj, const char *name, Error **errp);
+
+/**
+ * Mark the start of visiting the branches of a union. Return true if
+ * @data_present.
+ * FIXME: Should not be needed
+ */
 bool visit_start_union(Visitor *v, bool data_present, Error **errp);
+/**
+ * Mark the end of union branches, after visit_start_union().
+ * FIXME: Should not be needed
+ */
 void visit_end_union(Visitor *v, bool data_present, Error **errp);

 #endif
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 3bd5cae..042ef07 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -18,9 +18,21 @@
 #include "qapi/visitor.h"
 #include "qapi/visitor-impl.h"

+/* Determine if this is an output visitor.
+ * Useful for making some tighter assertions that hold for output
+ * visitors, but not for input or dealloc visitors. */
+static bool visit_is_output(Visitor *v)
+{
+    return v->type_enum == output_type_enum;
+}
+
 void visit_start_struct(Visitor *v, void **obj, size_t size,
                         const char *name, Error **errp)
 {
+    assert(obj ? size : !size);
+    if (obj && visit_is_output(v)) {
+        assert(*obj);
+    }
     v->start_struct(v, obj, size, name, errp);
 }

@@ -32,6 +44,10 @@ void visit_end_struct(Visitor *v, Error **errp)
 void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
                                  Error **errp)
 {
+    assert(obj && size);
+    if (visit_is_output(v)) {
+        assert(*obj);
+    }
     if (v->start_implicit_struct) {
         v->start_implicit_struct(v, obj, size, errp);
     }
@@ -51,6 +67,7 @@ void visit_start_list(Visitor *v, const char *name, Error **errp)

 GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp)
 {
+    assert(list);
     return v->next_list(v, list, errp);
 }

@@ -85,6 +102,7 @@ bool visit_optional(Visitor *v, bool *present, const char *name)
 void visit_get_next_type(Visitor *v, QType *type, bool promote_int,
                          const char *name, Error **errp)
 {
+    assert(type);
     if (v->get_next_type) {
         v->get_next_type(v, type, promote_int, name, errp);
     }
@@ -93,11 +111,13 @@ void visit_get_next_type(Visitor *v, QType *type, bool promote_int,
 void visit_type_enum(Visitor *v, int *obj, const char *const strings[],
                      const char *name, Error **errp)
 {
+    assert(obj && strings);
     v->type_enum(v, obj, strings, name, errp);
 }

 void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
 {
+    assert(obj);
     v->type_int64(v, obj, name, errp);
 }

@@ -144,6 +164,7 @@ void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name,
 void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name,
                        Error **errp)
 {
+    assert(obj);
     v->type_uint64(v, obj, name, errp);
 }

@@ -188,11 +209,13 @@ void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp)

 void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp)
 {
+    assert(obj);
     v->type_int64(v, obj, name, errp);
 }

 void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
 {
+    assert(obj);
     if (v->type_size) {
         v->type_size(v, obj, name, errp);
     } else {
@@ -202,22 +225,35 @@ void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)

 void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
 {
+    assert(obj);
     v->type_bool(v, obj, name, errp);
 }

 void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp)
 {
+    assert(obj);
+    /* TODO: Fix callers to not pass NULL when they mean "", so that we
+     * can enable:
+    if (visit_is_output(v)) {
+        assert(*obj);
+    }
+     */
     v->type_str(v, obj, name, errp);
 }

 void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
 {
+    assert(obj);
     v->type_number(v, obj, name, errp);
 }

 void visit_type_any(Visitor *v, QObject **obj, const char *name,
                     Error **errp)
 {
+    assert(obj);
+    if (visit_is_output(v)) {
+        assert(*obj);
+    }
     v->type_any(v, obj, name, errp);
 }

@@ -228,7 +264,6 @@ void output_type_enum(Visitor *v, int *obj, const char *const strings[],
     int value = *obj;
     char *enum_str;

-    assert(strings);
     while (strings[i++] != NULL);
     if (value < 0 || value >= i - 1) {
         error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
@@ -246,8 +281,6 @@ void input_type_enum(Visitor *v, int *obj, const char *const strings[],
     int64_t value = 0;
     char *enum_str;

-    assert(strings);
-
     visit_type_str(v, &enum_str, name, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
-- 
2.4.3

  parent reply	other threads:[~2015-12-08  3:55 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-08  3:54 [Qemu-devel] [PATCH v7 00/31] qapi visitor cleanups (post-introspection cleanups subset E) Eric Blake
2015-12-08  3:54 ` [Qemu-devel] [PATCH v7 01/31] qobject: Document more shortcomings in our number handling Eric Blake
2015-12-08  3:54 ` [Qemu-devel] [PATCH v7 02/31] qapi: Avoid use of misnamed DO_UPCAST() Eric Blake
2015-12-08  3:54 ` [Qemu-devel] [PATCH v7 03/31] qapi: Drop dead dealloc visitor variable Eric Blake
2015-12-08  3:54 ` [Qemu-devel] [PATCH v7 04/31] hmp: Improve use of qapi visitor Eric Blake
2015-12-08  3:54 ` [Qemu-devel] [PATCH v7 05/31] vl: " Eric Blake
2015-12-08  3:54 ` [Qemu-devel] [PATCH v7 06/31] balloon: " Eric Blake
2015-12-08  3:54 ` [Qemu-devel] [PATCH v7 07/31] qapi: Improve generated event " Eric Blake
2015-12-08  3:54 ` [Qemu-devel] [PATCH v7 08/31] qapi: Track all failures between visit_start/stop Eric Blake
2015-12-08  3:54 ` [Qemu-devel] [PATCH v7 09/31] qapi: Prefer type_int64 over type_int in visitors Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 10/31] qapi: Make all visitors supply uint64 callbacks Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 11/31] qapi: Consolidate visitor small integer callbacks Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 12/31] qapi: Don't cast Enum* to int* Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 13/31] qapi: Drop unused 'kind' for struct/enum visit Eric Blake
2015-12-08  4:40   ` David Gibson
2015-12-11 13:51   ` Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 14/31] qapi: Drop unused error argument for list and implicit struct Eric Blake
2015-12-08  4:40   ` David Gibson
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 15/31] qmp: Fix reference-counting of qnull on empty output visit Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 16/31] qmp: Don't abuse stack to track qmp-output root Eric Blake
2015-12-08  3:55 ` Eric Blake [this message]
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 18/31] qapi: Add visit_type_null() visitor Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 19/31] qmp: Tighten output visitor rules Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 20/31] spapr_drc: Expose 'null' in qom-get when there is no fdt Eric Blake
2015-12-08  4:40   ` David Gibson
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 21/31] qapi: Simplify excess input reporting in input visitors Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 22/31] qapi: Add type.is_empty() helper Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 23/31] qapi: Fix command with named empty argument type Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 24/31] qapi: Eliminate empty visit_type_FOO_fields Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 25/31] qapi: Canonicalize missing object to :empty Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 26/31] qapi-visit: Unify struct and union visit Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 27/31] qapi: Rework deallocation of partial struct Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 28/31] qapi: Split visit_end_struct() into pieces Eric Blake
2015-12-08  4:42   ` David Gibson
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 29/31] qapi: Simplify semantics of visit_next_list() Eric Blake
2015-12-08  4:51   ` David Gibson
2015-12-10 17:32   ` Eric Blake
2015-12-11  4:04     ` Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 30/31] qapi: Change visit_type_FOO() to no longer return partial objects Eric Blake
2015-12-08  3:55 ` [Qemu-devel] [PATCH v7 31/31] RFC: qapi: Adjust layout of FooList types Eric Blake
2015-12-08  4:54   ` David Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1449546921-6378-18-git-send-email-eblake@redhat.com \
    --to=eblake@redhat.com \
    --cc=armbru@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.