diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 128f074..ae7b1a5 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -1,7 +1,7 @@
 = How to use the QAPI code generator =

 Copyright IBM Corp. 2011
-Copyright (C) 2012-2015 Red Hat, Inc.
+Copyright (C) 2012-2016 Red Hat, Inc.

 This work is licensed under the terms of the GNU GPL, version 2 or
 later. See the COPYING file in the top-level directory.
@@ -655,7 +655,7 @@ Union types

     { "name": "BlockdevOptions", "meta-type": "object",
       "members": [
-          { "name": "kind", "type": "BlockdevOptionsKind" } ],
+          { "name": "type", "type": "BlockdevOptionsKind" } ],
       "tag": "type",
       "variants": [
           { "case": "file", "type": ":obj-FileOptions-wrapper" },
@@ -721,29 +721,34 @@ the names of built-in types.  Clients should examine member

 == Code generation ==

-Schemas are fed into four scripts to generate all the code/files that,
+Schemas are fed into five scripts to generate all the code/files that,
 paired with the core QAPI libraries, comprise everything required to
 take JSON commands read in by a Client JSON Protocol server, unmarshal
 the arguments into the underlying C types, call into the corresponding
-C function, and map the response back to a Client JSON Protocol
-response to be returned to the user.
+C function, map the response back to a Client JSON Protocol response
+to be returned to the user, and introspect the commands.

-As an example, we'll use the following schema, which describes a single
-complex user-defined type (which will produce a C struct, along with a list
-node structure that can be used to chain together a list of such types in
-case we want to accept/return a list of this type with a command), and a
-command which takes that type as a parameter and returns the same type:
+As an example, we'll use the following schema, which describes a
+single complex user-defined type, along with command which takes a
+list of that type as a parameter.  The user is responsible for writing
+the implementation of qmp_my_command(); everything else is produced by
+the generator.

     $ cat example-schema.json
     { 'struct': 'UserDefOne',
-      'data': { 'integer': 'int', 'string': 'str' } }
+      'data': { 'integer': 'int', '*string': 'str' } }

     { 'command': 'my-command',
-      'data':    {'arg1': 'UserDefOne'},
+      'data':    { 'arg1': ['UserDefOne'] },
       'returns': 'UserDefOne' }

     { 'event': 'MY_EVENT' }

+For a more thorough look at generated code, the testsuite includes
+tests/qapi-schema/qapi-schema-tests.json that covers more examples of
+what the generator will accept, and compiles the resulting C code as
+part of 'make check-unit'.
+
 === scripts/qapi-types.py ===

 Used to generate the C types defined by a schema. The following files are
@@ -776,7 +781,7 @@ Example:

         qdv = qapi_dealloc_visitor_new();
         v = qapi_dealloc_get_visitor(qdv);
-        visit_type_UserDefOne(v, &obj, NULL, NULL);
+        visit_type_UserDefOne(v, NULL, &obj, NULL);
         qapi_dealloc_visitor_cleanup(qdv);
     }

@@ -791,7 +796,7 @@ Example:

         qdv = qapi_dealloc_visitor_new();
         v = qapi_dealloc_get_visitor(qdv);
-        visit_type_UserDefOneList(v, &obj, NULL, NULL);
+        visit_type_UserDefOneList(v, NULL, &obj, NULL);
         qapi_dealloc_visitor_cleanup(qdv);
     }
     $ cat qapi-generated/example-qapi-types.h
@@ -808,17 +813,15 @@ Example:

     struct UserDefOne {
         int64_t integer;
+        bool has_string;
         char *string;
     };

     void qapi_free_UserDefOne(UserDefOne *obj);

     struct UserDefOneList {
-        union {
-            UserDefOne *value;
-            uint64_t padding;
-        };
         UserDefOneList *next;
+        UserDefOne *value;
     };

     void qapi_free_UserDefOneList(UserDefOneList *obj);
@@ -854,54 +857,76 @@ Example:
     {
         Error *err = NULL;

-        visit_type_int(v, &(*obj)->integer, "integer", &err);
+        visit_type_int(v, "integer", &(*obj)->integer, &err);
         if (err) {
             goto out;
         }
-        visit_type_str(v, &(*obj)->string, "string", &err);
-        if (err) {
-            goto out;
+        if (visit_optional(v, "string", &(*obj)->has_string)) {
+            visit_type_str(v, "string", &(*obj)->string, &err);
+            if (err) {
+                goto out;
+            }
         }

     out:
         error_propagate(errp, err);
     }

-    void visit_type_UserDefOne(Visitor *v, UserDefOne **obj, const char *name, Error **errp)
+    void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp)
     {
         Error *err = NULL;
+        bool allocated;

-        visit_start_struct(v, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), &err);
-        if (!err) {
-            if (*obj) {
-                visit_type_UserDefOne_fields(v, obj, errp);
-            }
-            visit_end_struct(v, &err);
+        allocated = visit_start_struct(v, name, (void **)obj, sizeof(UserDefOne),
+                                       &err);
+        if (err) {
+            goto out;
+        }
+        if (!*obj) {
+            goto out_obj;
+        }
+        visit_type_UserDefOne_fields(v, obj, &err);
+        if (err) {
+            goto out_obj;
         }
+        visit_check_struct(v, &err);
+    out_obj:
+        visit_end_struct(v);
+        if (allocated && err) {
+            qapi_free_UserDefOne(*obj);
+            *obj = NULL;
+        }
+    out:
         error_propagate(errp, err);
     }

