From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38209) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlGC3-0006pl-Bb for qemu-devel@nongnu.org; Mon, 03 Nov 2014 06:53:13 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XlGBx-0000wE-6S for qemu-devel@nongnu.org; Mon, 03 Nov 2014 06:53:07 -0500 Received: from mx1.redhat.com ([209.132.183.28]:42349) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlGBw-0000w1-W8 for qemu-devel@nongnu.org; Mon, 03 Nov 2014 06:53:01 -0500 From: Stefan Hajnoczi Date: Mon, 3 Nov 2014 11:50:52 +0000 Message-Id: <1415015456-25086-50-git-send-email-stefanha@redhat.com> In-Reply-To: <1415015456-25086-1-git-send-email-stefanha@redhat.com> References: <1415015456-25086-1-git-send-email-stefanha@redhat.com> Subject: [Qemu-devel] [PULL 49/53] block: let backup blockjob run in BDS AioContext List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Peter Maydell , Stefan Hajnoczi The backup block job must run in the BlockDriverState AioContext so that it works with dataplane. The basics of acquiring the AioContext are easy in blockdev.c. The completion code in block/backup.c must call bdrv_unref() from the main loop. Use block_job_defer_to_main_loop() to achieve that. Signed-off-by: Stefan Hajnoczi Reviewed-by: Max Reitz Message-id: 1413889440-32577-8-git-send-email-stefanha@redhat.com --- block/backup.c | 21 +++++++++++++++++++-- blockdev.c | 23 ++++++++++++++++------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/block/backup.c b/block/backup.c index e334740..792e655 100644 --- a/block/backup.c +++ b/block/backup.c @@ -227,9 +227,25 @@ static BlockErrorAction backup_error_action(BackupBlockJob *job, } } +typedef struct { + int ret; +} BackupCompleteData; + +static void backup_complete(BlockJob *job, void *opaque) +{ + BackupBlockJob *s = container_of(job, BackupBlockJob, common); + BackupCompleteData *data = opaque; + + bdrv_unref(s->target); + + block_job_completed(job, data->ret); + g_free(data); +} + static void coroutine_fn backup_run(void *opaque) { BackupBlockJob *job = opaque; + BackupCompleteData *data; BlockDriverState *bs = job->common.bs; BlockDriverState *target = job->target; BlockdevOnError on_target_error = job->on_target_error; @@ -344,9 +360,10 @@ static void coroutine_fn backup_run(void *opaque) hbitmap_free(job->bitmap); bdrv_iostatus_disable(target); - bdrv_unref(target); - block_job_completed(&job->common, ret); + data = g_malloc(sizeof(*data)); + data->ret = ret; + block_job_defer_to_main_loop(&job->common, backup_complete, data); } void backup_start(BlockDriverState *bs, BlockDriverState *target, diff --git a/blockdev.c b/blockdev.c index 774051b..9c68988 100644 --- a/blockdev.c +++ b/blockdev.c @@ -2108,6 +2108,7 @@ void qmp_drive_backup(const char *device, const char *target, BlockDriverState *bs; BlockDriverState *target_bs; BlockDriverState *source = NULL; + AioContext *aio_context; BlockDriver *drv = NULL; Error *local_err = NULL; int flags; @@ -2133,9 +2134,12 @@ void qmp_drive_backup(const char *device, const char *target, return; } + aio_context = bdrv_get_aio_context(bs); + aio_context_acquire(aio_context); + if (!bdrv_is_inserted(bs)) { error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device); - return; + goto out; } if (!has_format) { @@ -2145,12 +2149,12 @@ void qmp_drive_backup(const char *device, const char *target, drv = bdrv_find_format(format); if (!drv) { error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); - return; + goto out; } } if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) { - return; + goto out; } flags = bs->open_flags | BDRV_O_RDWR; @@ -2170,7 +2174,7 @@ void qmp_drive_backup(const char *device, const char *target, size = bdrv_getlength(bs); if (size < 0) { error_setg_errno(errp, -size, "bdrv_getlength failed"); - return; + goto out; } if (mode != NEW_IMAGE_MODE_EXISTING) { @@ -2187,23 +2191,28 @@ void qmp_drive_backup(const char *device, const char *target, if (local_err) { error_propagate(errp, local_err); - return; + goto out; } target_bs = NULL; ret = bdrv_open(&target_bs, target, NULL, NULL, flags, drv, &local_err); if (ret < 0) { error_propagate(errp, local_err); - return; + goto out; } + bdrv_set_aio_context(target_bs, aio_context); + backup_start(bs, target_bs, speed, sync, on_source_error, on_target_error, block_job_cb, bs, &local_err); if (local_err != NULL) { bdrv_unref(target_bs); error_propagate(errp, local_err); - return; + goto out; } + +out: + aio_context_release(aio_context); } BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp) -- 1.9.3