From patchwork Fri Apr 13 16:23:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 152347 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id E3D8CB700E for ; Sat, 14 Apr 2012 02:46:18 +1000 (EST) Received: from localhost ([::1]:39832 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SIjIl-0001KZ-H4 for incoming@patchwork.ozlabs.org; Fri, 13 Apr 2012 12:24:47 -0400 Received: from eggs.gnu.org ([208.118.235.92]:45289) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SIjHx-0007XL-3s for qemu-devel@nongnu.org; Fri, 13 Apr 2012 12:24:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SIjHq-0007vn-Bu for qemu-devel@nongnu.org; Fri, 13 Apr 2012 12:23:56 -0400 Received: from mail-pz0-f46.google.com ([209.85.210.46]:40589) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SIjHq-0007ul-2b for qemu-devel@nongnu.org; Fri, 13 Apr 2012 12:23:50 -0400 Received: by mail-pz0-f46.google.com with SMTP id z9so4706424dad.33 for ; Fri, 13 Apr 2012 09:23:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=brQ1Rwdqg/IWuDrG9CVJbHNSVWh4Emx9YSlejFUvQEQ=; b=i2fmmINJgaSk1Pj6xgMTFKIRPheWhVCr0Y2Qtv08Rv7RTOYW3k6xZOZm3Jcuf4R54n bAyMxDMjCMtXJ92xJ3WBusK/CUduQPTbG5i1QRo+y45X6qpeKzx62/x4V89tElFFRfBA Ts0vs0Dfc+QhKvXm7PwLHvvH1mwl/M4XNNCrQkrvHnjRrH/VyI9aYg/vPAI0KRIezQwE OsD+AjVeb3wmCU0TYgm5aVFGqn7dikbI83H/aGFV4pTRtmp6pH7RBou1AlOlKGAB9H/6 87FX57ijsckWGNZQkIJd46nVvEN37aprSZpEy0P6sP2lOSntl6AYI7mvcNWPY1CI/2Po gGiw== Received: by 10.68.226.5 with SMTP id ro5mr5904400pbc.74.1334334229224; Fri, 13 Apr 2012 09:23:49 -0700 (PDT) Received: from yakj.usersys.redhat.com (93-34-182-16.ip50.fastwebnet.it. [93.34.182.16]) by mx.google.com with ESMTPS id s7sm9116719pbl.31.2012.04.13.09.23.45 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 13 Apr 2012 09:23:47 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Fri, 13 Apr 2012 18:23:13 +0200 Message-Id: <1334334198-30899-4-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.9.3 In-Reply-To: <1334334198-30899-1-git-send-email-pbonzini@redhat.com> References: <1334334198-30899-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.210.46 Cc: kwolf@redhat.com, fsimonce@redhat.com, mtosatti@redhat.com, eblake@redhat.com, stefanha@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 3/8] block: allow doing I/O in a job after cancellation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Track the coroutine that executes the job, so that the wait can be cancelled before block_job_cancel restarts. This also gives to the coroutine an opportunity to flip job->busy to true, and submit new I/O before exiting. block_job_cancel_sync will wait for job->busy to become false again. Also drain the I/O *before* canceling the job, so that all I/O from the guest is visible to the job. This is needed for mirroring. Once mirroring reaches "steady state" (i.e. all data from the source is also in the target, except for new writes coming in from the guest), cancellation of the job will keep the disks synchronized. The job thus requires to handle cancellation with care, and this patch provides the infrastructure. Signed-off-by: Paolo Bonzini --- block.c | 8 ++++++++ block/stream.c | 7 +++---- block_int.h | 12 ++++++++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/block.c b/block.c index 1eb82f2..c272421 100644 --- a/block.c +++ b/block.c @@ -4255,7 +4255,15 @@ int block_job_set_speed(BlockJob *job, int64_t value) void block_job_cancel(BlockJob *job) { + /* Complete all guest I/O before cancelling the job, so that if the + * job chooses to complete itself it will do so with a consistent + * view of the disk. + */ + bdrv_drain_all(); job->cancelled = true; + if (job->co && !job->busy) { + qemu_coroutine_enter(job->co, NULL); + } } bool block_job_is_cancelled(BlockJob *job) diff --git a/block/stream.c b/block/stream.c index 0116450..d38f30a 100644 --- a/block/stream.c +++ b/block/stream.c @@ -191,7 +191,6 @@ int stream_start(BlockDriverState *bs, BlockDriverState *base, void *opaque) { StreamBlockJob *s; - Coroutine *co; s = block_job_create(&stream_job_type, bs, cb, opaque); if (!s) { @@ -203,8 +202,8 @@ int stream_start(BlockDriverState *bs, BlockDriverState *base, pstrcpy(s->backing_file_id, sizeof(s->backing_file_id), base_id); } - co = qemu_coroutine_create(stream_run); - trace_stream_start(bs, base, s, co, opaque); - qemu_coroutine_enter(co, s); + s->common.co = qemu_coroutine_create(stream_run); + trace_stream_start(bs, base, s, s->common.co, opaque); + qemu_coroutine_enter(s->common.co, s); return 0; } diff --git a/block_int.h b/block_int.h index 58e3eea..eae24d2 100644 --- a/block_int.h +++ b/block_int.h @@ -94,6 +94,12 @@ struct BlockJob { BlockDriverState *bs; /** + * The coroutine that executes the job. If not NULL, it is + * reentered when busy is false and the job is cancelled. + */ + Coroutine *co; + + /** * Set to true if the job should cancel itself. The flag must * always be tested just before toggling the busy flag from false * to true. After a job has detected that the cancelled flag is @@ -104,10 +110,8 @@ struct BlockJob { /** * Set to false by the job while it is in a quiescent state, where - * no I/O is pending and cancellation can be processed without - * issuing new I/O. The busy flag must be set to false when the - * job goes to sleep on any condition that is not detected by - * #qemu_aio_wait, such as a timer. + * no I/O is pending and the job goes to sleep on any condition + * that is not detected by #qemu_aio_wait, such as a timer. */ bool busy;