All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: Jianjun Duan <duanj@linux.vnet.ibm.com>
Cc: qemu-devel@nongnu.org, qemu-ppc@nongnu.org, dmitry@daynix.com,
	peter.maydell@linaro.org, kraxel@redhat.com, mst@redhat.com,
	david@gibson.dropbear.id.au, pbonzini@redhat.com,
	veroniabahaa@gmail.com, quintela@redhat.com,
	amit.shah@redhat.com, mreitz@redhat.com, kwolf@redhat.com,
	rth@twiddle.net, aurelien@aurel32.net, leon.alrae@imgtec.com,
	blauwirbel@gmail.com, mark.cave-ayland@ilande.co.uk,
	mdroth@linux.vnet.ibm.com
Subject: Re: [Qemu-devel] [QEMU PATCH v9 2/3] migration: migrate QTAILQ
Date: Fri, 28 Oct 2016 20:06:58 +0100	[thread overview]
Message-ID: <20161028190657.GB2173@work-vm> (raw)
In-Reply-To: <1477607317-27817-3-git-send-email-duanj@linux.vnet.ibm.com>

* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> Currently we cannot directly transfer a QTAILQ instance because of the
> limitation in the migration code. Here we introduce an approach to
> transfer such structures. We created VMStateInfo vmstate_info_qtailq
> for QTAILQ. Similar VMStateInfo can be created for other data structures
> such as list.
> 
> This approach will be used to transfer pending_events and ccs_list in spapr
> state.
> 
> We also create some macros in qemu/queue.h to access a QTAILQ using pointer
> arithmetic. This ensures that we do not depend on the implementation
> details about QTAILQ in the migration code.
> 
> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> ---
>  include/migration/vmstate.h | 20 ++++++++++++++
>  include/qemu/queue.h        | 61 +++++++++++++++++++++++++++++++++++++++++
>  migration/trace-events      |  4 +++
>  migration/vmstate.c         | 67 +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 152 insertions(+)
> 
> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> index d0e37b5..318a6f1 100644
> --- a/include/migration/vmstate.h
> +++ b/include/migration/vmstate.h
> @@ -251,6 +251,7 @@ extern const VMStateInfo vmstate_info_timer;
>  extern const VMStateInfo vmstate_info_buffer;
>  extern const VMStateInfo vmstate_info_unused_buffer;
>  extern const VMStateInfo vmstate_info_bitmap;
> +extern const VMStateInfo vmstate_info_qtailq;
>  
>  #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
>  #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
> @@ -662,6 +663,25 @@ extern const VMStateInfo vmstate_info_bitmap;
>      .offset       = offsetof(_state, _field),                        \
>  }
>  
> +/* For QTAILQ that need customized handling.
> + * Target QTAILQ needs be properly initialized.
> + * _type: type of QTAILQ element
> + * _next: name of QTAILQ entry field in QTAILQ element
> + * _vmsd: VMSD for QTAILQ element
> + * size: size of QTAILQ element
> + * start: offset of QTAILQ entry in QTAILQ element
> + */
> +#define VMSTATE_QTAILQ_V(_field, _state, _version, _vmsd, _type, _next)  \
> +{                                                                        \
> +    .name         = (stringify(_field)),                                 \
> +    .version_id   = (_version),                                          \
> +    .vmsd         = &(_vmsd),                                            \
> +    .size         = sizeof(_type),                                       \
> +    .info         = &vmstate_info_qtailq,                                \
> +    .offset       = offsetof(_state, _field),                            \
> +    .start        = offsetof(_type, _next),                              \
> +}
> +
>  /* _f : field name
>     _f_n : num of elements field_name
>     _n : num of elements
> diff --git a/include/qemu/queue.h b/include/qemu/queue.h
> index 342073f..16af127 100644
> --- a/include/qemu/queue.h
> +++ b/include/qemu/queue.h
> @@ -438,4 +438,65 @@ struct {                                                                \
>  #define QTAILQ_PREV(elm, headname, field) \
>          (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
>  
> +#define field_at_offset(base, offset, type)                                    \
> +        ((type) (((char *) (base)) + (offset)))
> +
> +typedef struct DUMB_Q_ENTRY DUMB_Q_ENTRY;
> +typedef struct DUMB_Q DUMB_Q;
> +
> +struct DUMB_Q_ENTRY {
> +        QTAILQ_ENTRY(DUMB_Q_ENTRY) next;
> +};
> +
> +struct DUMB_Q {
> +        QTAILQ_HEAD(DUMB_Q_HEAD, DUMB_Q_ENTRY) head;
> +};

OK, good we've got rid of the hard coded offsets; thanks!

> +#define dumb_q ((DUMB_Q *) 0)
> +#define dumb_qh ((typeof(dumb_q->head) *) 0)
> +#define dumb_qe ((DUMB_Q_ENTRY *) 0)

Note that 'dumb' and 'dummy' are completely different words;
this is a dummy not a dumb.

> +/*
> + * Offsets of layout of a tail queue head.
> + */
> +#define QTAILQ_FIRST_OFFSET ((size_t) &(QTAILQ_FIRST(dumb_qh)))

Isn't that just  offsetof(dumb_qh, tqh_first) ?

> +#define QTAILQ_LAST_OFFSET  (offsetof(typeof(dumb_q->head), tqh_last))

Similarly isnt't that just  offsetof(DUMB_Q_HEAD, tqh_last) ?

> +/*
> + * Raw access of elements of a tail queue
> + */
> +#define QTAILQ_RAW_FIRST(head)                                                 \
> +        (*field_at_offset(head, QTAILQ_FIRST_OFFSET, void **))
> +#define QTAILQ_RAW_LAST(head)                                                  \
> +        (*field_at_offset(head, QTAILQ_LAST_OFFSET, void ***))
> +
> +/*
> + * Offsets of layout of a tail queue element.
> + */
> +#define QTAILQ_NEXT_OFFSET ((size_t) (&QTAILQ_NEXT(dumb_qe, next)))
> +#define QTAILQ_PREV_OFFSET (offsetof(typeof(dumb_qe->next), tqe_prev))

Similar comments to the pair above.

Dave
P.S. I'm out next week, so please someone else jump in.

> +/*
> + * Raw access of elements of a tail entry
> + */
> +#define QTAILQ_RAW_NEXT(elm, entry)                                            \
> +        (*field_at_offset(elm, entry + QTAILQ_NEXT_OFFSET, void **))
> +#define QTAILQ_RAW_PREV(elm, entry)                                            \
> +        (*field_at_offset(elm, entry + QTAILQ_PREV_OFFSET, void ***))
> +/*
> + * Tail queue tranversal using pointer arithmetic.
> + */
> +#define QTAILQ_RAW_FOREACH(elm, head, entry)                                   \
> +        for ((elm) = QTAILQ_RAW_FIRST(head);                                   \
> +             (elm);                                                            \
> +             (elm) = QTAILQ_RAW_NEXT(elm, entry))
> +/*
> + * Tail queue insertion using pointer arithmetic.
> + */
> +#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do {                          \
> +        QTAILQ_RAW_NEXT(elm, entry) = NULL;                                    \
> +        QTAILQ_RAW_PREV(elm, entry) = QTAILQ_RAW_LAST(head);                   \
> +        *QTAILQ_RAW_LAST(head) = (elm);                                        \
> +        QTAILQ_RAW_LAST(head) = &QTAILQ_RAW_NEXT(elm, entry);                  \
> +} while (/*CONSTCOND*/0)
> +
>  #endif /* QEMU_SYS_QUEUE_H */
> diff --git a/migration/trace-events b/migration/trace-events
> index dfee75a..9a6ec59 100644
> --- a/migration/trace-events
> +++ b/migration/trace-events
> @@ -52,6 +52,10 @@ vmstate_n_elems(const char *name, int n_elems) "%s: %d"
>  vmstate_subsection_load(const char *parent) "%s"
>  vmstate_subsection_load_bad(const char *parent,  const char *sub, const char *sub2) "%s: %s/%s"
>  vmstate_subsection_load_good(const char *parent) "%s"
> +get_qtailq(const char *name, int version_id) "%s v%d"
> +get_qtailq_end(const char *name, const char *reason, int val) "%s %s/%d"
> +put_qtailq(const char *name, int version_id) "%s v%d"
> +put_qtailq_end(const char *name, const char *reason) "%s %s"
>  
>  # migration/qemu-file.c
>  qemu_file_fclose(void) ""
> diff --git a/migration/vmstate.c b/migration/vmstate.c
> index d188afa..70e0472 100644
> --- a/migration/vmstate.c
> +++ b/migration/vmstate.c
> @@ -5,6 +5,7 @@
>  #include "migration/vmstate.h"
>  #include "qemu/bitops.h"
>  #include "qemu/error-report.h"
> +#include "qemu/queue.h"
>  #include "trace.h"
>  #include "migration/qjson.h"
>  
> @@ -948,3 +949,69 @@ const VMStateInfo vmstate_info_bitmap = {
>      .get = get_bitmap,
>      .put = put_bitmap,
>  };
> +
> +/* get for QTAILQ
> + * meta data about the QTAILQ is encoded in a VMStateField structure
> + */
> +static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
> +                      VMStateField *field)
> +{
> +    int ret = 0;
> +    const VMStateDescription *vmsd = field->vmsd;
> +    /* size of a QTAILQ element */
> +    size_t size = field->size;
> +    /* offset of the QTAILQ entry in a QTAILQ element */
> +    size_t entry_offset = field->start;
> +    int version_id = field->version_id;
> +    void *elm;
> +
> +    trace_get_qtailq(vmsd->name, version_id);
> +    if (version_id > vmsd->version_id) {
> +        error_report("%s %s",  vmsd->name, "too new");
> +        trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
> +
> +        return -EINVAL;
> +    }
> +    if (version_id < vmsd->minimum_version_id) {
> +        error_report("%s %s",  vmsd->name, "too old");
> +        trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
> +        return -EINVAL;
> +    }
> +
> +    while (qemu_get_byte(f)) {
> +        elm = g_malloc(size);
> +        ret = vmstate_load_state(f, vmsd, elm, version_id);
> +        if (ret) {
> +            return ret;
> +        }
> +        QTAILQ_RAW_INSERT_TAIL(pv, elm, entry_offset);
> +    }
> +
> +    trace_get_qtailq_end(vmsd->name, "end", ret);
> +    return ret;
> +}
> +
> +/* put for QTAILQ */
> +static void put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
> +                       VMStateField *field, QJSON *vmdesc)
> +{
> +    const VMStateDescription *vmsd = field->vmsd;
> +    /* offset of the QTAILQ entry in a QTAILQ element*/
> +    size_t entry_offset = field->start;
> +    void *elm;
> +
> +    trace_put_qtailq(vmsd->name, vmsd->version_id);
> +
> +    QTAILQ_RAW_FOREACH(elm, pv, entry_offset) {
> +        qemu_put_byte(f, true);
> +        vmstate_save_state(f, vmsd, elm, vmdesc);
> +    }
> +    qemu_put_byte(f, false);
> +
> +    trace_put_qtailq_end(vmsd->name, "end");
> +}
> +const VMStateInfo vmstate_info_qtailq = {
> +    .name = "qtailq",
> +    .get  = get_qtailq,
> +    .put  = put_qtailq,
> +};
> -- 
> 1.9.1
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

  reply	other threads:[~2016-10-28 19:07 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-27 22:28 [Qemu-devel] [QEMU PATCH v9 0/3] migration: migrate QTAILQ Jianjun Duan
2016-10-27 22:28 ` [Qemu-devel] [QEMU PATCH v9 1/3] migration: extend VMStateInfo Jianjun Duan
2016-10-27 22:28 ` [Qemu-devel] [QEMU PATCH v9 2/3] migration: migrate QTAILQ Jianjun Duan
2016-10-28 19:06   ` Dr. David Alan Gilbert [this message]
2016-10-28 19:46     ` Jianjun Duan
2016-10-31 13:10       ` Halil Pasic
2016-10-31 17:10         ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
2016-10-31 17:21           ` Halil Pasic
2016-10-31 17:32             ` Jianjun Duan
2016-10-31 18:01               ` Halil Pasic
2016-10-31 18:25                 ` Jianjun Duan
2016-10-31 19:02                   ` Halil Pasic
2016-11-01 15:02         ` [Qemu-devel] " Paolo Bonzini
2016-11-01 15:47           ` Halil Pasic
2016-10-27 22:28 ` [Qemu-devel] [QEMU PATCH v9 3/3] tests/migration: Add test for QTAILQ migration Jianjun Duan
2016-10-28 13:57 ` [Qemu-devel] [QEMU PATCH v9 0/3] migration: migrate QTAILQ no-reply

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=20161028190657.GB2173@work-vm \
    --to=dgilbert@redhat.com \
    --cc=amit.shah@redhat.com \
    --cc=aurelien@aurel32.net \
    --cc=blauwirbel@gmail.com \
    --cc=david@gibson.dropbear.id.au \
    --cc=dmitry@daynix.com \
    --cc=duanj@linux.vnet.ibm.com \
    --cc=kraxel@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=leon.alrae@imgtec.com \
    --cc=mark.cave-ayland@ilande.co.uk \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=mreitz@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    --cc=quintela@redhat.com \
    --cc=rth@twiddle.net \
    --cc=veroniabahaa@gmail.com \
    /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.