From patchwork Tue Apr 26 08:51:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 1622252 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=fkZK145g; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KnbJL4txQz9s09 for ; Tue, 26 Apr 2022 18:53:22 +1000 (AEST) Received: from localhost ([::1]:56138 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1njGwi-0007XV-KG for incoming@patchwork.ozlabs.org; Tue, 26 Apr 2022 04:53:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43332) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGux-0006uY-Ja for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:34 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:47682) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGur-0000dN-SK for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:27 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1650963085; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TAF+iXN/P5vG3kfcg8FnN98Snqyu8MB1Oeu77oXegUk=; b=fkZK145glStlEdyXxtiGDuAlMOHmaBSLkFWier0L6pFnNhMMHbz5dg+rXGv7x4oLl2ubE0 5+xYOlaxrww+t5ZG8uoCup97c6qwnfn5aErv21yz6k+Lq8a06QkdNfdNOy28uxWrIaYtNC PWv9MNK8N1zshlwyi4235aj0LZtP5RM= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-205-wbAyKP0ZNyyN_Q2epr6AaQ-1; Tue, 26 Apr 2022 04:51:18 -0400 X-MC-Unique: wbAyKP0ZNyyN_Q2epr6AaQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id F2391811E7A; Tue, 26 Apr 2022 08:51:17 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id ADF8340D282C; Tue, 26 Apr 2022 08:51:17 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [RFC PATCH v2 1/8] aio_wait_kick: add missing memory barrier Date: Tue, 26 Apr 2022 04:51:07 -0400 Message-Id: <20220426085114.199647-2-eesposit@redhat.com> In-Reply-To: <20220426085114.199647-1-eesposit@redhat.com> References: <20220426085114.199647-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Vladimir Sementsov-Ogievskiy , Emanuele Giuseppe Esposito , qemu-devel@nongnu.org, Hanna Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" It seems that aio_wait_kick always required a memory barrier or atomic operation in the caller, but almost nobody actually took care of doing it. Let's put the barrier in the function instead. Signed-off-by: Emanuele Giuseppe Esposito --- util/aio-wait.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/aio-wait.c b/util/aio-wait.c index bdb3d3af22..c0a343ac87 100644 --- a/util/aio-wait.c +++ b/util/aio-wait.c @@ -35,7 +35,8 @@ static void dummy_bh_cb(void *opaque) void aio_wait_kick(void) { - /* The barrier (or an atomic op) is in the caller. */ + smp_mb(); + if (qatomic_read(&global_aio_wait.num_waiters)) { aio_bh_schedule_oneshot(qemu_get_aio_context(), dummy_bh_cb, NULL); } From patchwork Tue Apr 26 08:51:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 1622250 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=jSko5UXp; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KnbHw0Yb0z9s09 for ; Tue, 26 Apr 2022 18:53:00 +1000 (AEST) Received: from localhost ([::1]:55390 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1njGwJ-0006yn-Nw for incoming@patchwork.ozlabs.org; Tue, 26 Apr 2022 04:52:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43324) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGux-0006uT-GU for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:34 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:21892) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGur-0000dD-Rt for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1650963082; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WGzY5fCDmcuo233jTOQ7/MqWha3GnCirdY9aw2kP2Uk=; b=jSko5UXpuwM8+hwwzD1W+cCgh+UwUQKmhf+yKP/58qkxx3PdCarJVoBMG8tos9DMqg5/ei +dnWxf5y+I2eByPPAImq/S3aoZKnA1dL1cCC0E96LtuzhfuA1J5izdJcGwmlz+Zr55Q9Ps eKMhsHW5Lp9s12walOg04stGT7Bq3iA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-207-jCeEHahmPNOEQm8U-tzZ6g-1; Tue, 26 Apr 2022 04:51:18 -0400 X-MC-Unique: jCeEHahmPNOEQm8U-tzZ6g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 49ECC1014A60; Tue, 26 Apr 2022 08:51:18 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 063EA40D2962; Tue, 26 Apr 2022 08:51:18 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [RFC PATCH v2 2/8] coroutine-lock: release lock when restarting all coroutines Date: Tue, 26 Apr 2022 04:51:08 -0400 Message-Id: <20220426085114.199647-3-eesposit@redhat.com> In-Reply-To: <20220426085114.199647-1-eesposit@redhat.com> References: <20220426085114.199647-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Vladimir Sementsov-Ogievskiy , Emanuele Giuseppe Esposito , qemu-devel@nongnu.org, Hanna Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Current implementation of qemu_co_queue_do_restart does not releases the lock before calling aio_co_wake. Most of the time this is fine, but if the coroutine acquires the lock again then we have a deadlock. Instead of duplicating code, use qemu_co_enter_next_impl, since it implements exactly the same functionality that we want. Signed-off-by: Emanuele Giuseppe Esposito --- include/qemu/coroutine.h | 10 ++++++++++ util/qemu-coroutine-lock.c | 26 ++++++++++---------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index c828a95ee0..c49cdc21b4 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -220,6 +220,16 @@ bool qemu_co_queue_next(CoQueue *queue); */ void qemu_co_queue_restart_all(CoQueue *queue); +/** + * Empties the CoQueue; all coroutines are woken up. + * OK to run from coroutine and non-coroutine context. + * Unlocks lock before waking up each coroutine takes it again + * when done. + */ +#define qemu_co_queue_restart_all_lockable(queue, lock) \ + qemu_co_queue_restart_all_impl(queue, QEMU_MAKE_LOCKABLE(lock)) +void qemu_co_queue_restart_all_impl(CoQueue *queue, QemuLockable *lock); + /** * Removes the next coroutine from the CoQueue, and wake it up. Unlike * qemu_co_queue_next, this function releases the lock during aio_co_wake diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c index 2669403839..17bb0d0c95 100644 --- a/util/qemu-coroutine-lock.c +++ b/util/qemu-coroutine-lock.c @@ -67,32 +67,26 @@ void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock) } } -static bool qemu_co_queue_do_restart(CoQueue *queue, bool single) +static void qemu_co_queue_do_restart(CoQueue *queue, QemuLockable *lock) { - Coroutine *next; - - if (QSIMPLEQ_EMPTY(&queue->entries)) { - return false; + while (qemu_co_enter_next_impl(queue, lock)) { + /* nop */ } - - while ((next = QSIMPLEQ_FIRST(&queue->entries)) != NULL) { - QSIMPLEQ_REMOVE_HEAD(&queue->entries, co_queue_next); - aio_co_wake(next); - if (single) { - break; - } - } - return true; } bool qemu_co_queue_next(CoQueue *queue) { - return qemu_co_queue_do_restart(queue, true); + return qemu_co_enter_next_impl(queue, NULL); } void qemu_co_queue_restart_all(CoQueue *queue) { - qemu_co_queue_do_restart(queue, false); + qemu_co_queue_do_restart(queue, NULL); +} + +void qemu_co_queue_restart_all_impl(CoQueue *queue, QemuLockable *lock) +{ + qemu_co_queue_do_restart(queue, lock); } bool qemu_co_enter_next_impl(CoQueue *queue, QemuLockable *lock) From patchwork Tue Apr 26 08:51:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 1622257 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=JB2Iv+tE; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KnbTM0rndz9s75 for ; Tue, 26 Apr 2022 19:01:11 +1000 (AEST) Received: from localhost ([::1]:41850 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1njH4H-00008J-2t for incoming@patchwork.ozlabs.org; Tue, 26 Apr 2022 05:01:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43462) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGvA-00073s-94 for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:44419) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGv7-0000fb-Oh for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1650963101; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6ybqeLj928KxsoJnODD+n8vlkCVYf+o9rlKL+Gb4eDw=; b=JB2Iv+tEjkPasjzlzSxHjgXLNxE+Le2aYJRNz+pG4nKBAHhNHOgRPjvlGg1/uYHHWThNm6 jRnB81vMczJOq1QxbeLz7UCJ+BOFwk+bNKFICQ8hubJ46FQvo+bLUzRqod+LXLy9N4zu9x feIYyJb4vi/jzg6J6neYZtClQPfpz68= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-458-E001ejmhOyCKTMW4Ete3ZA-1; Tue, 26 Apr 2022 04:51:39 -0400 X-MC-Unique: E001ejmhOyCKTMW4Ete3ZA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 18C241E12D37; Tue, 26 Apr 2022 08:51:24 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 530BC40D2824; Tue, 26 Apr 2022 08:51:18 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [RFC PATCH v2 3/8] block: introduce a lock to protect graph operations Date: Tue, 26 Apr 2022 04:51:09 -0400 Message-Id: <20220426085114.199647-4-eesposit@redhat.com> In-Reply-To: <20220426085114.199647-1-eesposit@redhat.com> References: <20220426085114.199647-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Vladimir Sementsov-Ogievskiy , Emanuele Giuseppe Esposito , qemu-devel@nongnu.org, Hanna Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" block layer graph operations are always run under BQL in the main loop. This is proved by the assertion qemu_in_main_thread() and its wrapper macro GLOBAL_STATE_CODE. However, there are also concurrent coroutines running in other iothreads that always try to traverse the graph. Currently this is protected (among various other things) by the AioContext lock, but once this is removed we need to make sure that reads do not happen while modifying the graph. We distinguish between writer (main loop, under BQL) that modifies the graph, and readers (all other coroutines running in various AioContext), that go through the graph edges, reading ->parents and->children. The writer (main loop) has an "exclusive" access, so it first waits for current read to finish, and then prevents incoming ones from entering while it has the exclusive access. The readers (coroutines in multiple AioContext) are free to access the graph as long the writer is not modifying the graph. In case it is, they go in a CoQueue and sleep until the writer is done. If a coroutine changes AioContext, the counter in the original and new AioContext are left intact, since the writer does not care where is the reader, but only if there is one. If instead the original AioContext gets deleted, we need to transfer the current amount of readers in a global shared counter, so that the writer is always aware of all readers. Signed-off-by: Emanuele Giuseppe Esposito --- block/graph-lock.c | 216 +++++++++++++++++++++++++++++++++++++ block/meson.build | 1 + include/block/aio.h | 9 ++ include/block/block_int.h | 1 + include/block/graph-lock.h | 56 ++++++++++ 5 files changed, 283 insertions(+) create mode 100644 block/graph-lock.c create mode 100644 include/block/graph-lock.h diff --git a/block/graph-lock.c b/block/graph-lock.c new file mode 100644 index 0000000000..a2904ff6d8 --- /dev/null +++ b/block/graph-lock.c @@ -0,0 +1,216 @@ +/* + * CPU thread main loop - common bits for user and system mode emulation + * + * Copyright (c) 2003-2005 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "block/graph-lock.h" +#include "block/block.h" +#include "block/block_int.h" + +/* Protects the list of aiocontext and global_reader_count */ +static QemuMutex aio_context_list_lock; + +/* Written under aio_context_list_lock, read with atomic operations. */ +static int has_writer; + +/* + * A reader coroutine could move from an AioContext to another. + * If this happens, there is no problem from the point of view of + * counters. The problem is when the original AioContext where it + * took the rdlock gets deleted. We can't lose the counter of + * readers that are still running, so transfer it to this + * global variable. + * Protected by aio_context_list_lock. + */ +static uint32_t global_reader_count; + +/* Queue of readers waiting for the writer to finish */ +static CoQueue exclusive_resume; + +/* + * List of AioContext. This list ensures that each AioContext + * can safely modify only its own counter, avoid reading/writing + * others and thus improving performances by avoidind cacheline bounces. + */ +static QTAILQ_HEAD(, AioContext) aio_context_list = + QTAILQ_HEAD_INITIALIZER(aio_context_list); + +static void __attribute__((__constructor__)) bdrv_init_graph_lock(void) +{ + qemu_mutex_init(&aio_context_list_lock); + qemu_co_queue_init(&exclusive_resume); +} + +void register_aiocontext(AioContext *ctx) +{ + QEMU_LOCK_GUARD(&aio_context_list_lock); + assert(ctx->reader_count == 0); + QTAILQ_INSERT_TAIL(&aio_context_list, ctx, next_aio); +} + +void unregister_aiocontext(AioContext *ctx) +{ + QEMU_LOCK_GUARD(&aio_context_list_lock); + global_reader_count += ctx->reader_count; + QTAILQ_REMOVE(&aio_context_list, ctx, next_aio); +} + +static uint32_t reader_count(void) +{ + AioContext *ctx; + uint32_t rd; + + QEMU_LOCK_GUARD(&aio_context_list_lock); + + /* rd can temporarly be negative, but the will *always* >= 0 */ + rd = global_reader_count; + QTAILQ_FOREACH(ctx, &aio_context_list, next_aio) { + rd += qatomic_read(&ctx->reader_count); + } + + /* shouldn't overflow unless there are 2^31 readers */ + assert((int32_t)rd >= 0); + return rd; +} + +/* + * Start an exclusive write operation. + * Must only be called from outside bdrv_graph_co_rdlock. + */ +void bdrv_graph_wrlock(void) +{ + GLOBAL_STATE_CODE(); + assert(!has_writer); + + qatomic_set(&has_writer, 1); + /* make sure all readers read has_writer = 1 */ + smp_mb(); + + /* + * reader_count == 0: this means writer will read has_reader as 1 + * reader_count >= 1: we don't know if writer read has_writer == 0 or 1, + * but we need to wait. + * Wait by allowing other coroutine (and possible readers) to continue. + */ + AIO_WAIT_WHILE(qemu_get_aio_context(), reader_count() >= 1); +} + +/* Finish an exclusive write operation. */ +void bdrv_graph_wrunlock(void) +{ + GLOBAL_STATE_CODE(); + QEMU_LOCK_GUARD(&aio_context_list_lock); + assert(has_writer); + + /* + * No need for memory barriers, this works in pair with + * the slow path of rdlock() and both take the lock. + */ + qatomic_store_release(&has_writer, 0); + + /* Wake up all coroutine that are waiting to read the graph */ + qemu_co_queue_restart_all_lockable(&exclusive_resume, + &aio_context_list_lock); +} + +/* Wait for exclusive write to finish, and begin reading graph. */ +void coroutine_fn bdrv_graph_co_rdlock(void) +{ + AioContext *aiocontext; + aiocontext = qemu_get_current_aio_context(); + + for (;;) { + qatomic_set(&aiocontext->reader_count, + aiocontext->reader_count + 1); + /* make sure writer sees reader_count */ + smp_mb(); + + /* + * has_writer == 0: this means writer will read reader_count as >= 1 + * has_writer == 1: we don't know if writer read reader_count == 0 + * or > 0, but we need to wait anyways because + * it will write. + */ + if (!qatomic_read(&has_writer)) { + break; + } + + /* + * Synchronize access with reader_count() in bdrv_graph_wrlock(). + * Case 1: + * If this critical section gets executed first, reader_count will + * decrease and the reader will go to sleep. + * Then the writer will read reader_count that does not take into + * account this reader, and if there's no other reader it will + * enter the write section. + * Case 2: + * If reader_count() critical section gets executed first, + * then writer will read reader_count >= 1. + * It will wait in AIO_WAIT_WHILE(), but once it releases the lock + * we will enter this critical section and call aio_wait_kick(). + */ + WITH_QEMU_LOCK_GUARD(&aio_context_list_lock) { + /* + * Additional check when we use the above lock to synchronize + * with bdrv_graph_wrunlock(). + * Case 1: + * If this gets executed first, has_writer is still 1, so we reduce + * reader_count and go to sleep. + * Then the writer will set has_writer to 0 and wake up all readers, + * us included. + * Case 2: + * If bdrv_graph_wrunlock() critical section gets executed first, + * then it will set has_writer to 0 and wake up all other readers. + * Then we execute this critical section, and therefore must check + * again for has_writer, otherwise we sleep without any writer + * actually running. + */ + if (!qatomic_read(&has_writer)) { + return; + } + + /* slow path where reader sleeps */ + aiocontext->reader_count--; + aio_wait_kick(); + qemu_co_queue_wait(&exclusive_resume, &aio_context_list_lock); + } + } +} + +/* Mark bs as not reading anymore, and release pending exclusive ops. */ +void coroutine_fn bdrv_graph_co_rdunlock(void) +{ + AioContext *aiocontext; + aiocontext = qemu_get_current_aio_context(); + + qatomic_store_release(&aiocontext->reader_count, + aiocontext->reader_count - 1); + /* make sure writer sees reader_count */ + smp_mb(); + + /* + * has_writer == 0: this means reader will read reader_count decreased + * has_writer == 1: we don't know if writer read reader_count old or + * new. Therefore, kick again so on next iteration + * writer will for sure read the updated value. + */ + if (qatomic_read(&has_writer)) { + aio_wait_kick(); + } +} diff --git a/block/meson.build b/block/meson.build index e42bcb58d5..32ecf5c864 100644 --- a/block/meson.build +++ b/block/meson.build @@ -10,6 +10,7 @@ block_ss.add(files( 'blkverify.c', 'block-backend.c', 'block-copy.c', + 'graph-lock.c', 'commit.c', 'copy-on-read.c', 'preallocate.c', diff --git a/include/block/aio.h b/include/block/aio.h index 5634173b12..cb7d1f95cc 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -127,6 +127,15 @@ struct AioContext { /* Used by AioContext users to protect from multi-threaded access. */ QemuRecMutex lock; + /* How many readers in this AioContext are currently reading the graph. */ + uint32_t reader_count; + + /* + * List of AioContext kept in graph-lock.c + * Protected by aio_context_list_lock + */ + QTAILQ_ENTRY(AioContext) next_aio; + /* The list of registered AIO handlers. Protected by ctx->list_lock. */ AioHandlerList aio_handlers; diff --git a/include/block/block_int.h b/include/block/block_int.h index 7d50b6bbd1..b35b0138ed 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -26,6 +26,7 @@ #include "block_int-global-state.h" #include "block_int-io.h" +#include "block/graph-lock.h" /* DO NOT ADD ANYTHING IN HERE. USE ONE OF THE HEADERS INCLUDED ABOVE */ diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h new file mode 100644 index 0000000000..f171ba0527 --- /dev/null +++ b/include/block/graph-lock.h @@ -0,0 +1,56 @@ +#ifndef BLOCK_LOCK_H +#define BLOCK_LOCK_H + +#include "qemu/osdep.h" + +/* + * register_aiocontext: + * Add AioContext @ctx to the list of AioContext. + * This list is used to obtain the total number of readers + * currently running the graph. + */ +void register_aiocontext(AioContext *ctx); + +/* + * unregister_aiocontext: + * Removes AioContext @ctx to the list of AioContext. + */ +void unregister_aiocontext(AioContext *ctx); + +/* + * bdrv_graph_wrlock: + * Modify the graph. Nobody else is allowed to access the graph. + * Set global has_writer to 1, so that the next readers will wait + * that writer is done in a coroutine queue. + * Then keep track of the running readers by counting what is the total + * amount of readers (sum of all aiocontext readers), and wait until + * they all finish with AIO_WAIT_WHILE. + */ +void bdrv_graph_wrlock(void); + +/* + * bdrv_graph_wrunlock: + * Write finished, reset global has_writer to 0 and restart + * all readers that are waiting. + */ +void bdrv_graph_wrunlock(void); + +/* + * bdrv_graph_co_rdlock: + * Read the bs graph. Increases the reader counter of the current aiocontext, + * and if has_writer is set, it means that the writer is modifying + * the graph, therefore wait in a coroutine queue. + * The writer will then wake this coroutine once it is done. + */ +void coroutine_fn bdrv_graph_co_rdlock(void); + +/* + * bdrv_graph_rdunlock: + * Read terminated, decrease the count of readers in the current aiocontext. + * If the writer is waiting for reads to finish (has_writer == 1), signal + * the writer that we are done via aio_wait_kick() to let it continue. + */ +void coroutine_fn bdrv_graph_co_rdunlock(void); + +#endif /* BLOCK_LOCK_H */ + From patchwork Tue Apr 26 08:51:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 1622256 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=FJA4tQyZ; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KnbPB2rvWz9s75 for ; Tue, 26 Apr 2022 18:57:34 +1000 (AEST) Received: from localhost ([::1]:38022 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1njH0m-00060l-CH for incoming@patchwork.ozlabs.org; Tue, 26 Apr 2022 04:57:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43434) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGv5-0006xQ-Cf for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:39 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:37802) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGv3-0000el-JW for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1650963097; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dDs6u8MKFRfFKRAxcoyD1ePLpJCy0KVNZ2hTII/yAlA=; b=FJA4tQyZhRyhEjcwNoZSpIkooOkLanbPc/CWWpA6C7dEL8Q4MnhxeobaXvQoymINNSH8l+ vthyt6gW3DpfhEDe4HCD6onBnKbxkIQrLy/h2QLgS/KtovsB6SX3PP0dCKMa43HNF0Burj hlUeWLPmsLTjuLOjsCrmoSnMsxyR/SU= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-270-6sanNp-cNa2HM243q1Un_A-1; Tue, 26 Apr 2022 04:51:32 -0400 X-MC-Unique: 6sanNp-cNa2HM243q1Un_A-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 27416185A7A4; Tue, 26 Apr 2022 08:51:21 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id C71C24047D3B; Tue, 26 Apr 2022 08:51:18 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [RFC PATCH v2 4/8] async: register/unregister aiocontext in graph lock list Date: Tue, 26 Apr 2022 04:51:10 -0400 Message-Id: <20220426085114.199647-5-eesposit@redhat.com> In-Reply-To: <20220426085114.199647-1-eesposit@redhat.com> References: <20220426085114.199647-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Vladimir Sementsov-Ogievskiy , Emanuele Giuseppe Esposito , qemu-devel@nongnu.org, Hanna Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Add/remove the AioContext in aio_context_list in graph-lock.c only when it is being effectively created/destroyed. Signed-off-by: Emanuele Giuseppe Esposito --- util/async.c | 4 ++++ util/meson.build | 1 + 2 files changed, 5 insertions(+) diff --git a/util/async.c b/util/async.c index 2ea1172f3e..3a73f83910 100644 --- a/util/async.c +++ b/util/async.c @@ -27,6 +27,7 @@ #include "qapi/error.h" #include "block/aio.h" #include "block/thread-pool.h" +#include "block/graph-lock.h" #include "qemu/main-loop.h" #include "qemu/atomic.h" #include "qemu/rcu_queue.h" @@ -368,6 +369,7 @@ aio_ctx_finalize(GSource *source) qemu_rec_mutex_destroy(&ctx->lock); qemu_lockcnt_destroy(&ctx->list_lock); timerlistgroup_deinit(&ctx->tlg); + unregister_aiocontext(ctx); aio_context_destroy(ctx); } @@ -563,6 +565,8 @@ AioContext *aio_context_new(Error **errp) ctx->aio_max_batch = 0; + register_aiocontext(ctx); + return ctx; fail: g_source_destroy(&ctx->source); diff --git a/util/meson.build b/util/meson.build index 3736988b9f..c85d8695de 100644 --- a/util/meson.build +++ b/util/meson.build @@ -64,6 +64,7 @@ endif if have_block util_ss.add(files('aiocb.c', 'async.c', 'aio-wait.c')) + util_ss.add(files('../block/graph-lock.c')) util_ss.add(files('base64.c')) util_ss.add(files('buffer.c')) util_ss.add(files('bufferiszero.c')) From patchwork Tue Apr 26 08:51:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 1622259 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=dJ8PE/F5; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Knbb35GCjz9s75 for ; Tue, 26 Apr 2022 19:06:07 +1000 (AEST) Received: from localhost ([::1]:45832 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1njH93-0002zG-KP for incoming@patchwork.ozlabs.org; Tue, 26 Apr 2022 05:06:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43586) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGvO-0007PZ-JV for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:58 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:50803) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGvM-0000h2-Tn for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:58 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1650963116; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9tR9EQyveeV7BWJ+cvY0bFphwMHnUtQXmhjsqqmIvKo=; b=dJ8PE/F5s8ZJoW2d0Oj1oFCzG1R1IUU9zscmOZ6a54OX8XSc9NR7CJ0wL9Qo3PFJ90Yhk/ IVcx+ug4nH8nkH+pSL+T6/tPveVfnhJu0obXlNyxlhkOVxfJOBbIMY1rEA8zoy2S3/5Qk9 IV9BRBde8Ir1/+8CYyz7wJK9CqqG8CQ= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-353-EkViV2VcN5SDKKPdtDtkIw-1; Tue, 26 Apr 2022 04:51:53 -0400 X-MC-Unique: EkViV2VcN5SDKKPdtDtkIw-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id AC61A83395E; Tue, 26 Apr 2022 08:51:22 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id ED46E40D2969; Tue, 26 Apr 2022 08:51:20 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [RFC PATCH v2 5/8] block.c: wrlock in bdrv_replace_child_noperm Date: Tue, 26 Apr 2022 04:51:11 -0400 Message-Id: <20220426085114.199647-6-eesposit@redhat.com> In-Reply-To: <20220426085114.199647-1-eesposit@redhat.com> References: <20220426085114.199647-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Vladimir Sementsov-Ogievskiy , Emanuele Giuseppe Esposito , qemu-devel@nongnu.org, Hanna Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The only problem here is ->attach and ->detach callbacks could call bdrv_{un}apply_subtree_drain(), which itself will use a rdlock to navigate through all nodes. To avoid deadlocks, take the lock only outside the drains, and if we need to both attach and detach, do it in a single critical section. Therefore change ->attach and ->detach to return true if they are modifying the lock, so that we don't take it twice or release temporarly. Signed-off-by: Emanuele Giuseppe Esposito --- block.c | 31 +++++++++++++++++++++++++++---- block/block-backend.c | 6 ++++-- include/block/block_int-common.h | 8 ++++++-- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/block.c b/block.c index b2eb679abb..6cd87e8dd3 100644 --- a/block.c +++ b/block.c @@ -1434,21 +1434,26 @@ static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format, *child_flags = flags; } -static void bdrv_child_cb_attach(BdrvChild *child) +static bool bdrv_child_cb_attach(BdrvChild *child) { BlockDriverState *bs = child->opaque; assert_bdrv_graph_writable(bs); QLIST_INSERT_HEAD(&bs->children, child, next); + /* Paired with bdrv_graph_wrlock() in bdrv_replace_child_noperm */ + bdrv_graph_wrunlock(); + if (child->role & BDRV_CHILD_COW) { bdrv_backing_attach(child); } bdrv_apply_subtree_drain(child, bs); + + return true; } -static void bdrv_child_cb_detach(BdrvChild *child) +static bool bdrv_child_cb_detach(BdrvChild *child) { BlockDriverState *bs = child->opaque; @@ -1458,8 +1463,13 @@ static void bdrv_child_cb_detach(BdrvChild *child) bdrv_unapply_subtree_drain(child, bs); + /* Paired with bdrv_graph_wrunlock() in bdrv_replace_child_noperm */ + bdrv_graph_wrlock(); + assert_bdrv_graph_writable(bs); QLIST_REMOVE(child, next); + + return true; } static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base, @@ -2842,6 +2852,7 @@ static void bdrv_replace_child_noperm(BdrvChild **childp, BlockDriverState *old_bs = child->bs; int new_bs_quiesce_counter; int drain_saldo; + bool locked = false; assert(!child->frozen); assert(old_bs != new_bs); @@ -2868,8 +2879,12 @@ static void bdrv_replace_child_noperm(BdrvChild **childp, * are already gone and we only end the drain sections that came from * elsewhere. */ if (child->klass->detach) { - child->klass->detach(child); + locked = child->klass->detach(child); + } + if (!locked) { + bdrv_graph_wrlock(); } + locked = true; assert_bdrv_graph_writable(old_bs); QLIST_REMOVE(child, next_parent); } @@ -2880,6 +2895,10 @@ static void bdrv_replace_child_noperm(BdrvChild **childp, } if (new_bs) { + if (!locked) { + bdrv_graph_wrlock(); + locked = true; + } assert_bdrv_graph_writable(new_bs); QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent); @@ -2896,10 +2915,14 @@ static void bdrv_replace_child_noperm(BdrvChild **childp, * drain sections coming from @child don't get an extra .drained_begin * callback. */ if (child->klass->attach) { - child->klass->attach(child); + locked = !(child->klass->attach(child)); } } + if (locked) { + bdrv_graph_wrunlock(); + } + /* * If the old child node was drained but the new one is not, allow * requests to come in only after the new node has been attached. diff --git a/block/block-backend.c b/block/block-backend.c index e0e1aff4b1..5dbd9fceae 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -282,7 +282,7 @@ static int blk_root_inactivate(BdrvChild *child) return 0; } -static void blk_root_attach(BdrvChild *child) +static bool blk_root_attach(BdrvChild *child) { BlockBackend *blk = child->opaque; BlockBackendAioNotifier *notifier; @@ -295,9 +295,10 @@ static void blk_root_attach(BdrvChild *child) notifier->detach_aio_context, notifier->opaque); } + return false; } -static void blk_root_detach(BdrvChild *child) +static bool blk_root_detach(BdrvChild *child) { BlockBackend *blk = child->opaque; BlockBackendAioNotifier *notifier; @@ -310,6 +311,7 @@ static void blk_root_detach(BdrvChild *child) notifier->detach_aio_context, notifier->opaque); } + return false; } static AioContext *blk_root_get_parent_aio_context(BdrvChild *c) diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 5a04c778e4..dd058c1fd8 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -857,8 +857,12 @@ struct BdrvChildClass { void (*activate)(BdrvChild *child, Error **errp); int (*inactivate)(BdrvChild *child); - void (*attach)(BdrvChild *child); - void (*detach)(BdrvChild *child); + /* + * Return true if the graph wrlock is taken/released, + * false if the wrlock state is not changed. + */ + bool (*attach)(BdrvChild *child); + bool (*detach)(BdrvChild *child); /* * Notifies the parent that the filename of its child has changed (e.g. From patchwork Tue Apr 26 08:51:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 1622254 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=PIqTR1gF; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KnbNk27cgz9s09 for ; Tue, 26 Apr 2022 18:57:08 +1000 (AEST) Received: from localhost ([::1]:35924 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1njH0L-0004ZW-7H for incoming@patchwork.ozlabs.org; Tue, 26 Apr 2022 04:57:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43542) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGvK-0007Hh-Mp for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:54 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:48214) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGvI-0000gX-SH for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1650963112; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=w+kdbW/UoUeuWtfuRNw/Xekk3y7L37wznJv37tJ3hKA=; b=PIqTR1gFx2nqgZQWyPWTh3M3hqhyNFYxUyu7MIfzJv0Swgiy6PXAQnuoNMcWmv/hMjj1hL ZCM6rhYYSiwP5CVjfibv/wQw1z8/SglmXdBtTFt3oG76/RBYE0JY7CdoeuudVdO38ua+Yf QbaiYVMJnfcAsUTU8KQ5qEgFC+sNJEQ= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-484-MHwtUeaGMrO_eQDlWi8j7g-1; Tue, 26 Apr 2022 04:51:46 -0400 X-MC-Unique: MHwtUeaGMrO_eQDlWi8j7g-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 28A9C3C10AC6; Tue, 26 Apr 2022 08:51:30 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 71717404D2C2; Tue, 26 Apr 2022 08:51:22 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [RFC PATCH v2 6/8] block: assert that graph read and writes are performed correctly Date: Tue, 26 Apr 2022 04:51:12 -0400 Message-Id: <20220426085114.199647-7-eesposit@redhat.com> In-Reply-To: <20220426085114.199647-1-eesposit@redhat.com> References: <20220426085114.199647-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Vladimir Sementsov-Ogievskiy , Emanuele Giuseppe Esposito , qemu-devel@nongnu.org, Hanna Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Remove the old assert_bdrv_graph_writable, and replace it with the new version using graph-lock API. See the function documentation for more information. Signed-off-by: Emanuele Giuseppe Esposito --- block.c | 8 ++++---- block/graph-lock.c | 11 +++++++++++ include/block/block_int-global-state.h | 17 ----------------- include/block/graph-lock.h | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/block.c b/block.c index 6cd87e8dd3..b427d632e1 100644 --- a/block.c +++ b/block.c @@ -1438,7 +1438,7 @@ static bool bdrv_child_cb_attach(BdrvChild *child) { BlockDriverState *bs = child->opaque; - assert_bdrv_graph_writable(bs); + assert_bdrv_graph_writable(); QLIST_INSERT_HEAD(&bs->children, child, next); /* Paired with bdrv_graph_wrlock() in bdrv_replace_child_noperm */ @@ -1466,7 +1466,7 @@ static bool bdrv_child_cb_detach(BdrvChild *child) /* Paired with bdrv_graph_wrunlock() in bdrv_replace_child_noperm */ bdrv_graph_wrlock(); - assert_bdrv_graph_writable(bs); + assert_bdrv_graph_writable(); QLIST_REMOVE(child, next); return true; @@ -2885,7 +2885,7 @@ static void bdrv_replace_child_noperm(BdrvChild **childp, bdrv_graph_wrlock(); } locked = true; - assert_bdrv_graph_writable(old_bs); + assert_bdrv_graph_writable(); QLIST_REMOVE(child, next_parent); } @@ -2899,7 +2899,7 @@ static void bdrv_replace_child_noperm(BdrvChild **childp, bdrv_graph_wrlock(); locked = true; } - assert_bdrv_graph_writable(new_bs); + assert_bdrv_graph_writable(); QLIST_INSERT_HEAD(&new_bs->parents, child, next_parent); /* diff --git a/block/graph-lock.c b/block/graph-lock.c index a2904ff6d8..0edae31545 100644 --- a/block/graph-lock.c +++ b/block/graph-lock.c @@ -214,3 +214,14 @@ void coroutine_fn bdrv_graph_co_rdunlock(void) aio_wait_kick(); } } + +void assert_bdrv_graph_readable(void) +{ + assert(qemu_in_main_thread() || reader_count()); +} + +void assert_bdrv_graph_writable(void) +{ + assert(qemu_in_main_thread()); + assert(qatomic_read(&has_writer)); +} diff --git a/include/block/block_int-global-state.h b/include/block/block_int-global-state.h index 0f21b0570b..5078d6a6ea 100644 --- a/include/block/block_int-global-state.h +++ b/include/block/block_int-global-state.h @@ -309,21 +309,4 @@ void bdrv_remove_aio_context_notifier(BlockDriverState *bs, */ void bdrv_drain_all_end_quiesce(BlockDriverState *bs); -/** - * Make sure that the function is running under both drain and BQL. - * The latter protects from concurrent writings - * from the GS API, while the former prevents concurrent reads - * from I/O. - */ -static inline void assert_bdrv_graph_writable(BlockDriverState *bs) -{ - /* - * TODO: this function is incomplete. Because the users of this - * assert lack the necessary drains, check only for BQL. - * Once the necessary drains are added, - * assert also for qatomic_read(&bs->quiesce_counter) > 0 - */ - assert(qemu_in_main_thread()); -} - #endif /* BLOCK_INT_GLOBAL_STATE */ diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h index f171ba0527..2211d41286 100644 --- a/include/block/graph-lock.h +++ b/include/block/graph-lock.h @@ -52,5 +52,20 @@ void coroutine_fn bdrv_graph_co_rdlock(void); */ void coroutine_fn bdrv_graph_co_rdunlock(void); +/* + * assert_bdrv_graph_readable: + * Make sure that the reader is either the main loop, + * or there is at least a reader helding the rdlock. + * In this way an incoming writer is aware of the read and waits. + */ +void assert_bdrv_graph_readable(void); + +/* + * assert_bdrv_graph_writable: + * Make sure that the writer is the main loop and has set @has_writer, + * so that incoming readers will pause. + */ +void assert_bdrv_graph_writable(void); + #endif /* BLOCK_LOCK_H */ From patchwork Tue Apr 26 08:51:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 1622251 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=VfZjZGGu; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KnbHy2Rrwz9s09 for ; Tue, 26 Apr 2022 18:53:02 +1000 (AEST) Received: from localhost ([::1]:55432 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1njGwO-00070d-42 for incoming@patchwork.ozlabs.org; Tue, 26 Apr 2022 04:53:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43390) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGv3-0006w7-KP for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:37 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:24541) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGv2-0000eW-5K for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1650963094; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=N+wccC5A53d2EmDYvrg5hZcFAZySjf7nYFphAqdnRD0=; b=VfZjZGGu9mKmyHUTzwsnsl5DwQsbi63wiTFS+WcugneQYv3+E97gUlxlinA9ALqySc0qXo 1UiM7G8yskNTRy5Pi69ArI0vEn3clRXY4GMJPshLaypxE21Bfg4zc5kfbB8DwnhLGHEalO dJyaFy8fsVqa7CyIs9WFwSIRtOzkf6c= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-591-QZznUMJJMrWPuiuwEh8Yew-1; Tue, 26 Apr 2022 04:51:32 -0400 X-MC-Unique: QZznUMJJMrWPuiuwEh8Yew-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 30FB73C10ACB; Tue, 26 Apr 2022 08:51:31 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0750340E80E2; Tue, 26 Apr 2022 08:51:23 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [RFC PATCH v2 7/8] graph-lock: implement WITH_GRAPH_RDLOCK_GUARD and GRAPH_RDLOCK_GUARD macros Date: Tue, 26 Apr 2022 04:51:13 -0400 Message-Id: <20220426085114.199647-8-eesposit@redhat.com> In-Reply-To: <20220426085114.199647-1-eesposit@redhat.com> References: <20220426085114.199647-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 Received-SPF: pass client-ip=170.10.129.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Vladimir Sementsov-Ogievskiy , Emanuele Giuseppe Esposito , qemu-devel@nongnu.org, Hanna Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Similar to the implementation in lockable.h, implement macros to automatically take and release the rdlock. Create the empty GraphLockable struct only to use it as a type for G_DEFINE_AUTOPTR_CLEANUP_FUNC. Signed-off-by: Emanuele Giuseppe Esposito --- include/block/graph-lock.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h index 2211d41286..8d8a6513f1 100644 --- a/include/block/graph-lock.h +++ b/include/block/graph-lock.h @@ -67,5 +67,35 @@ void assert_bdrv_graph_readable(void); */ void assert_bdrv_graph_writable(void); +typedef struct GraphLockable { } GraphLockable; + +#define GML_OBJ_() (&(GraphLockable) { }) + +static inline GraphLockable *graph_lockable_auto_lock(GraphLockable *x) +{ + bdrv_graph_co_rdlock(); + return x; +} + +static inline void graph_lockable_auto_unlock(GraphLockable *x) +{ + bdrv_graph_co_rdunlock(); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GraphLockable, graph_lockable_auto_unlock) + +#define WITH_GRAPH_RDLOCK_GUARD_(var) \ + for (g_autoptr(GraphLockable) var = graph_lockable_auto_lock(GML_OBJ_()); \ + var; \ + graph_lockable_auto_unlock(var), var = NULL) + +#define WITH_GRAPH_RDLOCK_GUARD() \ + WITH_GRAPH_RDLOCK_GUARD_(glue(graph_lockable_auto, __COUNTER__)) + +#define GRAPH_RDLOCK_GUARD(x) \ + g_autoptr(GraphLockable) \ + glue(graph_lockable_auto, __COUNTER__) G_GNUC_UNUSED = \ + graph_lockable_auto_lock(GML_OBJ_()) + #endif /* BLOCK_LOCK_H */ From patchwork Tue Apr 26 08:51:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Emanuele Giuseppe Esposito X-Patchwork-Id: 1622260 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Unkg/6LA; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Knbbs2kfhz9s75 for ; Tue, 26 Apr 2022 19:06:49 +1000 (AEST) Received: from localhost ([::1]:46588 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1njH9j-0003Tq-Ai for incoming@patchwork.ozlabs.org; Tue, 26 Apr 2022 05:06:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43502) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGvF-0007DP-LO for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:53905) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1njGvE-0000gI-5i for qemu-devel@nongnu.org; Tue, 26 Apr 2022 04:51:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1650963107; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=t4QLXWHSEH+WUuRo1EdjW0OdX0UvC4rVVzDAZajucAM=; b=Unkg/6LAj0jaFNvjFnJejmsavOj/q7BH2yFiZAlHlY06SgmlduoHfNML57xib55xn0cVGU Yl7LRO4nRyRiDByJNF6Nm9R8XqJxwGiyjIFL8AQMq2XFlETD1X6SWwWU4kuXI+yqomv+ly PgFrc+6AMSpobGC7JOUO92zkRHo1fMk= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-294-wRp9yW_HMzWMkAT_eL3c1w-1; Tue, 26 Apr 2022 04:51:43 -0400 X-MC-Unique: wRp9yW_HMzWMkAT_eL3c1w-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 362CF29ABA05; Tue, 26 Apr 2022 08:51:32 +0000 (UTC) Received: from virtlab701.virt.lab.eng.bos.redhat.com (virtlab701.virt.lab.eng.bos.redhat.com [10.19.152.228]) by smtp.corp.redhat.com (Postfix) with ESMTP id 11C5640E8100; Tue, 26 Apr 2022 08:51:25 +0000 (UTC) From: Emanuele Giuseppe Esposito To: qemu-block@nongnu.org Subject: [RFC PATCH v2 8/8] mirror: protect drains in coroutine with rdlock Date: Tue, 26 Apr 2022 04:51:14 -0400 Message-Id: <20220426085114.199647-9-eesposit@redhat.com> In-Reply-To: <20220426085114.199647-1-eesposit@redhat.com> References: <20220426085114.199647-1-eesposit@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 Received-SPF: pass client-ip=170.10.133.124; envelope-from=eesposit@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -28 X-Spam_score: -2.9 X-Spam_bar: -- X-Spam_report: (-2.9 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.082, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Fam Zheng , Vladimir Sementsov-Ogievskiy , Emanuele Giuseppe Esposito , qemu-devel@nongnu.org, Hanna Reitz , Stefan Hajnoczi , Paolo Bonzini , John Snow Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Drain performed in coroutine schedules a bh in the main loop. However, drain itself still is a read, and we need to signal the writer that we are going through the graph. Signed-off-by: Emanuele Giuseppe Esposito --- block/mirror.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/block/mirror.c b/block/mirror.c index ce6bc58d1f..de86729f9b 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1065,10 +1065,14 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) trace_mirror_before_drain(s, cnt); s->in_drain = true; + bdrv_graph_co_rdlock(); bdrv_drained_begin(bs); + bdrv_graph_co_rdunlock(); cnt = bdrv_get_dirty_count(s->dirty_bitmap); if (cnt > 0 || mirror_flush(s) < 0) { + bdrv_graph_co_rdlock(); bdrv_drained_end(bs); + bdrv_graph_co_rdunlock(); s->in_drain = false; continue; } @@ -1110,7 +1114,9 @@ immediate_exit: if (need_drain) { s->in_drain = true; + bdrv_graph_co_rdlock(); bdrv_drained_begin(bs); + bdrv_graph_co_rdunlock(); } return ret;