This patch series enables libxl to set dirty log on QEMU upstream during migration through a new QMP command. The success of the call depends on the presence of the specific QMP command xen-set-global-dirty-log in QEMU. Patches for this command have been sent. There is several patches that cleanup a bit the libxl_json/qmp codes. Change since v3: - Update the comment on the first patch to say that NOGC can be used. Anthony PERARD (10): libxl_json: Export json_object related function. libxl_json: Remove JSON_ERROR from enum. libxl_json: Replace JSON_TRUE/FALSE by JSON_BOOL. libxl_json: Introduce libxl__json_object_to_yajl_gen. libxl_qmp: Introduces helpers to create an argument list. libxl_qmp: Use qmp_parameters_* functions for param list of a QMP command. libxl_qmp: Simplify run of single QMP commands. libxl_qmp: Introduce libxl__qmp_set_global_dirty_log. libxl_dom: Call the right switch logdirty for the right DM. libxl: Allow migration with qemu-xen. tools/libxl/libxl.c | 17 ---- tools/libxl/libxl_dom.c | 45 ++++++++++- tools/libxl/libxl_internal.h | 35 ++++++-- tools/libxl/libxl_json.c | 95 ++++++++++++++++++---- tools/libxl/libxl_qmp.c | 189 ++++++++++++++++++++++++------------------- 5 files changed, 254 insertions(+), 127 deletions(-) -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 01/10] libxl_json: Export json_object related function.
Export libxl__json_object_alloc and libxl__json_object_append_to to use them in a later patch. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_internal.h | 14 ++++++++++++-- tools/libxl/libxl_json.c | 34 +++++++++++++++++----------------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index c0e879d..cdf5300 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1516,6 +1516,15 @@ static inline long long libxl__json_object_get_integer(const libxl__json_object return -1; } +/* + * NOGC can be used with those json_object functions, but the + * libxl__json_object* will need to be freed with libxl__json_object_free. + */ +_hidden libxl__json_object *libxl__json_object_alloc(libxl__gc *gc_opt, + libxl__json_node_type type); +_hidden int libxl__json_object_append_to(libxl__gc *gc_opt, + libxl__json_object *obj, + libxl__json_object *dst); _hidden libxl__json_object *libxl__json_array_get(const libxl__json_object *o, int i); _hidden @@ -1524,9 +1533,10 @@ libxl__json_map_node *libxl__json_map_node_get(const libxl__json_object *o, _hidden const libxl__json_object *libxl__json_map_get(const char *key, const libxl__json_object *o, libxl__json_node_type expected_type); -_hidden void libxl__json_object_free(libxl__gc *gc, libxl__json_object *obj); +_hidden void libxl__json_object_free(libxl__gc *gc_opt, + libxl__json_object *obj); -_hidden libxl__json_object *libxl__json_parse(libxl__gc *gc, const char *s); +_hidden libxl__json_object *libxl__json_parse(libxl__gc *gc_opt, const char *s); /* Based on /local/domain/$domid/dm-version xenstore key * default is qemu xen traditional */ diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c index 3cba48f..a045594 100644 --- a/tools/libxl/libxl_json.c +++ b/tools/libxl/libxl_json.c @@ -205,7 +205,7 @@ yajl_gen_status libxl__string_gen_json(yajl_gen hand, * libxl__json_object helper functions */ -static libxl__json_object *json_object_alloc(libxl__gc *gc, +libxl__json_object *libxl__json_object_alloc(libxl__gc *gc, libxl__json_node_type type) { libxl__json_object *obj; @@ -225,7 +225,7 @@ static libxl__json_object *json_object_alloc(libxl__gc *gc, return obj; } -static int json_object_append_to(libxl__gc *gc, +int libxl__json_object_append_to(libxl__gc *gc, libxl__json_object *obj, libxl__json_object *dst) { @@ -378,9 +378,9 @@ static int json_callback_null(void *opaque) DEBUG_GEN(ctx, null); - obj = json_object_alloc(ctx->gc, JSON_NULL); + obj = libxl__json_object_alloc(ctx->gc, JSON_NULL); - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { return 0; } @@ -394,10 +394,10 @@ static int json_callback_boolean(void *opaque, int boolean) DEBUG_GEN_VALUE(ctx, bool, boolean); - obj = json_object_alloc(ctx->gc, - boolean ? JSON_TRUE : JSON_FALSE); + obj = libxl__json_object_alloc(ctx->gc, + boolean ? JSON_TRUE : JSON_FALSE); - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { return 0; } @@ -429,7 +429,7 @@ static int json_callback_number(void *opaque, const char *s, libxl_yajl_length l goto error; } - obj = json_object_alloc(ctx->gc, JSON_DOUBLE); + obj = libxl__json_object_alloc(ctx->gc, JSON_DOUBLE); obj->u.d = d; } else { long long i = strtoll(s, NULL, 10); @@ -438,14 +438,14 @@ static int json_callback_number(void *opaque, const char *s, libxl_yajl_length l goto error; } - obj = json_object_alloc(ctx->gc, JSON_INTEGER); + obj = libxl__json_object_alloc(ctx->gc, JSON_INTEGER); obj->u.i = i; } goto out; error: /* If the conversion fail, we just store the original string. */ - obj = json_object_alloc(ctx->gc, JSON_NUMBER); + obj = libxl__json_object_alloc(ctx->gc, JSON_NUMBER); t = libxl__zalloc(ctx->gc, len + 1); strncpy(t, s, len); @@ -454,7 +454,7 @@ error: obj->u.string = t; out: - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { return 0; } @@ -475,10 +475,10 @@ static int json_callback_string(void *opaque, const unsigned char *str, strncpy(t, (const char *) str, len); t[len] = 0; - obj = json_object_alloc(ctx->gc, JSON_STRING); + obj = libxl__json_object_alloc(ctx->gc, JSON_STRING); obj->u.string = t; - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { return 0; } @@ -524,10 +524,10 @@ static int json_callback_start_map(void *opaque) DEBUG_GEN(ctx, map_open); - obj = json_object_alloc(ctx->gc, JSON_MAP); + obj = libxl__json_object_alloc(ctx->gc, JSON_MAP); if (ctx->current) { - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { return 0; } } @@ -564,10 +564,10 @@ static int json_callback_start_array(void *opaque) DEBUG_GEN(ctx, array_open); - obj = json_object_alloc(ctx->gc, JSON_ARRAY); + obj = libxl__json_object_alloc(ctx->gc, JSON_ARRAY); if (ctx->current) { - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { + if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { return 0; } } -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 02/10] libxl_json: Remove JSON_ERROR from enum.
This value from libxl__json_node_type is never used. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_internal.h | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index cdf5300..6977a6d 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1432,7 +1432,6 @@ _hidden yajl_gen_status libxl__yajl_gen_asciiz(yajl_gen hand, const char *str); _hidden yajl_gen_status libxl__yajl_gen_enum(yajl_gen hand, const char *str); typedef enum { - JSON_ERROR, JSON_NULL, JSON_TRUE, JSON_FALSE, -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 03/10] libxl_json: Replace JSON_TRUE/FALSE by JSON_BOOL.
Those two JSON_TRUE and JSON_FALSE were types of node. But it''s better to have a unique JSON_BOOL type. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_internal.h | 15 +++++++++++++-- tools/libxl/libxl_json.c | 4 ++-- tools/libxl/libxl_qmp.c | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 6977a6d..6744fda 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1433,8 +1433,7 @@ _hidden yajl_gen_status libxl__yajl_gen_enum(yajl_gen hand, const char *str); typedef enum { JSON_NULL, - JSON_TRUE, - JSON_FALSE, + JSON_BOOL, JSON_INTEGER, JSON_DOUBLE, /* number is store in string, it''s too big to be a long long or a double */ @@ -1448,6 +1447,7 @@ typedef enum { typedef struct libxl__json_object { libxl__json_node_type type; union { + bool b; long long i; double d; char *string; @@ -1466,6 +1466,10 @@ typedef struct { typedef struct libxl__yajl_ctx libxl__yajl_ctx; +static inline bool libxl__json_object_is_bool(const libxl__json_object *o) +{ + return o != NULL && o->type == JSON_BOOL; +} static inline bool libxl__json_object_is_string(const libxl__json_object *o) { return o != NULL && o->type == JSON_STRING; @@ -1483,6 +1487,13 @@ static inline bool libxl__json_object_is_array(const libxl__json_object *o) return o != NULL && o->type == JSON_ARRAY; } +static inline bool libxl__json_object_get_bool(const libxl__json_object *o) +{ + if (libxl__json_object_is_bool(o)) + return o->u.b; + else + return false; +} static inline const char *libxl__json_object_get_string(const libxl__json_object *o) { diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c index a045594..26a7370 100644 --- a/tools/libxl/libxl_json.c +++ b/tools/libxl/libxl_json.c @@ -394,8 +394,8 @@ static int json_callback_boolean(void *opaque, int boolean) DEBUG_GEN_VALUE(ctx, bool, boolean); - obj = libxl__json_object_alloc(ctx->gc, - boolean ? JSON_TRUE : JSON_FALSE); + obj = libxl__json_object_alloc(ctx->gc, JSON_BOOL); + obj->u.b = boolean; if (libxl__json_object_append_to(ctx->gc, obj, ctx->current) == -1) { return 0; diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index 15550e7..9109ac5 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -178,7 +178,8 @@ static int qmp_register_vnc_callback(libxl__qmp_handler *qmp, goto out; } - if (libxl__json_map_get("enabled", o, JSON_FALSE)) { + obj = libxl__json_map_get("enabled", o, JSON_BOOL); + if (!obj || !libxl__json_object_get_bool(obj)) { rc = 0; goto out; } -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 04/10] libxl_json: Introduce libxl__json_object_to_yajl_gen.
This function converts a libxl__json_object to yajl by calling every yajl_gen_* function on a preallocated yajl_gen hand. This helps to integrate a json_object into an already existing yajl_gen tree. This function is used in a later patch. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_internal.h | 3 +++ tools/libxl/libxl_json.c | 61 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 6744fda..04ca5a5 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1543,6 +1543,9 @@ libxl__json_map_node *libxl__json_map_node_get(const libxl__json_object *o, _hidden const libxl__json_object *libxl__json_map_get(const char *key, const libxl__json_object *o, libxl__json_node_type expected_type); +_hidden yajl_status libxl__json_object_to_yajl_gen(libxl__gc *gc_opt, + yajl_gen hand, + libxl__json_object *param); _hidden void libxl__json_object_free(libxl__gc *gc_opt, libxl__json_object *obj); diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c index 26a7370..f5d87f7 100644 --- a/tools/libxl/libxl_json.c +++ b/tools/libxl/libxl_json.c @@ -366,6 +366,67 @@ const libxl__json_object *libxl__json_map_get(const char *key, return NULL; } +yajl_status libxl__json_object_to_yajl_gen(libxl__gc *gc, + yajl_gen hand, + libxl__json_object *obj) +{ + int index = 0; + yajl_status rc; + + switch (obj->type) { + case JSON_NULL: + return yajl_gen_null(hand); + case JSON_BOOL: + return yajl_gen_bool(hand, obj->u.b); + case JSON_INTEGER: + return yajl_gen_integer(hand, obj->u.i); + case JSON_DOUBLE: + return yajl_gen_double(hand, obj->u.d); + case JSON_NUMBER: + return yajl_gen_number(hand, obj->u.string, strlen(obj->u.string)); + case JSON_STRING: + return libxl__yajl_gen_asciiz(hand, obj->u.string); + case JSON_MAP: { + libxl__json_map_node *node = NULL; + + rc = yajl_gen_map_open(hand); + if (rc != yajl_status_ok) + return rc; + for (index = 0; index < obj->u.map->count; index++) { + if (flexarray_get(obj->u.map, index, (void**)&node) != 0) + break; + + rc = libxl__yajl_gen_asciiz(hand, node->map_key); + if (rc != yajl_status_ok) + return rc; + rc = libxl__json_object_to_yajl_gen(gc, hand, node->obj); + if (rc != yajl_status_ok) + return rc; + } + return yajl_gen_map_close(hand); + } + case JSON_ARRAY: { + libxl__json_object *node = NULL; + + rc = yajl_gen_array_open(hand); + if (rc != yajl_status_ok) + return rc; + for (index = 0; index < obj->u.array->count; index++) { + if (flexarray_get(obj->u.array, index, (void**)&node) != 0) + break; + rc = libxl__json_object_to_yajl_gen(gc, hand, node); + if (rc != yajl_status_ok) + return rc; + } + return yajl_gen_array_close(hand); + } + case JSON_ANY: + /* JSON_ANY is not a valid value for obj->type. */ + ; + } + abort(); +} + /* * JSON callbacks -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 05/10] libxl_qmp: Introduces helpers to create an argument list.
Those functions will be used to create a "list" of parameters that contain more than just strings. This list is converted by qmp_send to a string to be sent to QEMU. Those functions will be used in the next two patches, so right now there are not compiled. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_qmp.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index 9109ac5..d86f290 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -623,6 +623,57 @@ static void qmp_free_handler(libxl__qmp_handler *qmp) free(qmp); } +#if 0 +/* + * QMP Parameters Helpers + */ +static void qmp_parameters_common_add(libxl__gc *gc, + libxl__json_object **param, + const char *name, + libxl__json_object *obj) +{ + libxl__json_map_node *arg = NULL; + + if (!*param) { + *param = libxl__json_object_alloc(gc, JSON_MAP); + } + + arg = libxl__zalloc(gc, sizeof(*arg)); + + arg->map_key = libxl__strdup(gc, name); + arg->obj = obj; + + flexarray_append((*param)->u.map, arg); +} + +static void qmp_parameters_add_string(libxl__gc *gc, + libxl__json_object **param, + const char *name, const char *argument) +{ + libxl__json_object *obj; + + obj = libxl__json_object_alloc(gc, JSON_STRING); + obj->u.string = libxl__strdup(gc, argument); + + qmp_parameters_common_add(gc, param, name, obj); +} + +static void qmp_parameters_add_bool(libxl__gc *gc, + libxl__json_object **param, + const char *name, bool b) +{ + libxl__json_object *obj; + + obj = libxl__json_object_alloc(gc, JSON_BOOL); + obj->u.b = b; + qmp_parameters_common_add(gc, param, name, obj); +} + +#define QMP_PARAMETERS_SPRINTF(args, name, format, ...) \ + qmp_parameters_add_string(gc, args, name, \ + libxl__sprintf(gc, format, __VA_ARGS__)) +#endif + /* * API */ -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 06/10] libxl_qmp: Use qmp_parameters_* functions for param list of a QMP command.
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_qmp.c | 71 +++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index d86f290..caf2a59 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -78,7 +78,7 @@ struct libxl__qmp_handler { }; static int qmp_send(libxl__qmp_handler *qmp, - const char *cmd, libxl_key_value_list *args, + const char *cmd, libxl__json_object *args, qmp_callback_t callback, void *opaque, qmp_request_context *context); @@ -502,7 +502,7 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp) } static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp, - const char *cmd, libxl_key_value_list *args, + const char *cmd, libxl__json_object *args, qmp_callback_t callback, void *opaque, qmp_request_context *context) { @@ -526,7 +526,7 @@ static char *qmp_send_prepare(libxl__gc *gc, libxl__qmp_handler *qmp, yajl_gen_integer(hand, ++qmp->last_id_used); if (args) { libxl__yajl_gen_asciiz(hand, "arguments"); - libxl_key_value_list_gen_json(hand, args); + libxl__json_object_to_yajl_gen(gc, hand, args); } yajl_gen_map_close(hand); @@ -560,7 +560,7 @@ out: } static int qmp_send(libxl__qmp_handler *qmp, - const char *cmd, libxl_key_value_list *args, + const char *cmd, libxl__json_object *args, qmp_callback_t callback, void *opaque, qmp_request_context *context) { @@ -588,7 +588,7 @@ out: } static int qmp_synchronous_send(libxl__qmp_handler *qmp, const char *cmd, - libxl_key_value_list *args, + libxl__json_object *args, qmp_callback_t callback, void *opaque, int ask_timeout) { @@ -623,7 +623,6 @@ static void qmp_free_handler(libxl__qmp_handler *qmp) free(qmp); } -#if 0 /* * QMP Parameters Helpers */ @@ -658,6 +657,7 @@ static void qmp_parameters_add_string(libxl__gc *gc, qmp_parameters_common_add(gc, param, name, obj); } +#if 0 static void qmp_parameters_add_bool(libxl__gc *gc, libxl__json_object **param, const char *name, bool b) @@ -668,11 +668,11 @@ static void qmp_parameters_add_bool(libxl__gc *gc, obj->u.b = b; qmp_parameters_common_add(gc, param, name, obj); } +#endif #define QMP_PARAMETERS_SPRINTF(args, name, format, ...) \ qmp_parameters_add_string(gc, args, name, \ libxl__sprintf(gc, format, __VA_ARGS__)) -#endif /* * API @@ -800,8 +800,7 @@ out: int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) { libxl__qmp_handler *qmp = NULL; - flexarray_t *parameters = NULL; - libxl_key_value_list args = NULL; + libxl__json_object *args = NULL; char *hostaddr = NULL; int rc = 0; @@ -814,22 +813,16 @@ int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) if (!hostaddr) return -1; - parameters = flexarray_make(gc, 6, 1); - flexarray_append_pair(parameters, "driver", "xen-pci-passthrough"); - flexarray_append_pair(parameters, "id", - libxl__sprintf(gc, PCI_PT_QDEV_ID, - pcidev->bus, pcidev->dev, - pcidev->func)); - flexarray_append_pair(parameters, "hostaddr", hostaddr); + qmp_parameters_add_string(gc, &args, "driver", "xen-pci-passthrough"); + QMP_PARAMETERS_SPRINTF(&args, "id", PCI_PT_QDEV_ID, + pcidev->bus, pcidev->dev, pcidev->func); + qmp_parameters_add_string(gc, &args, "hostaddr", hostaddr); if (pcidev->vdevfn) { - flexarray_append_pair(parameters, "addr", - libxl__sprintf(gc, "%x.%x", - PCI_SLOT(pcidev->vdevfn), - PCI_FUNC(pcidev->vdevfn))); + QMP_PARAMETERS_SPRINTF(&args, "addr", "%x.%x", + PCI_SLOT(pcidev->vdevfn), PCI_FUNC(pcidev->vdevfn)); } - args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); - rc = qmp_synchronous_send(qmp, "device_add", &args, + rc = qmp_synchronous_send(qmp, "device_add", args, NULL, NULL, qmp->timeout); if (rc == 0) { rc = qmp_synchronous_send(qmp, "query-pci", NULL, @@ -843,19 +836,16 @@ int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) static int qmp_device_del(libxl__gc *gc, int domid, char *id) { libxl__qmp_handler *qmp = NULL; - flexarray_t *parameters = NULL; - libxl_key_value_list args = NULL; + libxl__json_object *args = NULL; int rc = 0; qmp = libxl__qmp_initialize(gc, domid); if (!qmp) return ERROR_FAIL; - parameters = flexarray_make(gc, 2, 1); - flexarray_append_pair(parameters, "id", id); - args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); + qmp_parameters_add_string(gc, &args, "id", id); - rc = qmp_synchronous_send(qmp, "device_del", &args, + rc = qmp_synchronous_send(qmp, "device_del", args, NULL, NULL, qmp->timeout); libxl__qmp_close(qmp); @@ -875,19 +865,16 @@ int libxl__qmp_pci_del(libxl__gc *gc, int domid, libxl_device_pci *pcidev) int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename) { libxl__qmp_handler *qmp = NULL; - flexarray_t *parameters = NULL; - libxl_key_value_list args = NULL; + libxl__json_object *args = NULL; int rc = 0; qmp = libxl__qmp_initialize(gc, domid); if (!qmp) return ERROR_FAIL; - parameters = flexarray_make(gc, 2, 1); - flexarray_append_pair(parameters, "filename", (char *)filename); - args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); + qmp_parameters_add_string(gc, &args, "filename", (char *)filename); - rc = qmp_synchronous_send(qmp, "xen-save-devices-state", &args, + rc = qmp_synchronous_send(qmp, "xen-save-devices-state", args, NULL, NULL, qmp->timeout); libxl__qmp_close(qmp); @@ -897,18 +884,16 @@ int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename) static int qmp_change(libxl__gc *gc, libxl__qmp_handler *qmp, char *device, char *target, char *arg) { - flexarray_t *parameters = NULL; - libxl_key_value_list args = NULL; + libxl__json_object *args = NULL; int rc = 0; - parameters = flexarray_make(gc, 6, 1); - flexarray_append_pair(parameters, "device", device); - flexarray_append_pair(parameters, "target", target); - if (arg) - flexarray_append_pair(parameters, "arg", arg); - args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); + qmp_parameters_add_string(gc, &args, "device", device); + qmp_parameters_add_string(gc, &args, "target", target); + if (arg) { + qmp_parameters_add_string(gc, &args, "arg", arg); + } - rc = qmp_synchronous_send(qmp, "change", &args, + rc = qmp_synchronous_send(qmp, "change", args, NULL, NULL, qmp->timeout); return rc; -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 07/10] libxl_qmp: Simplify run of single QMP commands.
This new function connects to QEMU, sends the command and disconnects. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_qmp.c | 70 ++++++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 48 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index caf2a59..7bf56a7 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -797,6 +797,23 @@ out: return rc; } +static int qmp_run_command(libxl__gc *gc, int domid, + const char *cmd, libxl__json_object *args, + qmp_callback_t callback, void *opaque) +{ + libxl__qmp_handler *qmp = NULL; + int rc = 0; + + qmp = libxl__qmp_initialize(gc, domid); + if (!qmp) + return ERROR_FAIL; + + rc = qmp_synchronous_send(qmp, cmd, args, callback, opaque, qmp->timeout); + + libxl__qmp_close(qmp); + return rc; +} + int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) { libxl__qmp_handler *qmp = NULL; @@ -835,21 +852,10 @@ int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) static int qmp_device_del(libxl__gc *gc, int domid, char *id) { - libxl__qmp_handler *qmp = NULL; libxl__json_object *args = NULL; - int rc = 0; - - qmp = libxl__qmp_initialize(gc, domid); - if (!qmp) - return ERROR_FAIL; qmp_parameters_add_string(gc, &args, "id", id); - - rc = qmp_synchronous_send(qmp, "device_del", args, - NULL, NULL, qmp->timeout); - - libxl__qmp_close(qmp); - return rc; + return qmp_run_command(gc, domid, "device_del", args, NULL, NULL); } int libxl__qmp_pci_del(libxl__gc *gc, int domid, libxl_device_pci *pcidev) @@ -864,21 +870,11 @@ int libxl__qmp_pci_del(libxl__gc *gc, int domid, libxl_device_pci *pcidev) int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename) { - libxl__qmp_handler *qmp = NULL; libxl__json_object *args = NULL; - int rc = 0; - - qmp = libxl__qmp_initialize(gc, domid); - if (!qmp) - return ERROR_FAIL; qmp_parameters_add_string(gc, &args, "filename", (char *)filename); - - rc = qmp_synchronous_send(qmp, "xen-save-devices-state", args, - NULL, NULL, qmp->timeout); - - libxl__qmp_close(qmp); - return rc; + return qmp_run_command(gc, domid, "xen-save-devices-state", args, + NULL, NULL); } static int qmp_change(libxl__gc *gc, libxl__qmp_handler *qmp, @@ -901,34 +897,12 @@ static int qmp_change(libxl__gc *gc, libxl__qmp_handler *qmp, int libxl__qmp_stop(libxl__gc *gc, int domid) { - libxl__qmp_handler *qmp = NULL; - int rc = 0; - - qmp = libxl__qmp_initialize(gc, domid); - if (!qmp) - return ERROR_FAIL; - - rc = qmp_synchronous_send(qmp, "stop", NULL, - NULL, NULL, qmp->timeout); - - libxl__qmp_close(qmp); - return rc; + return qmp_run_command(gc, domid, "stop", NULL, NULL, NULL); } int libxl__qmp_resume(libxl__gc *gc, int domid) { - libxl__qmp_handler *qmp = NULL; - int rc = 0; - - qmp = libxl__qmp_initialize(gc, domid); - if (!qmp) - return ERROR_FAIL; - - rc = qmp_synchronous_send(qmp, "cont", NULL, - NULL, NULL, qmp->timeout); - - libxl__qmp_close(qmp); - return rc; + return qmp_run_command(gc, domid, "cont", NULL, NULL, NULL); } int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid, -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 08/10] libxl_qmp: Introduce libxl__qmp_set_global_dirty_log.
This function will enable or disable the global dirty log on QEMU, used during a migration. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_internal.h | 2 ++ tools/libxl/libxl_qmp.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 04ca5a5..afa36a7 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1404,6 +1404,8 @@ _hidden int libxl__qmp_stop(libxl__gc *gc, int domid); _hidden int libxl__qmp_resume(libxl__gc *gc, int domid); /* Save current QEMU state into fd. */ _hidden int libxl__qmp_save(libxl__gc *gc, int domid, const char *filename); +/* Set dirty bitmap logging status */ +_hidden int libxl__qmp_set_global_dirty_log(libxl__gc *gc, int domid, bool enable); /* close and free the QMP handler */ _hidden void libxl__qmp_close(libxl__qmp_handler *qmp); /* remove the socket file, if the file has already been removed, diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index 7bf56a7..5fa0c65 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -657,7 +657,6 @@ static void qmp_parameters_add_string(libxl__gc *gc, qmp_parameters_common_add(gc, param, name, obj); } -#if 0 static void qmp_parameters_add_bool(libxl__gc *gc, libxl__json_object **param, const char *name, bool b) @@ -668,7 +667,6 @@ static void qmp_parameters_add_bool(libxl__gc *gc, obj->u.b = b; qmp_parameters_common_add(gc, param, name, obj); } -#endif #define QMP_PARAMETERS_SPRINTF(args, name, format, ...) \ qmp_parameters_add_string(gc, args, name, \ @@ -905,6 +903,16 @@ int libxl__qmp_resume(libxl__gc *gc, int domid) return qmp_run_command(gc, domid, "cont", NULL, NULL, NULL); } +int libxl__qmp_set_global_dirty_log(libxl__gc *gc, int domid, bool enable) +{ + libxl__json_object *args = NULL; + + qmp_parameters_add_bool(gc, &args, "enable", enable); + + return qmp_run_command(gc, domid, "xen-set-global-dirty-log", args, + NULL, NULL); +} + int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid, const libxl_domain_config *guest_config) { -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 09/10] libxl_dom: Call the right switch logdirty for the right DM.
This patch dispatch the switch logdirty call depending on which device model version is running. The call to qemu-xen right now is synchronous, not like the one to qemu-xen-traditional. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_dom.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index e1de832..95da18e 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -685,10 +685,10 @@ static void logdirty_init(libxl__logdirty_switch *lds) libxl__ev_time_init(&lds->timeout); } -void libxl__domain_suspend_common_switch_qemu_logdirty - (int domid, unsigned enable, void *user) +static void domain_suspend_switch_qemu_xen_traditional_logdirty + (int domid, unsigned enable, + libxl__save_helper_state *shs) { - libxl__save_helper_state *shs = user; libxl__egc *egc = shs->egc; libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs); libxl__logdirty_switch *lds = &dss->logdirty; @@ -756,6 +756,45 @@ void libxl__domain_suspend_common_switch_qemu_logdirty switch_logdirty_done(egc,dss,-1); } +static void domain_suspend_switch_qemu_xen_logdirty + (int domid, unsigned enable, + libxl__save_helper_state *shs) +{ + libxl__egc *egc = shs->egc; + libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs); + STATE_AO_GC(dss->ao); + int rc; + + rc = libxl__qmp_set_global_dirty_log(gc, domid, enable); + if (!rc) { + libxl__xc_domain_saverestore_async_callback_done(egc, shs, 0); + } else { + LOG(ERROR,"logdirty switch failed (rc=%d), aborting suspend",rc); + libxl__xc_domain_saverestore_async_callback_done(egc, shs, -1); + } +} + +void libxl__domain_suspend_common_switch_qemu_logdirty + (int domid, unsigned enable, void *user) +{ + libxl__save_helper_state *shs = user; + libxl__egc *egc = shs->egc; + libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs); + STATE_AO_GC(dss->ao); + + switch (libxl__device_model_version_running(gc, domid)) { + case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: + domain_suspend_switch_qemu_xen_traditional_logdirty(domid, enable, shs); + break; + case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: + domain_suspend_switch_qemu_xen_logdirty(domid, enable, shs); + break; + default: + LOG(ERROR,"logdirty switch failed" + ", no valid device model version found, aborting suspend"); + libxl__xc_domain_saverestore_async_callback_done(egc, shs, -1); + } +} static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev, const struct timeval *requested_abs) { -- Anthony PERARD
Anthony PERARD
2012-Oct-05 14:30 UTC
[PATCH V4 10/10] libxl: Allow migration with qemu-xen.
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index af3682f..0cf4768 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -767,23 +767,6 @@ int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags, goto out_err; } - if (type == LIBXL_DOMAIN_TYPE_HVM && flags & LIBXL_SUSPEND_LIVE) { - switch (libxl__device_model_version_running(gc, domid)) { - case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: - LOG(ERROR, - "cannot live migrate HVM domains with qemu-xen device-model"); - rc = ERROR_FAIL; - goto out_err; - case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: - /* No problem */ - break; - case -1: - rc = ERROR_FAIL; - goto out_err; - default: abort(); - } - } - libxl__domain_suspend_state *dss; GCNEW(dss); -- Anthony PERARD
On Fri, 2012-10-05 at 15:30 +0100, Anthony PERARD wrote:> This patch series enables libxl to set dirty log on QEMU upstream during > migration through a new QMP command.Applied. I made one change, to Introduce libxl__json_object_to_yajl_gen, to fix: cc1: warnings being treated as errors libxl_json.c: In function ‘libxl__json_object_to_yajl_gen’: libxl_json.c:373: error: declaration of ‘index’ shadows a global declaration /usr/include/string.h:487: error: shadowed declaration is here I did s/index/idx/. Hope that's ok Ian.> > The success of the call depends on the presence of the specific QMP command > xen-set-global-dirty-log in QEMU. Patches for this command have been sent. > > There is several patches that cleanup a bit the libxl_json/qmp codes. > > Change since v3: > - Update the comment on the first patch to say that NOGC can be used. > > > Anthony PERARD (10): > libxl_json: Export json_object related function. > libxl_json: Remove JSON_ERROR from enum. > libxl_json: Replace JSON_TRUE/FALSE by JSON_BOOL. > libxl_json: Introduce libxl__json_object_to_yajl_gen. > libxl_qmp: Introduces helpers to create an argument list. > libxl_qmp: Use qmp_parameters_* functions for param list of a QMP > command. > libxl_qmp: Simplify run of single QMP commands. > libxl_qmp: Introduce libxl__qmp_set_global_dirty_log. > libxl_dom: Call the right switch logdirty for the right DM. > libxl: Allow migration with qemu-xen. > > tools/libxl/libxl.c | 17 ---- > tools/libxl/libxl_dom.c | 45 ++++++++++- > tools/libxl/libxl_internal.h | 35 ++++++-- > tools/libxl/libxl_json.c | 95 ++++++++++++++++++---- > tools/libxl/libxl_qmp.c | 189 ++++++++++++++++++++++++------------------- > 5 files changed, 254 insertions(+), 127 deletions(-) >_______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel