On 09/25/2014 06:57 PM, Kevin Wolf wrote: > Am 25.09.2014 um 10:41 hat Alexey Kardashevskiy geschrieben: >> On 09/24/2014 07:48 PM, Kevin Wolf wrote: >>> Am 23.09.2014 um 10:47 hat Alexey Kardashevskiy geschrieben: >>>> On 09/19/2014 06:47 PM, Kevin Wolf wrote:> Am 16.09.2014 um 14:59 hat Paolo Bonzini geschrieben: >>>>>> Il 16/09/2014 14:52, Kevin Wolf ha scritto: >>>>>>> Yes, that's true. We can't fix this problem in qcow2, though, because >>>>>>> it's a more general one. I think we must make sure that >>>>>>> bdrv_invalidate_cache() doesn't yield. >>>>>>> >>>>>>> Either by forbidding to run bdrv_invalidate_cache() in a coroutine and >>>>>>> moving the problem to the caller (where and why is it even called from a >>>>>>> coroutine?), or possibly by creating a new coroutine for the driver >>>>>>> callback and running that in a nested event loop that only handles >>>>>>> bdrv_invalidate_cache() callbacks, so that the NBD server doesn't get a >>>>>>> chance to process new requests in this thread. >>>>>> >>>>>> Incoming migration runs in a coroutine (the coroutine entry point is >>>>>> process_incoming_migration_co). But everything after qemu_fclose() can >>>>>> probably be moved into a separate bottom half, so that it gets out of >>>>>> coroutine context. >>>>> >>>>> Alexey, you should probably rather try this (and add a bdrv_drain_all() >>>>> in bdrv_invalidate_cache) than messing around with qcow2 locks. This >>>>> isn't a problem that can be completely fixed in qcow2. >>>> >>>> >>>> Ok. Tried :) Not very successful though. The patch is below. >>>> >>>> Is that the correct bottom half? When I did it, I started getting crashes >>>> in various sport on accesses to s->l1_cache which is NULL after qcow2_close. >>>> Normally the code would check s->l1_size and then use but they are out of sync. >>> >>> No, that's not the place we were talking about. >>> >>> What Paolo meant is that in process_incoming_migration_co(), you can >>> split out the final part that calls bdrv_invalidate_cache_all() into a >>> BH (you need to move everything until the end of the function into the >>> BH then). His suggestion was to move everything below the qemu_fclose(). >> >> Ufff. I took it very literally. Ok. Let it be >> process_incoming_migration_co(). But there is something I am missing about >> BHs. Here is a patch: >> > You need to call qemu_bh_schedule(). Right. Cool. So is below what was suggested? I am doublechecking as it does not solve the original issue - the bottomhalf is called first and then nbd_trip() crashes in qcow2_co_flush_to_os(). diff --git a/block.c b/block.c index d06dd51..1e6dfd1 100644 --- a/block.c +++ b/block.c @@ -5037,20 +5037,22 @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp) if (local_err) { error_propagate(errp, local_err); return; } ret = refresh_total_sectors(bs, bs->total_sectors); if (ret < 0) { error_setg_errno(errp, -ret, "Could not refresh total sector count"); return; } + + bdrv_drain_all(); } void bdrv_invalidate_cache_all(Error **errp) { BlockDriverState *bs; Error *local_err = NULL; QTAILQ_FOREACH(bs, &bdrv_states, device_list) { AioContext *aio_context = bdrv_get_aio_context(bs); diff --git a/migration.c b/migration.c index 6db04a6..dc026a9 100644 --- a/migration.c +++ b/migration.c @@ -81,49 +81,64 @@ void qemu_start_incoming_migration(const char *uri, Error **errp) else if (strstart(uri, "unix:", &p)) unix_start_incoming_migration(p, errp); else if (strstart(uri, "fd:", &p)) fd_start_incoming_migration(p, errp); #endif else { error_setg(errp, "unknown migration protocol: %s", uri); } } +static QEMUBH *migration_complete_bh; +static void process_incoming_migration_complete(void *opaque); + static void process_incoming_migration_co(void *opaque) { QEMUFile *f = opaque; - Error *local_err = NULL; int ret; ret = qemu_loadvm_state(f); qemu_fclose(f); free_xbzrle_decoded_buf(); if (ret < 0) { error_report("load of migration failed: %s", strerror(-ret)); exit(EXIT_FAILURE); } qemu_announce_self(); bdrv_clear_incoming_migration_all(); + + migration_complete_bh = aio_bh_new(qemu_get_aio_context(), + process_incoming_migration_complete, + NULL); + qemu_bh_schedule(migration_complete_bh); +} + +static void process_incoming_migration_complete(void *opaque) +{ + Error *local_err = NULL; + /* Make sure all file formats flush their mutable metadata */ bdrv_invalidate_cache_all(&local_err); if (local_err) { qerror_report_err(local_err); error_free(local_err); exit(EXIT_FAILURE); } if (autostart) { vm_start(); } else { runstate_set(RUN_STATE_PAUSED); } + qemu_bh_delete(migration_complete_bh); + migration_complete_bh = NULL; } -- Alexey -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list