[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 18/27] tools/libxl: Convert a legacy stream if needed
For backwards compatibility, a legacy stream needs converting before it can be read by the v2 stream logic. This causes the v2 stream logic to need to juggle two parallel tasks. check_stream_finished() is introduced for the purpose of joining the tasks in both success and error cases. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CC: Ian Campbell <Ian.Campbell@xxxxxxxxxx> CC: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> CC: Wei Liu <wei.liu2@xxxxxxxxxx> --- tools/libxl/libxl_internal.h | 7 +++ tools/libxl/libxl_stream_read.c | 98 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 68e7f02..1cf1884 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -3274,6 +3274,7 @@ struct libxl__stream_read_state { /* filled by the user */ libxl__ao *ao; int fd; + bool legacy; void (*completion_callback)(libxl__egc *egc, libxl__stream_read_state *srs, int rc); @@ -3281,6 +3282,12 @@ struct libxl__stream_read_state { int rc; bool running; + /* Active-stuff handling */ + int joined_rc; + + /* Conversion helper */ + libxl__carefd *v2_carefd; + /* Main stream-reading data */ libxl__datacopier_state dc; libxl__sr_hdr hdr; diff --git a/tools/libxl/libxl_stream_read.c b/tools/libxl/libxl_stream_read.c index 6f5d572..3011820 100644 --- a/tools/libxl/libxl_stream_read.c +++ b/tools/libxl/libxl_stream_read.c @@ -57,6 +57,10 @@ * - stream_write_emulator() * - stream_write_emulator_done() * - stream_continue() + * + * Depending on the contents of the stream, there are likely to be several + * parallel tasks being managed. check_stream_finished() is used to join all + * tasks in both success and error cases. */ /* Stream error/success handling. */ @@ -67,6 +71,16 @@ static void stream_failed(libxl__egc *egc, static void stream_done(libxl__egc *egc, libxl__stream_read_state *stream); +/* Stream other-active-stuff handling. */ +/* libxl__xc_domain_restore_done() is logically grouped here. */ +#if defined(__x86_64__) || defined(__i386__) +static void conversion_done(libxl__egc *egc, + libxl__conversion_helper_state *chs, int rc); +#endif +static void check_stream_finished(libxl__egc *egc, + libxl__stream_read_state *stream, + int rc, const char *what); + /* Event callbacks for main reading loop. */ static void stream_header_done(libxl__egc *egc, libxl__datacopier_state *dc, @@ -112,12 +126,40 @@ static int setup_read(libxl__stream_read_state *stream, void libxl__stream_read_start(libxl__egc *egc, libxl__stream_read_state *stream) { + libxl__domain_create_state *dcs = CONTAINER_OF(stream, *dcs, srs); libxl__datacopier_state *dc = &stream->dc; + STATE_AO_GC(stream->ao); int ret = 0; /* State initialisation. */ assert(!stream->running); + /* + * Initialise other moving parts so stream_check_finished() can correctly + * work out whether to tear them down. + */ + libxl__conversion_helper_init(&dcs->chs); + +#if defined(__x86_64__) || defined(__i386__) + if (stream->legacy) { + /* Convert a legacy stream, if needed. */ + dcs->chs.ao = stream->ao; + dcs->chs.legacy_fd = stream->fd; + dcs->chs.hvm = + (dcs->guest_config->b_info.type == LIBXL_DOMAIN_TYPE_HVM); + dcs->chs.v2_carefd = NULL; + dcs->chs.completion_callback = conversion_done; + + libxl__convert_legacy_stream(egc, &dcs->chs); + + assert(dcs->chs.v2_carefd); + stream->v2_carefd = dcs->chs.v2_carefd; + dcs->libxc_fd = stream->fd = libxl__carefd_fd(dcs->chs.v2_carefd); + } +#endif + + /* stream->fd is now guarenteed to be a v2 stream. */ + memset(dc, 0, sizeof(*dc)); dc->ao = stream->ao; dc->readfd = stream->fd; @@ -183,7 +225,50 @@ static void stream_done(libxl__egc *egc, free(rec); } - stream->completion_callback(egc, stream, stream->rc); + if (stream->v2_carefd) + libxl__carefd_close(stream->v2_carefd); + + check_stream_finished(egc, stream, stream->rc, "stream"); +} + +static void check_stream_finished(libxl__egc *egc, + libxl__stream_read_state *stream, + int rc, const char *what) +{ + libxl__domain_create_state *dcs = CONTAINER_OF(stream, *dcs, srs); + STATE_AO_GC(stream->ao); + + LOG(DEBUG, "Task '%s' joining (rc %d)", what, rc); + + if (rc && !stream->joined_rc) { + bool skip = false; + /* First reported failure from joining tasks. Tear everything down */ + stream->joined_rc = rc; + + if (libxl__stream_read_inuse(&dcs->srs)) { + skip = true; + libxl__stream_read_abort(egc, &dcs->srs, rc); + } + + if (libxl__convert_legacy_stream_inuse(&dcs->chs)) { + skip = true; + libxl__convert_legacy_stream_abort(egc, &dcs->chs, rc); + } + + /* There is at least one more active task to join - wait for its + callback */ + if ( skip ) + return; + } + + if (libxl__stream_read_inuse(&dcs->srs)) + LOG(DEBUG, "stream still in use"); + else if (libxl__convert_legacy_stream_inuse(&dcs->chs)) + LOG(DEBUG, "conversion still in use"); + else { + LOG(DEBUG, "Join complete: result %d", stream->joined_rc); + stream->completion_callback(egc, stream, stream->joined_rc); + } } static void stream_continue(libxl__egc *egc, @@ -354,6 +439,17 @@ static void record_body_done(libxl__egc *egc, stream_failed(egc, stream, ret); } +#if defined(__x86_64__) || defined(__i386__) +static void conversion_done(libxl__egc *egc, + libxl__conversion_helper_state *chs, int rc) +{ + STATE_AO_GC(chs->ao); + libxl__domain_create_state *dcs = CONTAINER_OF(chs, *dcs, chs); + + check_stream_finished(egc, &dcs->srs, rc, "conversion"); +} +#endif + /* * Returns a boolean indicating whether a further action should be set up by * the caller. This is needed to prevent mutual recursion with -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |