diff options
author | Roger Pau Monne <roger.pau@citrix.com> | 2012-07-23 13:09:42 +0100 |
---|---|---|
committer | Roger Pau Monne <roger.pau@citrix.com> | 2012-07-23 13:09:42 +0100 |
commit | 225b2010db1b84c223c981a0cd09e548e5fcf93b (patch) | |
tree | c140f42ff2f297df239ab4a280703471eaf36a2e /tools/libxl/libxl.c | |
parent | 9770c75ba37df52ad363ac114a8da5bee487b7b1 (diff) | |
download | xen-225b2010db1b84c223c981a0cd09e548e5fcf93b.tar.gz xen-225b2010db1b84c223c981a0cd09e548e5fcf93b.tar.bz2 xen-225b2010db1b84c223c981a0cd09e548e5fcf93b.zip |
libxl: convert libxl_domain_destroy to an async op
This change introduces some new structures, and breaks the mutual
dependency that libxl_domain_destroy and libxl__destroy_device_model
had. This is done by checking if the domid passed to
libxl_domain_destroy has a stubdom, and then having the bulk of the
destroy machinery in a separate function (libxl__destroy_domid) that
doesn't check for stubdom presence, since we check for it in the upper
level function. The reason behind this change is the need to use
structures for ao operations, and it was impossible to have two
different self-referencing structs.
All uses of libxl_domain_destroy have been changed, and either
replaced by the new libxl_domain_destroy ao function or by the
internal libxl__domain_destroy that can be used inside an already
running ao.
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'tools/libxl/libxl.c')
-rw-r--r-- | tools/libxl/libxl.c | 176 |
1 files changed, 168 insertions, 8 deletions
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index ebc314b46d..0600ce43f3 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -1216,11 +1216,133 @@ void libxl_evdisable_disk_eject(libxl_ctx *ctx, libxl_evgen_disk_eject *evg) { GC_FREE; } -int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid) +/* Callbacks for libxl_domain_destroy */ + +static void domain_destroy_cb(libxl__egc *egc, libxl__domain_destroy_state *dds, + int rc); + +int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, + const libxl_asyncop_how *ao_how) { - GC_INIT(ctx); + AO_CREATE(ctx, domid, ao_how); + libxl__domain_destroy_state *dds; + + GCNEW(dds); + dds->ao = ao; + dds->domid = domid; + dds->callback = domain_destroy_cb; + libxl__domain_destroy(egc, dds); + + return AO_INPROGRESS; +} + +static void domain_destroy_cb(libxl__egc *egc, libxl__domain_destroy_state *dds, + int rc) +{ + STATE_AO_GC(dds->ao); + + if (rc) + LOG(ERROR, "destruction of domain %u failed", dds->domid); + + libxl__ao_complete(egc, ao, rc); +} + +/* Callbacks for libxl__domain_destroy */ + +static void stubdom_destroy_callback(libxl__egc *egc, + libxl__destroy_domid_state *dis, + int rc); + +static void domain_destroy_callback(libxl__egc *egc, + libxl__destroy_domid_state *dis, + int rc); + +static void destroy_finish_check(libxl__egc *egc, + libxl__domain_destroy_state *dds); + +void libxl__domain_destroy(libxl__egc *egc, libxl__domain_destroy_state *dds) +{ + STATE_AO_GC(dds->ao); + uint32_t stubdomid = libxl_get_stubdom_id(CTX, dds->domid); + + if (stubdomid) { + dds->stubdom.ao = ao; + dds->stubdom.domid = stubdomid; + dds->stubdom.callback = stubdom_destroy_callback; + libxl__destroy_domid(egc, &dds->stubdom); + } else { + dds->stubdom_finished = 1; + } + + dds->domain.ao = ao; + dds->domain.domid = dds->domid; + dds->domain.callback = domain_destroy_callback; + libxl__destroy_domid(egc, &dds->domain); +} + +static void stubdom_destroy_callback(libxl__egc *egc, + libxl__destroy_domid_state *dis, + int rc) +{ + STATE_AO_GC(dis->ao); + libxl__domain_destroy_state *dds = CONTAINER_OF(dis, *dds, stubdom); + const char *savefile; + + if (rc) { + LOG(ERROR, "unable to destroy stubdom with domid %u", dis->domid); + dds->rc = rc; + } + + dds->stubdom_finished = 1; + savefile = libxl__device_model_savefile(gc, dis->domid); + rc = libxl__remove_file(gc, savefile); + /* + * On suspend libxl__domain_save_device_model will have already + * unlinked the save file. + */ + if (rc) { + LOG(ERROR, "failed to remove device-model savefile %s", savefile); + } + + destroy_finish_check(egc, dds); +} + +static void domain_destroy_callback(libxl__egc *egc, + libxl__destroy_domid_state *dis, + int rc) +{ + STATE_AO_GC(dis->ao); + libxl__domain_destroy_state *dds = CONTAINER_OF(dis, *dds, domain); + + if (rc) { + LOG(ERROR, "unable to destroy guest with domid %u", dis->domid); + dds->rc = rc; + } + + dds->domain_finished = 1; + destroy_finish_check(egc, dds); +} + +static void destroy_finish_check(libxl__egc *egc, + libxl__domain_destroy_state *dds) +{ + if (!(dds->domain_finished && dds->stubdom_finished)) + return; + + dds->callback(egc, dds, dds->rc); +} + +/* Callbacks for libxl__destroy_domid */ +static void devices_destroy_cb(libxl__egc *egc, + libxl__devices_remove_state *drs, + int rc); + +void libxl__destroy_domid(libxl__egc *egc, libxl__destroy_domid_state *dis) +{ + STATE_AO_GC(dis->ao); + libxl_ctx *ctx = CTX; + uint32_t domid = dis->domid; char *dom_path; - char *vm_path; char *pid; int rc, dm_present; @@ -1231,12 +1353,15 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid) case ERROR_INVAL: LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "non-existant domain %d", domid); default: - return rc; + goto out; } switch (libxl__domain_type(gc, domid)) { case LIBXL_DOMAIN_TYPE_HVM: - dm_present = 1; + if (!libxl_get_stubdom_id(CTX, domid)) + dm_present = 1; + else + dm_present = 0; break; case LIBXL_DOMAIN_TYPE_PV: pid = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "/local/domain/%d/image/device-model-pid", domid)); @@ -1267,7 +1392,37 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid) libxl__qmp_cleanup(gc, domid); } - if (libxl__devices_destroy(gc, domid) < 0) + dis->drs.ao = ao; + dis->drs.domid = domid; + dis->drs.callback = devices_destroy_cb; + dis->drs.force = 1; + libxl__devices_destroy(egc, &dis->drs); + return; + +out: + assert(rc); + dis->callback(egc, dis, rc); + return; +} + +static void devices_destroy_cb(libxl__egc *egc, + libxl__devices_remove_state *drs, + int rc) +{ + STATE_AO_GC(drs->ao); + libxl__destroy_domid_state *dis = CONTAINER_OF(drs, *dis, drs); + libxl_ctx *ctx = CTX; + uint32_t domid = dis->domid; + char *dom_path; + char *vm_path; + + dom_path = libxl__xs_get_dompath(gc, domid); + if (!dom_path) { + rc = ERROR_FAIL; + goto out; + } + + if (rc < 0) LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl__devices_destroy failed for %d", domid); @@ -1280,6 +1435,10 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid) 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)); + xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(gc, + "/local/domain/0/device-model/%d", domid)); + xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(gc, + "/local/domain/%d/hvmloader", domid)); libxl__userdata_destroyall(gc, domid); @@ -1290,9 +1449,10 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid) goto out; } rc = 0; + out: - GC_FREE; - return rc; + dis->callback(egc, dis, rc); + return; } int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, |