From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34558) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XZNIH-0002dn-5o for qemu-devel@nongnu.org; Wed, 01 Oct 2014 13:02:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XZNI9-0001eO-JY for qemu-devel@nongnu.org; Wed, 01 Oct 2014 13:02:25 -0400 Received: from mx1.redhat.com ([209.132.183.28]:10438) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XZNI9-0001eJ-Co for qemu-devel@nongnu.org; Wed, 01 Oct 2014 13:02:17 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s91H2G0B020973 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Wed, 1 Oct 2014 13:02:16 -0400 From: Stefan Hajnoczi Date: Wed, 1 Oct 2014 18:01:53 +0100 Message-Id: <1412182919-9550-6-git-send-email-stefanha@redhat.com> In-Reply-To: <1412182919-9550-1-git-send-email-stefanha@redhat.com> References: <1412182919-9550-1-git-send-email-stefanha@redhat.com> Subject: [Qemu-devel] [PATCH 05/11] blockjob: add block_job_defer_to_main_loop() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , Paolo Bonzini , Fam Zheng , Stefan Hajnoczi , Max Reitz Block jobs will run in the BlockDriverState's AioContext, which may not always be the QEMU main loop. There are some block layer APIs that are either not thread-safe or risk lock ordering problems. This includes bdrv_unref(), bdrv_close(), and anything that calls bdrv_drain_all(). The block_job_defer_to_main_loop() API allows a block job to schedule a function to run in the main loop with the BlockDriverState AioContext held. This function will be used to perform cleanup and backing chain manipulations in block jobs. Signed-off-by: Stefan Hajnoczi --- blockjob.c | 35 +++++++++++++++++++++++++++++++++++ include/block/blockjob.h | 19 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/blockjob.c b/blockjob.c index 0689fdd..24a64d8 100644 --- a/blockjob.c +++ b/blockjob.c @@ -313,3 +313,38 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, } return action; } + +typedef struct { + BlockJob *job; + QEMUBH *bh; + AioContext *aio_context; + BlockJobDeferToMainLoopFn *fn; + void *opaque; +} BlockJobDeferToMainLoopData; + +static void block_job_defer_to_main_loop_bh(void *opaque) +{ + BlockJobDeferToMainLoopData *data = opaque; + + qemu_bh_delete(data->bh); + + aio_context_acquire(data->aio_context); + data->fn(data->job, data->opaque); + aio_context_release(data->aio_context); + + g_free(data); +} + +void block_job_defer_to_main_loop(BlockJob *job, + BlockJobDeferToMainLoopFn *fn, + void *opaque) +{ + BlockJobDeferToMainLoopData *data = g_malloc(sizeof(*data)); + data->job = job; + data->bh = qemu_bh_new(block_job_defer_to_main_loop_bh, data); + data->aio_context = bdrv_get_aio_context(job->bs); + data->fn = fn; + data->opaque = opaque; + + qemu_bh_schedule(data->bh); +} diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 60aa835..5c13124 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -295,4 +295,23 @@ void block_job_iostatus_reset(BlockJob *job); BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, BlockdevOnError on_err, int is_read, int error); + +typedef void BlockJobDeferToMainLoopFn(BlockJob *job, void *opaque); + +/** + * block_job_defer_to_main_loop: + * @job: The job + * @fn: The function to run in the main loop + * @opaque: The opaque value that is passed to @fn + * + * Execute a given function in the main loop with the BlockDriverState + * AioContext acquired. Block jobs must call bdrv_unref(), bdrv_close(), and + * anything that uses bdrv_drain_all() in the main loop. + * + * The @job AioContext is held while @fn executes. + */ +void block_job_defer_to_main_loop(BlockJob *job, + BlockJobDeferToMainLoopFn *fn, + void *opaque); + #endif -- 1.9.3