From patchwork Mon Jun 13 17:05:34 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 9173675 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 65F246044F for ; Mon, 13 Jun 2016 17:27:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 533382040D for ; Mon, 13 Jun 2016 17:27:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 464DC26861; Mon, 13 Jun 2016 17:27:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id BC57E2040D for ; Mon, 13 Jun 2016 17:27:19 +0000 (UTC) Received: from localhost ([::1]:58020 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCVdu-0003yS-Jr for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jun 2016 13:27:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39573) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCVJZ-0001uu-0T for qemu-devel@nongnu.org; Mon, 13 Jun 2016 13:06:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bCVJS-000214-V7 for qemu-devel@nongnu.org; Mon, 13 Jun 2016 13:06:15 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48522) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bCVJS-00020z-Mt for qemu-devel@nongnu.org; Mon, 13 Jun 2016 13:06:10 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5D5A7C0C4F; Mon, 13 Jun 2016 17:06:10 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5DH68nr029144; Mon, 13 Jun 2016 13:06:09 -0400 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Mon, 13 Jun 2016 18:05:34 +0100 Message-Id: <1465837535-30067-15-git-send-email-stefanha@redhat.com> In-Reply-To: <1465837535-30067-1-git-send-email-stefanha@redhat.com> References: <1465837535-30067-1-git-send-email-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 13 Jun 2016 17:06:10 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v3 14/15] blockjob: add AioContext attach/detach callbacks X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Stefan Hajnoczi , Jeff Cody , mreitz@redhat.com, jjherne@linux.vnet.ibm.com, Paolo Bonzini Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Block jobs need callbacks to get their affairs in order when the AioContext is switched. Simple block jobs can get away without implementing these callbacks. The callbacks are needed if the block job accesses other BlockDriverStates. Other BDSes need to be moved to the new AioContext in the attach callback. The detach callback must be used to quiesce asynchronous I/O. Although bdrv_set_aio_context() internally calls bdrv_drain(), this isn't enough when multiple BDSes are accessed by the job: When completing requests on one BDS submits new requests on another BDS, especially if this is cyclical, then a custom detach callback is needed. Signed-off-by: Stefan Hajnoczi --- blockjob.c | 33 +++++++++++++++++++++++++++++++++ include/block/blockjob.h | 14 ++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/blockjob.c b/blockjob.c index b810d73..dd384fe 100644 --- a/blockjob.c +++ b/blockjob.c @@ -60,6 +60,33 @@ BlockJob *block_job_next(BlockJob *job) return QLIST_NEXT(job, job_list); } +static void block_job_attached_aio_context(AioContext *new_context, + void *opaque) +{ + BlockJob *job = opaque; + + if (job->driver->attached_aio_context) { + job->driver->attached_aio_context(job, new_context); + } + + block_job_resume(job); +} + +static void block_job_detach_aio_context(void *opaque) +{ + BlockJob *job = opaque; + + block_job_pause(job); + + if (job->driver->detach_aio_context) { + job->driver->detach_aio_context(job); + } + + while (job->busy) { + aio_poll(blk_get_aio_context(job->blk), true); + } +} + void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, int64_t speed, BlockCompletionFunc *cb, void *opaque, Error **errp) @@ -92,6 +119,9 @@ void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, QLIST_INSERT_HEAD(&block_jobs, job, job_list); + blk_add_aio_context_notifier(blk, block_job_attached_aio_context, + block_job_detach_aio_context, job); + /* Only set speed when necessary to avoid NotSupported error */ if (speed != 0) { Error *local_err = NULL; @@ -117,6 +147,9 @@ void block_job_unref(BlockJob *job) BlockDriverState *bs = blk_bs(job->blk); bs->job = NULL; bdrv_op_unblock_all(bs, job->blocker); + blk_remove_aio_context_notifier(job->blk, + block_job_attached_aio_context, + block_job_detach_aio_context, job); blk_unref(job->blk); error_free(job->blocker); g_free(job->id); diff --git a/include/block/blockjob.h b/include/block/blockjob.h index f83a4f0..604aff8 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -70,6 +70,20 @@ typedef struct BlockJobDriver { * never both. */ void (*abort)(BlockJob *job); + + /** + * If the callback is not NULL, it will be invoked before the job is + * resumed in a new AioContext. This is the place to move any resources + * besides job->blk to the new AioContext. + */ + void (*attached_aio_context)(BlockJob *job, AioContext *new_context); + + /** + * If the callback is not NULL, it will be invoked after the job is paused + * but before job->blk is detached from the old AioContext. This is the + * place to complete all asynchronous I/O that is in flight. + */ + void (*detach_aio_context)(BlockJob *job); } BlockJobDriver; /**