-    void visit_type_UserDefOneList(Visitor *v, UserDefOneList **obj, const char *name, Error **errp)
+    void visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp)
     {
         Error *err = NULL;
-        GenericList *i, **prev;
+        UserDefOneList *eld;
+        bool allocated;

-        visit_start_list(v, name, &err);
+        allocated = visit_start_list(v, name, (GenericList **)obj, sizeof(UserDefOneList), &err);
         if (err) {
             goto out;
         }
-
-        for (prev = (GenericList **)obj;
-             !err && (i = visit_next_list(v, prev, &err)) != NULL;
-             prev = &i) {
-            UserDefOneList *native_i = (UserDefOneList *)i;
-            visit_type_UserDefOne(v, &native_i->value, NULL, &err);
+        elt = *obj;
+        while (elt) {
+            visit_type_UserDefOne(v, NULL, &elt->value, &err);
+            if (err) {
+                break;
+            }
+            elt = (UserDefOneList *)visit_next_list(v, (GenericList *)elt, sizeof(UserDefOneList), &err);
+            if (err) {
+                break;
+            }
         }
-
-        error_propagate(errp, err);
-        err = NULL;
-        visit_end_list(v, &err);
+        visit_end_list(v);
     out:
+        if (allocated && err) {
+            qapi_free_UserDefOneList(*obj);
+            *obj = NULL;
+        }
         error_propagate(errp, err);
     }
     $ cat qapi-generated/example-qapi-visit.h
@@ -912,8 +937,8 @@ Example:

 [Visitors for built-in types omitted...]

-    void visit_type_UserDefOne(Visitor *v, UserDefOne **obj, const char *name, Error **errp);
-    void visit_type_UserDefOneList(Visitor *v, UserDefOneList **obj, const char *name, Error **errp);
+    void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp);
+    void visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp);

     #endif

@@ -949,7 +974,7 @@ Example:
         Visitor *v;

         v = qmp_output_get_visitor(qov);
-        visit_type_UserDefOne(v, &ret_in, "unused", &err);
+        visit_type_UserDefOne(v, "unused", &ret_in, &err);
         if (err) {
             goto out;
         }
@@ -960,7 +985,7 @@ Example:
         qmp_output_visitor_cleanup(qov);
         qdv = qapi_dealloc_visitor_new();
         v = qapi_dealloc_get_visitor(qdv);
-        visit_type_UserDefOne(v, &ret_in, "unused", NULL);
+        visit_type_UserDefOne(v, "unused", &ret_in, NULL);
         qapi_dealloc_visitor_cleanup(qdv);
     }

@@ -971,10 +996,10 @@ Example:
         QmpInputVisitor *qiv = qmp_input_visitor_new_strict(QOBJECT(args));
         QapiDeallocVisitor *qdv;
         Visitor *v;
-        UserDefOne *arg1 = NULL;
+        UserDefOneList *arg1 = NULL;

         v = qmp_input_get_visitor(qiv);
-        visit_type_UserDefOne(v, &arg1, "arg1", &err);
+        visit_type_UserDefOne(v, "arg1", &arg1, &err);
         if (err) {
             goto out;
         }
@@ -991,7 +1016,7 @@ Example:
         qmp_input_visitor_cleanup(qiv);
         qdv = qapi_dealloc_visitor_new();
         v = qapi_dealloc_get_visitor(qdv);
-        visit_type_UserDefOne(v, &arg1, "arg1", NULL);
+        visit_type_UserDefOne(v, "arg1", &arg1, NULL);
         qapi_dealloc_visitor_cleanup(qdv);
     }

@@ -1011,7 +1036,7 @@ Example:
     #include "qapi/qmp/qdict.h"
     #include "qapi/error.h"

-    UserDefOne *qmp_my_command(UserDefOne *arg1, Error **errp);
+    UserDefOne *qmp_my_command(UserDefOneList *arg1, Error **errp);

     #endif

@@ -1095,8 +1120,9 @@ Example:
         "{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": \"MY_EVENT\"}, "
         "{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": \"my-command\", \"ret-type\": \"2\"}, "
         "{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, "
-        "{\"members\": [{\"name\": \"arg1\", \"type\": \"2\"}], \"meta-type\": \"object\", \"name\": \"1\"}, "
-        "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, "
+        "{\"members\": [{\"name\": \"arg1\", \"type\": \"[2]\"}], \"meta-type\": \"object\", \"name\": \"1\"}, "
+        "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"default\": null, \"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, "
+        "{\"element-type\": \"2\", \"meta-type\": \"array\", \"name\": \"[2]\"}, "
         "{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"int\"}, "
         "{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": \"str\"}]";
     $ cat qapi-generated/example-qmp-introspect.h
