Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 00/13] libxl: QMP client improvement + pci passthrougth insert through QMP
This patch series improves the QMP client in lib XenLight to be able to insert a PCI passthrough device with the upstream QEMU. This require to apply a patch series for QEMU (named Xen PCI Passthrough). The first three patches are fix. The next patch creates a key in xenstore with the version of the running device model, here: /libxl/$domid/dm-version Changed since v2: > dm-version xenstore key patch: - small coding style improvement - libxl__device_model_version_running() now return an error on unexpected value in /libxl/$domid/dm-version > qmp_request_context patch: - rename handle to context - the context is now only used between qmp_sync.._send and qmp_send - return code of a callback is now return by qmp_sync.._send() > Handle number abrove LONG_MAX patch: - the new callback now also handle double. > two new patches to do a pci-detatch. Change v1-v2: - 3 new patches, with small fix. - add a structure in qmp, qmp_request_handle, to carry the return code of a callback. - the xenstore key for the dm-version is now in /libxl/$domid, instead of /local/domain/$domid - new patch to parse number bigger than LONG_MAX for json. - an user specified vdevfn for a pci passthrough devices is now handle. - in the last patch, the code to handle a pci-add through xenstore have is own function. that help a bit to keep the code under 80col. Anthony PERARD (13): libxl_qmp: Fix return check of fcntl libxl_json: Check the parser status before to call parse_complete libxl_qmp: Better error message after a parse error. libxl: Introduce dm-version xenstore key. libxl_qmp: Introduce an opaque argument to the callbacks. libxl_qmp: Introduce list of arguments to qmp_send libxl_qmp: Always insert a command id in the callback_list. libxl_qmp: Introduce qmp_request_context. libxl_json: Handle number abrove LONG_MAX. libxl_qmp: Introduce libxl__qmp_pci_add. libxl: Use QMP to insert a passthrough device when using upstream QEMU libxl_qmp: Introduce libxl__qmp_pci_del libxl: Remove a passthrough device through QMP. tools/libxl/libxl.c | 2 + tools/libxl/libxl_create.c | 29 +++++- tools/libxl/libxl_internal.c | 23 ++++ tools/libxl/libxl_internal.h | 19 +++- tools/libxl/libxl_json.c | 111 +++++++++++++------- tools/libxl/libxl_pci.c | 143 +++++++++++++++++-------- tools/libxl/libxl_qmp.c | 236 +++++++++++++++++++++++++++++++++++------ tools/libxl/libxl_xshelp.c | 9 ++ 8 files changed, 450 insertions(+), 122 deletions(-) -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 01/13] libxl_qmp: Fix return check of fcntl
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_qmp.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index 618f20f..ef36348 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -296,7 +296,7 @@ static int qmp_open(libxl__qmp_handler *qmp, const char *qmp_socket_path, if (qmp->qmp_fd < 0) { return -1; } - if ((flags = fcntl(qmp->qmp_fd, F_GETFL)) == 1) { + if ((flags = fcntl(qmp->qmp_fd, F_GETFL)) == -1) { flags = 0; } if (fcntl(qmp->qmp_fd, F_SETFL, flags | O_NONBLOCK) == -1) { -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 02/13] libxl_json: Check the parser status before to call parse_complete
Also, use goto to handle an error. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_json.c | 37 ++++++++++++++++++++----------------- 1 files changed, 20 insertions(+), 17 deletions(-) diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c index 11f65fc..389b697 100644 --- a/tools/libxl/libxl_json.c +++ b/tools/libxl/libxl_json.c @@ -730,6 +730,8 @@ libxl__json_object *libxl__json_parse(libxl__gc *gc, const char *s) { yajl_status status; libxl__yajl_ctx yajl_ctx; + libxl__json_object *o = NULL; + unsigned char *str = NULL; memset(&yajl_ctx, 0, sizeof (yajl_ctx)); yajl_ctx.gc = gc; @@ -744,30 +746,31 @@ libxl__json_object *libxl__json_parse(libxl__gc *gc, const char *s) yajl_ctx.hand = yajl_alloc(&callbacks, &cfg, NULL, &yajl_ctx); } status = yajl_parse(yajl_ctx.hand, (const unsigned char *)s, strlen(s)); + if (status != yajl_status_ok) + goto out; + status = yajl_parse_complete(yajl_ctx.hand); + if (status != yajl_status_ok) + goto out; - if (status == yajl_status_ok) { - libxl__json_object *o = yajl_ctx.head; + o = yajl_ctx.head; - DEBUG_GEN_REPORT(&yajl_ctx); + DEBUG_GEN_REPORT(&yajl_ctx); - yajl_ctx.head = NULL; + yajl_ctx.head = NULL; - yajl_ctx_free(&yajl_ctx); - return o; - } else { - unsigned char *str = yajl_get_error(yajl_ctx.hand, 1, - (const unsigned char *)s, - strlen(s)); + yajl_ctx_free(&yajl_ctx); + return o; - LIBXL__LOG(libxl__gc_owner(gc), LIBXL__LOG_ERROR, - "yajl error: %s", str); - yajl_free_error(yajl_ctx.hand, str); +out: + str = yajl_get_error(yajl_ctx.hand, 1, (const unsigned char*)s, strlen(s)); - libxl__json_object_free(gc, yajl_ctx.head); - yajl_ctx_free(&yajl_ctx); - return NULL; - } + LIBXL__LOG(libxl__gc_owner(gc), LIBXL__LOG_ERROR, "yajl error: %s", str); + yajl_free_error(yajl_ctx.hand, str); + + libxl__json_object_free(gc, yajl_ctx.head); + yajl_ctx_free(&yajl_ctx); + return NULL; } static const char *yajl_gen_status_to_string(yajl_gen_status s) -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 03/13] libxl_qmp: Better error message after a parse error.
By setting the next string to parse after having printed any error messages. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_qmp.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index ef36348..f61a87a 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -403,7 +403,6 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp) *end = ''\0''; o = libxl__json_parse(gc, s); - s = end + 2; if (o) { qmp_handle_response(qmp, o); @@ -413,6 +412,8 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp) "Parse error of : %s\n", s); return -1; } + + s = end + 2; } else { break; } -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 04/13] libxl: Introduce dm-version xenstore key.
The all key is /libxl/$domid/dm-version. The /libxl/$domid dir is created with the domain and should be only accessible by the toolstack domain. The function libxl__xs_libxl_path() give this path. This come with libxl__device_model_version_running() helper function. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl.c | 2 ++ tools/libxl/libxl_create.c | 29 ++++++++++++++++++++++++++++- tools/libxl/libxl_internal.c | 23 +++++++++++++++++++++++ tools/libxl/libxl_internal.h | 7 +++++++ tools/libxl/libxl_xshelp.c | 9 +++++++++ 5 files changed, 69 insertions(+), 1 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 064fbc4..22a7795 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -777,6 +777,8 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, int force) if (!xs_rm(ctx->xsh, XBT_NULL, dom_path)) LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xs_rm failed for %s", dom_path); + xs_rm(ctx->xsh, XBT_NULL, libxl__xs_libxl_path(&gc, domid)); + libxl__userdata_destroyall(&gc, domid); rc = xc_domain_destroy(ctx->xch, domid); diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 68d0fc3..9506aa4 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -316,12 +316,14 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info, char *rw_paths[] = { "control/shutdown", "device", "device/suspend/event-channel" , "data"}; char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers", "control", "attr", "messages" }; - char *dom_path, *vm_path; + char *dom_path, *vm_path, *libxl_path; struct xs_permissions roperm[2]; struct xs_permissions rwperm[1]; + struct xs_permissions noperm[1]; xs_transaction_t t = 0; xen_domain_handle_t handle; + assert(!libxl_domid_valid_guest(*domid)); uuid_string = libxl__uuid2string(gc, info->uuid); @@ -368,6 +370,14 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info, goto out; } + libxl_path = libxl__xs_libxl_path(gc, *domid); + if (!libxl_path) { + rc = ERROR_FAIL; + goto out; + } + noperm[0].id = 0; + noperm[0].perms = XS_PERM_NONE; + roperm[0].id = 0; roperm[0].perms = XS_PERM_NONE; roperm[1].id = *domid; @@ -386,6 +396,10 @@ retry_transaction: xs_mkdir(ctx->xsh, t, vm_path); xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm)); + xs_rm(ctx->xsh, t, libxl_path); + xs_mkdir(ctx->xsh, t, libxl_path); + xs_set_permissions(ctx->xsh, t, libxl_path, noperm, ARRAY_SIZE(noperm)); + xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path)); rc = libxl__domain_rename(gc, *domid, 0, info->name, t); if (rc) @@ -429,6 +443,17 @@ retry_transaction: return rc; } +static int store_libxl_entry(libxl__gc *gc, uint32_t domid, + libxl_device_model_info *dm_info) +{ + char *path = NULL; + + path = libxl__xs_libxl_path(gc, domid); + path = libxl__sprintf(gc, "%s/dm-version", path); + return libxl__xs_write(gc, XBT_NULL, path, libxl__strdup(gc, + libxl_device_model_version_to_string(dm_info->device_model_version))); +} + static int do_domain_create(libxl__gc *gc, libxl_domain_config *d_config, libxl_console_ready cb, void *priv, uint32_t *domid_out, int restore_fd) @@ -485,6 +510,8 @@ static int do_domain_create(libxl__gc *gc, libxl_domain_config *d_config, goto error_out; } + store_libxl_entry(gc, domid, dm_info); + for (i = 0; i < d_config->num_disks; i++) { ret = libxl_device_disk_add(ctx, domid, &d_config->disks[i]); if (ret) { diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c index 3993d8e..34edaf3 100644 --- a/tools/libxl/libxl_internal.c +++ b/tools/libxl/libxl_internal.c @@ -319,6 +319,29 @@ int libxl__fd_set_cloexec(int fd) return fcntl(fd, F_SETFD, flags | FD_CLOEXEC); } +libxl_device_model_version libxl__device_model_version_running(libxl__gc *gc, + uint32_t domid) +{ + char *path = NULL; + char *dm_version = NULL; + libxl_device_model_version value; + + path = libxl__xs_libxl_path(gc, domid); + path = libxl__sprintf(gc, "%s/dm-version", path); + dm_version = libxl__xs_read(gc, XBT_NULL, path); + if (!dm_version) { + return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL; + } + + if (libxl_device_model_version_from_string(dm_version, &value) < 0) { + libxl_ctx *ctx = libxl__gc_owner(gc); + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, + "fatal: %s contain a wrong value (%s)", path, dm_version); + return -1; + } + return value; +} + /* * Local variables: * mode: C diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 2e26ac6..942d45b 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -195,6 +195,8 @@ _hidden char **libxl__xs_directory(libxl__gc *gc, xs_transaction_t t, char *path, unsigned int *nb); /* On error: returns NULL, sets errno (no logging) */ +_hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid); + /* from xl_dom */ _hidden libxl_domain_type libxl__domain_type(libxl__gc *gc, uint32_t domid); _hidden int libxl__domain_shutdown_reason(libxl__gc *gc, uint32_t domid); @@ -554,6 +556,11 @@ _hidden void libxl__json_object_free(libxl__gc *gc, libxl__json_object *obj); _hidden libxl__json_object *libxl__json_parse(libxl__gc *gc, const char *s); + /* Based on /local/domain/$domid/dm-version xenstore key + * default is qemu xen traditional */ +_hidden libxl_device_model_version +libxl__device_model_version_running(libxl__gc *gc, uint32_t domid); + #endif /* diff --git a/tools/libxl/libxl_xshelp.c b/tools/libxl/libxl_xshelp.c index e41f962..4b09be3 100644 --- a/tools/libxl/libxl_xshelp.c +++ b/tools/libxl/libxl_xshelp.c @@ -122,6 +122,15 @@ char **libxl__xs_directory(libxl__gc *gc, xs_transaction_t t, char *path, unsign return ret; } +char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid) +{ + libxl_ctx *ctx = libxl__gc_owner(gc); + char *s = libxl__sprintf(gc, "/libxl/%i", domid); + if (!s) + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot allocate create paths"); + return s; +} + /* * Local variables: * mode: C -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 05/13] libxl_qmp: Introduce an opaque argument to the callbacks.
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_qmp.c | 30 +++++++++++++++++++----------- 1 files changed, 19 insertions(+), 11 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index f61a87a..ddc0a4d 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -43,11 +43,13 @@ #define QMP_RECEIVE_BUFFER_SIZE 4096 typedef int (*qmp_callback_t)(libxl__qmp_handler *qmp, - const libxl__json_object *tree); + const libxl__json_object *tree, + void *opaque); typedef struct callback_id_pair { int id; qmp_callback_t callback; + void *opaque; SIMPLEQ_ENTRY(callback_id_pair) next; } callback_id_pair; @@ -70,7 +72,8 @@ struct libxl__qmp_handler { }; static int qmp_send(libxl__qmp_handler *qmp, - const char *cmd, qmp_callback_t callback); + const char *cmd, + qmp_callback_t callback, void *opaque); static const int QMP_SOCKET_CONNECT_TIMEOUT = 5; @@ -100,7 +103,8 @@ static int store_serial_port_info(libxl__qmp_handler *qmp, } static int register_serials_chardev_callback(libxl__qmp_handler *qmp, - const libxl__json_object *o) + const libxl__json_object *o, + void *unused) { const libxl__json_object *obj = NULL; const libxl__json_object *label = NULL; @@ -144,7 +148,7 @@ static int register_serials_chardev_callback(libxl__qmp_handler *qmp, } static int qmp_capabilities_callback(libxl__qmp_handler *qmp, - const libxl__json_object *o) + const libxl__json_object *o, void *unused) { qmp->connected = true; @@ -157,7 +161,7 @@ static int qmp_capabilities_callback(libxl__qmp_handler *qmp, static int enable_qmp_capabilities(libxl__qmp_handler *qmp) { - return qmp_send(qmp, "qmp_capabilities", qmp_capabilities_callback); + return qmp_send(qmp, "qmp_capabilities", qmp_capabilities_callback, NULL); } /* @@ -208,7 +212,7 @@ static void qmp_handle_error_response(libxl__qmp_handler *qmp, resp = libxl__json_map_get("desc", resp, JSON_STRING); if (pp) { - pp->callback(qmp, NULL); + pp->callback(qmp, NULL, pp->opaque); if (pp->id == qmp->wait_for_id) { /* tell that the id have been processed */ qmp->wait_for_id = 0; @@ -241,7 +245,8 @@ static int qmp_handle_response(libxl__qmp_handler *qmp, if (pp) { pp->callback(qmp, - libxl__json_map_get("return", resp, JSON_ANY)); + libxl__json_map_get("return", resp, JSON_ANY), + pp->opaque); if (pp->id == qmp->wait_for_id) { /* tell that the id have been processed */ qmp->wait_for_id = 0; @@ -424,7 +429,8 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp) } static int qmp_send(libxl__qmp_handler *qmp, - const char *cmd, qmp_callback_t callback) + const char *cmd, + qmp_callback_t callback, void *opaque) { yajl_gen_config conf = { 0, NULL }; const unsigned char *buf; @@ -462,6 +468,7 @@ static int qmp_send(libxl__qmp_handler *qmp, } elm->id = qmp->last_id_used; elm->callback = callback; + elm->opaque = opaque; SIMPLEQ_INSERT_TAIL(&qmp->callback_list, elm, next); } @@ -484,13 +491,14 @@ error: } static int qmp_synchronous_send(libxl__qmp_handler *qmp, const char *cmd, - qmp_callback_t callback, int ask_timeout) + qmp_callback_t callback, void *opaque, + int ask_timeout) { int id = 0; int ret = 0; libxl__gc gc = LIBXL_INIT_GC(qmp->ctx); - id = qmp_send(qmp, cmd, callback); + id = qmp_send(qmp, cmd, callback, opaque); if (id <= 0) { return -1; } @@ -580,7 +588,7 @@ int libxl__qmp_query_serial(libxl__qmp_handler *qmp) { return qmp_synchronous_send(qmp, "query-chardev", register_serials_chardev_callback, - qmp->timeout); + NULL, qmp->timeout); } int libxl__qmp_initializations(libxl_ctx *ctx, uint32_t domid) -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 06/13] libxl_qmp: Introduce list of arguments to qmp_send
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_qmp.c | 16 +++++++++++----- 1 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index ddc0a4d..43c7d04 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -72,7 +72,7 @@ struct libxl__qmp_handler { }; static int qmp_send(libxl__qmp_handler *qmp, - const char *cmd, + const char *cmd, libxl_key_value_list *args, qmp_callback_t callback, void *opaque); static const int QMP_SOCKET_CONNECT_TIMEOUT = 5; @@ -161,7 +161,8 @@ static int qmp_capabilities_callback(libxl__qmp_handler *qmp, static int enable_qmp_capabilities(libxl__qmp_handler *qmp) { - return qmp_send(qmp, "qmp_capabilities", qmp_capabilities_callback, NULL); + return qmp_send(qmp, "qmp_capabilities", NULL, + qmp_capabilities_callback, NULL); } /* @@ -429,7 +430,7 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp) } static int qmp_send(libxl__qmp_handler *qmp, - const char *cmd, + const char *cmd, libxl_key_value_list *args, qmp_callback_t callback, void *opaque) { yajl_gen_config conf = { 0, NULL }; @@ -448,6 +449,10 @@ static int qmp_send(libxl__qmp_handler *qmp, libxl__yajl_gen_asciiz(hand, cmd); libxl__yajl_gen_asciiz(hand, "id"); yajl_gen_integer(hand, ++qmp->last_id_used); + if (args) { + libxl__yajl_gen_asciiz(hand, "arguments"); + libxl_key_value_list_gen_json(hand, args); + } yajl_gen_map_close(hand); s = yajl_gen_get_buf(hand, &buf, &len); @@ -491,6 +496,7 @@ error: } static int qmp_synchronous_send(libxl__qmp_handler *qmp, const char *cmd, + libxl_key_value_list *args, qmp_callback_t callback, void *opaque, int ask_timeout) { @@ -498,7 +504,7 @@ static int qmp_synchronous_send(libxl__qmp_handler *qmp, const char *cmd, int ret = 0; libxl__gc gc = LIBXL_INIT_GC(qmp->ctx); - id = qmp_send(qmp, cmd, callback, opaque); + id = qmp_send(qmp, cmd, args, callback, opaque); if (id <= 0) { return -1; } @@ -586,7 +592,7 @@ void libxl__qmp_cleanup(libxl__gc *gc, uint32_t domid) int libxl__qmp_query_serial(libxl__qmp_handler *qmp) { - return qmp_synchronous_send(qmp, "query-chardev", + return qmp_synchronous_send(qmp, "query-chardev", NULL, register_serials_chardev_callback, NULL, qmp->timeout); } -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 07/13] libxl_qmp: Always insert a command id in the callback_list.
Because the function qmp_synchronous_send rely on the presence of the id in the callback_list. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Campbell <ian.campbell@citrix.com> --- tools/libxl/libxl_qmp.c | 34 ++++++++++++++++++---------------- 1 files changed, 18 insertions(+), 16 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index 43c7d04..47129c3 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -213,7 +213,9 @@ static void qmp_handle_error_response(libxl__qmp_handler *qmp, resp = libxl__json_map_get("desc", resp, JSON_STRING); if (pp) { - pp->callback(qmp, NULL, pp->opaque); + if (pp->callback) { + pp->callback(qmp, NULL, pp->opaque); + } if (pp->id == qmp->wait_for_id) { /* tell that the id have been processed */ qmp->wait_for_id = 0; @@ -245,9 +247,11 @@ static int qmp_handle_response(libxl__qmp_handler *qmp, callback_id_pair *pp = qmp_get_callback_from_id(qmp, resp); if (pp) { - pp->callback(qmp, - libxl__json_map_get("return", resp, JSON_ANY), - pp->opaque); + if (pp->callback) { + pp->callback(qmp, + libxl__json_map_get("return", resp, JSON_ANY), + pp->opaque); + } if (pp->id == qmp->wait_for_id) { /* tell that the id have been processed */ qmp->wait_for_id = 0; @@ -438,6 +442,7 @@ static int qmp_send(libxl__qmp_handler *qmp, unsigned int len = 0; yajl_gen_status s; yajl_gen hand; + callback_id_pair *elm = NULL; hand = yajl_gen_alloc(&conf, NULL); if (!hand) { @@ -463,19 +468,16 @@ static int qmp_send(libxl__qmp_handler *qmp, return -1; } - if (callback) { - callback_id_pair *elm = malloc(sizeof (callback_id_pair)); - if (elm == NULL) { - LIBXL__LOG_ERRNO(qmp->ctx, LIBXL__LOG_ERROR, - "Failed to allocate a QMP callback"); - yajl_gen_free(hand); - return -1; - } - elm->id = qmp->last_id_used; - elm->callback = callback; - elm->opaque = opaque; - SIMPLEQ_INSERT_TAIL(&qmp->callback_list, elm, next); + elm = malloc(sizeof (callback_id_pair)); + if (elm == NULL) { + LIBXL__LOG_ERRNO(qmp->ctx, LIBXL__LOG_ERROR, + "Failed to allocate a QMP callback"); + goto error; } + elm->id = qmp->last_id_used; + elm->callback = callback; + elm->opaque = opaque; + SIMPLEQ_INSERT_TAIL(&qmp->callback_list, elm, next); LIBXL__LOG(qmp->ctx, LIBXL__LOG_DEBUG, "next qmp command: ''%s''", buf); -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 08/13] libxl_qmp: Introduce qmp_request_context.
This structure helps to track the return code of a callback. It''s only used between qmp_synchronous_send and qmp_send. Now, qmp_synchronous_send will return the rc of the callback if there is no error. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_qmp.c | 49 ++++++++++++++++++++++++++++++++-------------- 1 files changed, 34 insertions(+), 15 deletions(-) diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index 47129c3..6d80538 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -46,10 +46,15 @@ typedef int (*qmp_callback_t)(libxl__qmp_handler *qmp, const libxl__json_object *tree, void *opaque); +typedef struct qmp_request_context { + int rc; +} qmp_request_context; + typedef struct callback_id_pair { int id; qmp_callback_t callback; void *opaque; + qmp_request_context *context; SIMPLEQ_ENTRY(callback_id_pair) next; } callback_id_pair; @@ -73,7 +78,8 @@ struct libxl__qmp_handler { static int qmp_send(libxl__qmp_handler *qmp, const char *cmd, libxl_key_value_list *args, - qmp_callback_t callback, void *opaque); + qmp_callback_t callback, void *opaque, + qmp_request_context *context); static const int QMP_SOCKET_CONNECT_TIMEOUT = 5; @@ -162,7 +168,7 @@ static int qmp_capabilities_callback(libxl__qmp_handler *qmp, static int enable_qmp_capabilities(libxl__qmp_handler *qmp) { return qmp_send(qmp, "qmp_capabilities", NULL, - qmp_capabilities_callback, NULL); + qmp_capabilities_callback, NULL, NULL); } /* @@ -214,7 +220,10 @@ static void qmp_handle_error_response(libxl__qmp_handler *qmp, if (pp) { if (pp->callback) { - pp->callback(qmp, NULL, pp->opaque); + int rc = pp->callback(qmp, NULL, pp->opaque); + if (pp->context) { + pp->context->rc = rc; + } } if (pp->id == qmp->wait_for_id) { /* tell that the id have been processed */ @@ -241,16 +250,18 @@ static int qmp_handle_response(libxl__qmp_handler *qmp, switch (type) { case LIBXL__QMP_MESSAGE_TYPE_QMP: /* On the greeting message from the server, enable QMP capabilities */ - enable_qmp_capabilities(qmp); - break; + return enable_qmp_capabilities(qmp); case LIBXL__QMP_MESSAGE_TYPE_RETURN: { callback_id_pair *pp = qmp_get_callback_from_id(qmp, resp); if (pp) { if (pp->callback) { - pp->callback(qmp, + int rc = pp->callback(qmp, libxl__json_map_get("return", resp, JSON_ANY), pp->opaque); + if (pp->context) { + pp->context->rc = rc; + } } if (pp->id == qmp->wait_for_id) { /* tell that the id have been processed */ @@ -259,13 +270,13 @@ static int qmp_handle_response(libxl__qmp_handler *qmp, SIMPLEQ_REMOVE(&qmp->callback_list, pp, callback_id_pair, next); free(pp); } - break; + return 0; } case LIBXL__QMP_MESSAGE_TYPE_ERROR: qmp_handle_error_response(qmp, resp); - break; + return -1; case LIBXL__QMP_MESSAGE_TYPE_EVENT: - break; + return 0; case LIBXL__QMP_MESSAGE_TYPE_INVALID: return -1; } @@ -358,6 +369,7 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp) char *incomplete = NULL; size_t incomplete_size = 0; + int rc = 0; do { fd_set rfds; @@ -415,7 +427,7 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp) o = libxl__json_parse(gc, s); if (o) { - qmp_handle_response(qmp, o); + rc = qmp_handle_response(qmp, o); libxl__json_object_free(gc, o); } else { LIBXL__LOG(qmp->ctx, LIBXL__LOG_ERROR, @@ -430,12 +442,13 @@ static int qmp_next(libxl__gc *gc, libxl__qmp_handler *qmp) } while (s < s_end); } while (s < s_end); - return 1; + return rc; } static int qmp_send(libxl__qmp_handler *qmp, const char *cmd, libxl_key_value_list *args, - qmp_callback_t callback, void *opaque) + qmp_callback_t callback, void *opaque, + qmp_request_context *context) { yajl_gen_config conf = { 0, NULL }; const unsigned char *buf; @@ -477,6 +490,7 @@ static int qmp_send(libxl__qmp_handler *qmp, elm->id = qmp->last_id_used; elm->callback = callback; elm->opaque = opaque; + elm->context = context; SIMPLEQ_INSERT_TAIL(&qmp->callback_list, elm, next); LIBXL__LOG(qmp->ctx, LIBXL__LOG_DEBUG, "next qmp command: ''%s''", buf); @@ -505,8 +519,9 @@ static int qmp_synchronous_send(libxl__qmp_handler *qmp, const char *cmd, int id = 0; int ret = 0; libxl__gc gc = LIBXL_INIT_GC(qmp->ctx); + qmp_request_context context = { .rc = 0 }; - id = qmp_send(qmp, cmd, args, callback, opaque); + id = qmp_send(qmp, cmd, args, callback, opaque, &context); if (id <= 0) { return -1; } @@ -514,13 +529,17 @@ static int qmp_synchronous_send(libxl__qmp_handler *qmp, const char *cmd, while (qmp->wait_for_id == id) { if ((ret = qmp_next(&gc, qmp)) < 0) { - return ret; + break; } } + if (qmp->wait_for_id != id && ret == 0) { + ret = context.rc; + } + libxl__free_all(&gc); - return 0; + return ret; } static void qmp_free_handler(libxl__qmp_handler *qmp) -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 09/13] libxl_json: Handle number abrove LONG_MAX.
The integers are now "long long" in the json_object. If a number (decimal or integer) is too big (or too low), it is stored as it in a string. So for that, we introduce a new type JSON_NUMBER. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_internal.h | 6 ++- tools/libxl/libxl_json.c | 74 ++++++++++++++++++++++++++++++------------ 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 942d45b..09e0c51 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -468,6 +468,8 @@ typedef enum { JSON_FALSE, JSON_INTEGER, JSON_DOUBLE, + /* number is store in string, it''s too big to be a long long or a double */ + JSON_NUMBER, JSON_STRING, JSON_MAP, JSON_ARRAY, @@ -477,7 +479,7 @@ typedef enum { typedef struct libxl__json_object { libxl__json_node_type type; union { - long i; + long long i; double d; char *string; /* List of libxl__json_object */ @@ -536,7 +538,7 @@ flexarray_t *libxl__json_object_get_array(const libxl__json_object *o) else return NULL; } -static inline long libxl__json_object_get_integer(const libxl__json_object *o) +static inline long long libxl__json_object_get_integer(const libxl__json_object *o) { if (libxl__json_object_is_integer(o)) return o->u.i; diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c index 389b697..fd5e2aa 100644 --- a/tools/libxl/libxl_json.c +++ b/tools/libxl/libxl_json.c @@ -14,6 +14,7 @@ #include <assert.h> #include <string.h> +#include <math.h> #include <yajl/yajl_parse.h> #include <yajl/yajl_gen.h> @@ -44,6 +45,7 @@ struct libxl__yajl_ctx { # define DEBUG_GEN(ctx, type) yajl_gen_##type(ctx->g) # define DEBUG_GEN_VALUE(ctx, type, value) yajl_gen_##type(ctx->g, value) # define DEBUG_GEN_STRING(ctx, str, n) yajl_gen_string(ctx->g, str, n) +# define DEBUG_GEN_NUMBER(ctx, str, n) yajl_gen_number(ctx->g, str, n) # define DEBUG_GEN_REPORT(yajl_ctx) \ do { \ const unsigned char *buf = NULL; \ @@ -60,6 +62,7 @@ struct libxl__yajl_ctx { # define DEBUG_GEN(ctx, type) ((void)0) # define DEBUG_GEN_VALUE(ctx, type, value) ((void)0) # define DEBUG_GEN_STRING(ctx, value, lenght) ((void)0) +# define DEBUG_GEN_NUMBER(ctx, value, lenght) ((void)0) # define DEBUG_GEN_REPORT(ctx) ((void)0) #endif @@ -363,6 +366,7 @@ void libxl__json_object_free(libxl__gc *gc, libxl__json_object *obj) return; switch (obj->type) { case JSON_STRING: + case JSON_NUMBER: free(obj->u.string); break; case JSON_MAP: { @@ -504,36 +508,64 @@ static int json_callback_boolean(void *opaque, int boolean) return 1; } -static int json_callback_integer(void *opaque, long value) +static bool is_decimal(const char *s, unsigned len) +{ + const char *end = s + len; + for (; s < end; s++) { + if (*s == ''.'') + return true; + } + return false; +} + +static int json_callback_number(void *opaque, const char *s, unsigned int len) { libxl__yajl_ctx *ctx = opaque; - libxl__json_object *obj; + libxl__json_object *obj = NULL; + char *t = NULL; - DEBUG_GEN_VALUE(ctx, integer, value); + DEBUG_GEN_NUMBER(ctx, s, len); - if ((obj = json_object_alloc(ctx->gc, JSON_INTEGER)) == NULL) - return 0; - obj->u.i = value; + if (is_decimal(s, len)) { + double d = strtod(s, NULL); - if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { - libxl__json_object_free(ctx->gc, obj); - return 0; - } + if ((d == HUGE_VAL || d == HUGE_VAL) && errno == ERANGE) { + goto error; + } - return 1; -} + if ((obj = json_object_alloc(ctx->gc, JSON_DOUBLE)) == NULL) + return 0; + obj->u.d = d; + } else { + long long i = strtoll(s, NULL, 10); -static int json_callback_double(void *opaque, double value) -{ - libxl__yajl_ctx *ctx = opaque; - libxl__json_object *obj; + if ((i == LLONG_MIN || i == LLONG_MAX) && errno == ERANGE) { + goto error; + } - DEBUG_GEN_VALUE(ctx, double, value); + if ((obj = json_object_alloc(ctx->gc, JSON_INTEGER)) == NULL) + return 0; + obj->u.i = i; + } + goto out; - if ((obj = json_object_alloc(ctx->gc, JSON_DOUBLE)) == NULL) +error: + /* If the conversion fail, we just store the original string. */ + if ((obj = json_object_alloc(ctx->gc, JSON_NUMBER)) == NULL) return 0; - obj->u.d = value; + t = malloc(len + 1); + if (t == NULL) { + LIBXL__LOG_ERRNO(libxl__gc_owner(ctx->gc), LIBXL__LOG_ERROR, + "Failed to allocate"); + return 0; + } + strncpy(t, s, len); + t[len] = 0; + + obj->u.string = t; + +out: if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) { libxl__json_object_free(ctx->gc, obj); return 0; @@ -706,9 +738,9 @@ static int json_callback_end_array(void *opaque) static yajl_callbacks callbacks = { json_callback_null, json_callback_boolean, - json_callback_integer, - json_callback_double, NULL, + NULL, + json_callback_number, json_callback_string, json_callback_start_map, json_callback_map_key, -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 10/13] libxl_qmp: Introduce libxl__qmp_pci_add.
This function insert a PCI passthrough device in qemu. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_internal.h | 4 ++ tools/libxl/libxl_qmp.c | 95 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 0 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 09e0c51..718a417 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -119,6 +119,9 @@ typedef struct { } libxl__device; #define XC_PCI_BDF "0x%x, 0x%x, 0x%x, 0x%x" +#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) +#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) +#define PCI_FUNC(devfn) ((devfn) & 0x07) #define AUTO_PHP_SLOT 0x100 #define SYSFS_PCI_DEV "/sys/bus/pci/devices" #define SYSFS_PCIBACK_DRIVER "/sys/bus/pci/drivers/pciback" @@ -446,6 +449,7 @@ _hidden libxl__qmp_handler *libxl__qmp_initialize(libxl_ctx *ctx, uint32_t domid); /* ask to QEMU the serial port information and store it in xenstore. */ _hidden int libxl__qmp_query_serial(libxl__qmp_handler *qmp); +_hidden int libxl__qmp_pci_add(libxl__gc *gc, int d, libxl_device_pci *pcidev); /* 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 6d80538..07ccf7a 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -41,6 +41,7 @@ */ #define QMP_RECEIVE_BUFFER_SIZE 4096 +#define PCI_PT_QDEV_ID "pci-pt-%02x_%02x.%01x" typedef int (*qmp_callback_t)(libxl__qmp_handler *qmp, const libxl__json_object *tree, @@ -618,6 +619,100 @@ int libxl__qmp_query_serial(libxl__qmp_handler *qmp) NULL, qmp->timeout); } +static int pci_add_callback(libxl__qmp_handler *qmp, + const libxl__json_object *response, void *opaque) +{ + libxl_device_pci *pcidev = opaque; + const libxl__json_object *bus = NULL; + libxl__gc gc = LIBXL_INIT_GC(qmp->ctx); + int i, j, rc = -1; + char *asked_id = libxl__sprintf(&gc, PCI_PT_QDEV_ID, + pcidev->bus, pcidev->dev, pcidev->func); + + for (i = 0; (bus = libxl__json_array_get(response, i)); i++) { + const libxl__json_object *devices = NULL; + const libxl__json_object *device = NULL; + const libxl__json_object *o = NULL; + const char *id = NULL; + + devices = libxl__json_map_get("devices", bus, JSON_ARRAY); + + for (j = 0; (device = libxl__json_array_get(devices, j)); j++) { + o = libxl__json_map_get("qdev_id", device, JSON_STRING); + id = libxl__json_object_get_string(o); + + if (id && strcmp(asked_id, id) == 0) { + int dev_slot, dev_func; + + o = libxl__json_map_get("slot", device, JSON_INTEGER); + if (!o) + goto out; + dev_slot = libxl__json_object_get_integer(o); + o = libxl__json_map_get("function", device, JSON_INTEGER); + if (!o) + goto out; + dev_func = libxl__json_object_get_integer(o); + + pcidev->vdevfn = PCI_DEVFN(dev_slot, dev_func); + + rc = 0; + goto out; + } + } + } + + +out: + libxl__free_all(&gc); + return rc; +} + +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; + char *hostaddr = NULL; + int rc = 0; + + qmp = libxl__qmp_initialize(libxl__gc_owner(gc), domid); + if (!qmp) + return -1; + + hostaddr = libxl__sprintf(gc, "%04x:%02x:%02x.%01x", pcidev->domain, + pcidev->bus, pcidev->dev, pcidev->func); + if (!hostaddr) + return -1; + + parameters = flexarray_make(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); + if (pcidev->vdevfn) { + flexarray_append_pair(parameters, "addr", + libxl__sprintf(gc, "%x.%x", + PCI_SLOT(pcidev->vdevfn), + PCI_FUNC(pcidev->vdevfn))); + } + args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); + if (!args) + return -1; + + rc = qmp_synchronous_send(qmp, "device_add", &args, + NULL, NULL, qmp->timeout); + if (rc == 0) { + rc = qmp_synchronous_send(qmp, "query-pci", NULL, + pci_add_callback, pcidev, qmp->timeout); + } + + flexarray_free(parameters); + libxl__qmp_close(qmp); + return rc; +} + int libxl__qmp_initializations(libxl_ctx *ctx, uint32_t domid) { libxl__qmp_handler *qmp = NULL; -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 11/13] libxl: Use QMP to insert a passthrough device when using upstream QEMU
Also move the xenstore specif code to a new function and add a message if sscanf fail. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_pci.c | 74 +++++++++++++++++++++++++++++++++-------------- 1 files changed, 52 insertions(+), 22 deletions(-) diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c index 33dd060..207ee33 100644 --- a/tools/libxl/libxl_pci.c +++ b/tools/libxl/libxl_pci.c @@ -599,11 +599,52 @@ static int pci_ins_check(libxl__gc *gc, uint32_t domid, const char *state, void return 1; } -static int do_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, int starting) +static int qemu_pci_add_xenstore(libxl__gc *gc, uint32_t domid, + libxl_device_pci *pcidev) { libxl_ctx *ctx = libxl__gc_owner(gc); + int rc = 0; char *path; char *state, *vdevfn; + + path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid); + state = libxl__xs_read(gc, XBT_NULL, path); + path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/parameter", + domid); + if (pcidev->vdevfn) { + libxl__xs_write(gc, XBT_NULL, path, PCI_BDF_VDEVFN, + pcidev->domain, pcidev->bus, pcidev->dev, + pcidev->func, pcidev->vdevfn); + } else { + libxl__xs_write(gc, XBT_NULL, path, PCI_BDF, pcidev->domain, + pcidev->bus, pcidev->dev, pcidev->func); + } + path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/command", + domid); + xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins")); + rc = libxl__wait_for_device_model(gc, domid, NULL, NULL, + pci_ins_check, state); + path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/parameter", + domid); + vdevfn = libxl__xs_read(gc, XBT_NULL, path); + path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", + domid); + if ( rc < 0 ) + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, + "qemu refused to add device: %s", vdevfn); + else if ( sscanf(vdevfn, "0x%x", &pcidev->vdevfn) != 1 ) { + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, + "wrong format for the vdevfn: ''%s''", vdevfn); + rc = -1; + } + xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state)); + + return rc; +} + +static int do_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, int starting) +{ + libxl_ctx *ctx = libxl__gc_owner(gc); int rc, hvm = 0; switch (libxl__domain_type(gc, domid)) { @@ -613,27 +654,16 @@ static int do_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, i NULL, NULL, NULL) < 0) { return ERROR_FAIL; } - path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid); - state = libxl__xs_read(gc, XBT_NULL, path); - path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/parameter", domid); - if (pcidev->vdevfn) - libxl__xs_write(gc, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain, - pcidev->bus, pcidev->dev, pcidev->func, pcidev->vdevfn); - else - libxl__xs_write(gc, XBT_NULL, path, PCI_BDF, pcidev->domain, - pcidev->bus, pcidev->dev, pcidev->func); - path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/command", domid); - xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins")); - rc = libxl__wait_for_device_model(gc, domid, NULL, NULL, - pci_ins_check, state); - path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/parameter", domid); - vdevfn = libxl__xs_read(gc, XBT_NULL, path); - path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid); - if ( rc < 0 ) - LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "qemu refused to add device: %s", vdevfn); - else if ( sscanf(vdevfn, "0x%x", &pcidev->vdevfn) != 1 ) - rc = -1; - xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state)); + switch (libxl__device_model_version_running(gc, domid)) { + case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: + rc = qemu_pci_add_xenstore(gc, domid, pcidev); + break; + case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: + rc = libxl__qmp_pci_add(gc, domid, pcidev); + break; + default: + return ERROR_INVAL; + } if ( rc ) return ERROR_FAIL; break; -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 12/13] libxl_qmp: Introduce libxl__qmp_pci_del
To remove a pci passthough device from QEMU (upstream). Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_internal.h | 2 ++ tools/libxl/libxl_qmp.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 0 deletions(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 718a417..5123578 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -450,6 +450,8 @@ _hidden libxl__qmp_handler *libxl__qmp_initialize(libxl_ctx *ctx, /* ask to QEMU the serial port information and store it in xenstore. */ _hidden int libxl__qmp_query_serial(libxl__qmp_handler *qmp); _hidden int libxl__qmp_pci_add(libxl__gc *gc, int d, libxl_device_pci *pcidev); +_hidden int libxl__qmp_pci_del(libxl__gc *gc, int domid, + libxl_device_pci *pcidev); /* 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 07ccf7a..e7eb8cc 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -713,6 +713,41 @@ int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev) return rc; } +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; + int rc = 0; + + qmp = libxl__qmp_initialize(libxl__gc_owner(gc), domid); + if (!qmp) + return -1; + + parameters = flexarray_make(2, 1); + flexarray_append_pair(parameters, "id", id); + args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count); + if (!args) + return -1; + + rc = qmp_synchronous_send(qmp, "device_del", &args, + NULL, NULL, qmp->timeout); + + flexarray_free(parameters); + libxl__qmp_close(qmp); + return rc; +} + +int libxl__qmp_pci_del(libxl__gc *gc, int domid, libxl_device_pci *pcidev) +{ + char *id = NULL; + + id = libxl__sprintf(gc, PCI_PT_QDEV_ID, + pcidev->bus, pcidev->dev, pcidev->func); + + return qmp_device_del(gc, domid, id); +} + int libxl__qmp_initializations(libxl_ctx *ctx, uint32_t domid) { libxl__qmp_handler *qmp = NULL; -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Anthony PERARD
2011-Nov-01 16:07 UTC
[Xen-devel] [PATCH V3 13/13] libxl: Remove a passthrough device through QMP.
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_pci.c | 69 ++++++++++++++++++++++++++++++---------------- 1 files changed, 45 insertions(+), 24 deletions(-) diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c index 207ee33..1f93e67 100644 --- a/tools/libxl/libxl_pci.c +++ b/tools/libxl/libxl_pci.c @@ -861,13 +861,45 @@ out: return rc; } +static int qemu_pci_remove_xenstore(libxl__gc *gc, uint32_t domid, + libxl_device_pci *pcidev, int force) +{ + libxl_ctx *ctx = libxl__gc_owner(gc); + char *state; + char *path; + + path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid); + state = libxl__xs_read(gc, XBT_NULL, path); + path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/parameter", domid); + libxl__xs_write(gc, XBT_NULL, path, PCI_BDF, pcidev->domain, + pcidev->bus, pcidev->dev, pcidev->func); + path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/command", domid); + + /* Remove all functions at once atomically by only signalling + * device-model for function 0 */ + if ( !force && (pcidev->vdevfn & 0x7) == 0 ) { + xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem")); + if (libxl__wait_for_device_model(gc, domid, "pci-removed", + NULL, NULL, NULL) < 0) { + LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Device Model didn''t respond in time"); + /* This depends on guest operating system acknowledging the + * SCI, if it doesn''t respond in time then we may wish to + * force the removal. + */ + return ERROR_FAIL; + } + } + path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid); + xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state)); + + return 0; +} + static int do_pci_remove(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, int force) { libxl_ctx *ctx = libxl__gc_owner(gc); libxl_device_pci *assigned; - char *path; - char *state; int hvm = 0, rc, num; int stubdomid = 0; @@ -886,29 +918,18 @@ static int do_pci_remove(libxl__gc *gc, uint32_t domid, NULL, NULL, NULL) < 0) { return ERROR_FAIL; } - path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid); - state = libxl__xs_read(gc, XBT_NULL, path); - path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/parameter", domid); - libxl__xs_write(gc, XBT_NULL, path, PCI_BDF, pcidev->domain, - pcidev->bus, pcidev->dev, pcidev->func); - path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/command", domid); - - /* Remove all functions at once atomically by only signalling - * device-model for function 0 */ - if ( !force && (pcidev->vdevfn & 0x7) == 0 ) { - xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem")); - if (libxl__wait_for_device_model(gc, domid, "pci-removed", - NULL, NULL, NULL) < 0) { - LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Device Model didn''t respond in time"); - /* This depends on guest operating system acknowledging the - * SCI, if it doesn''t respond in time then we may wish to - * force the removal. - */ - return ERROR_FAIL; - } + switch (libxl__device_model_version_running(gc, domid)) { + case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: + rc = qemu_pci_remove_xenstore(gc, domid, pcidev, force); + break; + case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: + rc = libxl__qmp_pci_del(gc, domid, pcidev); + break; + default: + return ERROR_INVAL; } - path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid); - xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state)); + if (rc) + return ERROR_FAIL; break; case LIBXL_DOMAIN_TYPE_PV: { -- Anthony PERARD _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Ian Jackson
2011-Nov-04 12:44 UTC
Re: [Xen-devel] [PATCH V3 10/13] libxl: libxl_qmp: Introduce libxl__qmp_pci_add.
Anthony PERARD writes ("[Xen-devel] [PATCH V3 10/13] libxl: libxl_qmp: Introduce libxl__qmp_pci_add."):> This function insert a PCI passthrough device in qemu.Thanks. I have applied 1-9 from this series. 13/13 had a conflict, and I wasn''t 100% sure that it was right to apply it without 10,11,12, although it seems to me that it ought to be OK. Can you confirm, and respin the last patch (or the others) as appropriate ? Thanks, Ian. _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Ian Jackson
2011-Nov-04 14:51 UTC
Re: [Xen-devel] [PATCH V3 11/13] libxl: Use QMP to insert a passthrough device when using upstream QEMU
Anthony PERARD writes ("[Xen-devel] [PATCH V3 11/13] libxl: Use QMP to insert a passthrough device when using upstream QEMU"):> Also move the xenstore specific code to a new function and add a > message if sscanf fails.Thanks, following discussion I''ve applied 10,11 and will wait with 12 for the rebase of 13. Ian. _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel