[01/12] chardev: ringbuf: add optional save parameter to save state

Submitted by Anthony Liguori on June 19, 2013, 8:40 p.m.

Details

Message ID 1371674435-14973-2-git-send-email-aliguori@us.ibm.com
State New
Headers show

Commit Message

Anthony Liguori June 19, 2013, 8:40 p.m.
It is very useful to use the ringbuf chardev for writing test
cases and even more useful if the state of the ringbuf is migrated
with the guest.  Otherwise it's hard to detect data loss in a test
case.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 qapi-schema.json |  3 ++-
 qemu-char.c      | 45 +++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 45 insertions(+), 3 deletions(-)

Comments

Eric Blake June 20, 2013, 7:49 p.m.
On 06/19/2013 09:40 PM, Anthony Liguori wrote:
> It is very useful to use the ringbuf chardev for writing test
> cases and even more useful if the state of the ringbuf is migrated
> with the guest.  Otherwise it's hard to detect data loss in a test
> case.
> 
> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
> ---
>  qapi-schema.json |  3 ++-
>  qemu-char.c      | 45 +++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 45 insertions(+), 3 deletions(-)
> 
> diff --git a/qapi-schema.json b/qapi-schema.json
> index a80ee40..90602d1 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -3280,10 +3280,11 @@
>  # Configuration info for memory chardevs
>  #
>  # @size: #optional Ringbuffer size, must be power of two, default is 65536
> +# @save: #optional Register a savevm handler, default false

Useful to have a '(since 1.6)' notation on the added field.

>  #
>  # Since: 1.5
>  ##
> -{ 'type': 'ChardevMemory', 'data': { '*size'  : 'int' } }
> +{ 'type': 'ChardevMemory', 'data': { '*size'  : 'int', '*save': 'bool' } }

Yet another case for introspection discovering an added feature to an
existing command.

Patch hide | download patch | download mbox

diff --git a/qapi-schema.json b/qapi-schema.json
index a80ee40..90602d1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3280,10 +3280,11 @@ 
 # Configuration info for memory chardevs
 #
 # @size: #optional Ringbuffer size, must be power of two, default is 65536
+# @save: #optional Register a savevm handler, default false
 #
 # Since: 1.5
 ##
-{ 'type': 'ChardevMemory', 'data': { '*size'  : 'int' } }
+{ 'type': 'ChardevMemory', 'data': { '*size'  : 'int', '*save': 'bool' } }
 
 ##
 # @ChardevBackend:
diff --git a/qemu-char.c b/qemu-char.c
index 2c3cfe6..87ba24f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2793,7 +2793,32 @@  static void ringbuf_chr_close(struct CharDriverState *chr)
     chr->opaque = NULL;
 }
 
-static CharDriverState *qemu_chr_open_memory(ChardevMemory *opts,
+static void ringbuf_save(QEMUFile *f, void *opaque)
+{
+    CharDriverState *chr = opaque;
+    RingBufCharDriver *d = chr->opaque;
+
+    qemu_put_be32(f, d->prod);
+    qemu_put_be32(f, d->cons);
+    qemu_put_be32(f, d->size);
+    qemu_put_buffer(f, d->cbuf, d->size);
+}
+
+static int ringbuf_load(QEMUFile *f, void *opaque, int version_id)
+{
+    CharDriverState *chr = opaque;
+    RingBufCharDriver *d = chr->opaque;
+
+    d->prod = qemu_get_be32(f);
+    d->cons = qemu_get_be32(f);
+    d->size = qemu_get_be32(f);
+    qemu_get_buffer(f, d->cbuf, d->size);
+
+    return 0;
+}
+
+static CharDriverState *qemu_chr_open_memory(const char *id,
+                                             ChardevMemory *opts,
                                              Error **errp)
 {
     CharDriverState *chr;
@@ -2804,6 +2829,14 @@  static CharDriverState *qemu_chr_open_memory(ChardevMemory *opts,
 
     d->size = opts->has_size ? opts->size : 65536;
 
+    if (opts->has_save && opts->save) {
+        char *idstr;
+
+        g_assert(id != NULL);
+        idstr = g_strdup_printf("memchar-%s", id);
+        register_savevm(NULL, idstr, 0, 1, ringbuf_save, ringbuf_load, chr);
+    }
+
     /* The size must be power of 2 */
     if (d->size & (d->size - 1)) {
         error_setg(errp, "size of memory chardev must be power of two");
@@ -3120,6 +3153,11 @@  static void qemu_chr_parse_memory(QemuOpts *opts, ChardevBackend *backend,
         backend->memory->has_size = true;
         backend->memory->size = val;
     }
+
+    if (qemu_opt_get_bool(opts, "save", false)) {
+        backend->memory->has_save = true;
+        backend->memory->save = true;
+    }
 }
 
 typedef struct CharDriver {
@@ -3489,6 +3527,9 @@  QemuOptsList qemu_chardev_opts = {
         },{
             .name = "size",
             .type = QEMU_OPT_SIZE,
+        }, {
+            .name = "save",
+            .type = QEMU_OPT_BOOL,
         },
         { /* end of list */ }
     },
@@ -3711,7 +3752,7 @@  ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
         chr = vc_init(backend->vc);
         break;
     case CHARDEV_BACKEND_KIND_MEMORY:
-        chr = qemu_chr_open_memory(backend->memory, errp);
+        chr = qemu_chr_open_memory(id, backend->memory, errp);
         break;
     default:
         error_setg(errp, "unknown chardev backend (%d)", backend->kind);