From nobody Wed Nov 27 13:39:26 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1698422096; cv=none; d=zohomail.com; s=zohoarc; b=gfNl7fbEy23NKdglt1luPjuMmEgr5f8snyx36PXQFQYDmWUmkkoF9Ylb/pNGROWarEbXKXjS6kkU/XRDRMGCiWRniWLmxu8GZWMpkVd9m10Ggu16HIu5uooV03RGaOh6FENuUNHZBfAAlWOwpgCoaZqT1WIqDt6+C6O78HMcpOE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1698422096; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=cMnf6vzuysy5ioqXVCVbl7/7Pel46hF1j1R6afga9Qw=; b=kyNuHUGbUy4vSunNEWO04D8qF/uGd1sgFOTeTk9/iR1kpmhZLOprNETeGTwSFbW3JYFJGqG2BUxzxdG8S1KSIYEMEhY6Z0R3so1a6Dm6TyQOyhRnqhhXvdrCzED4VIKhYpYJpkNo1ittXY3Gl4IEI/NXg/ptEIhLTBz6qadgypA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1698422096309693.533538768808; Fri, 27 Oct 2023 08:54:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qwPA8-0003cd-MC; Fri, 27 Oct 2023 11:54:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qwP9m-0003Uc-3a for qemu-devel@nongnu.org; Fri, 27 Oct 2023 11:53:55 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qwP9i-0002d3-Jb for qemu-devel@nongnu.org; Fri, 27 Oct 2023 11:53:52 -0400 Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-678-IVkGc78HMay-NP3zeiHKhQ-1; Fri, 27 Oct 2023 11:53:48 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 9655D2800B43; Fri, 27 Oct 2023 15:53:48 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.39.194.78]) by smtp.corp.redhat.com (Postfix) with ESMTP id 699195027; Fri, 27 Oct 2023 15:53:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1698422030; 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=cMnf6vzuysy5ioqXVCVbl7/7Pel46hF1j1R6afga9Qw=; b=PxLATIKWn8bQZ69UVVjCla3xBS7p9289yLYGEAVp00UY1dDduhvabrOBcvAYaQnfbAIDsN ixwb96VUHxXdrfiDIh0Vlapiv5YYGzKF7K+PmTCghDkt0Fd1aRPsyV1pFasqj9kDV/AyCE hk/qrdk4+kvIYTo3vi39OTOyhR68d2g= X-MC-Unique: IVkGc78HMay-NP3zeiHKhQ-1 From: Kevin Wolf To: qemu-block@nongnu.org Cc: kwolf@redhat.com, stefanha@redhat.com, eesposit@redhat.com, eblake@redhat.com, pbonzini@redhat.com, vsementsov@yandex-team.ru, qemu-devel@nongnu.org Subject: [PATCH 05/24] block: Mark block_job_add_bdrv() GRAPH_WRLOCK Date: Fri, 27 Oct 2023 17:53:14 +0200 Message-ID: <20231027155333.420094-6-kwolf@redhat.com> In-Reply-To: <20231027155333.420094-1-kwolf@redhat.com> References: <20231027155333.420094-1-kwolf@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.5 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=kwolf@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 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: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1698422096616100004 Content-Type: text/plain; charset="utf-8" Instead of taking the writer lock internally, require callers to already hold it when calling block_job_add_bdrv(). These callers will typically already hold the graph lock once the locking work is completed, which means that they can't call functions that take it internally. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake --- include/block/blockjob.h | 5 +++-- include/block/blockjob_int.h | 9 +++++---- block/backup.c | 21 +++++++++++++++------ block/commit.c | 5 +++++ block/mirror.c | 5 +++++ block/stream.c | 4 ++++ blockjob.c | 8 +++++--- tests/unit/test-bdrv-drain.c | 3 +++ 8 files changed, 45 insertions(+), 15 deletions(-) diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 058b0c824c..059138aa27 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -138,8 +138,9 @@ BlockJob *block_job_get_locked(const char *id); * @job. This means that all operations will be blocked on @bs while * @job exists. */ -int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *= bs, - uint64_t perm, uint64_t shared_perm, Error **errp); +int GRAPH_WRLOCK +block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, + uint64_t perm, uint64_t shared_perm, Error **errp); =20 /** * block_job_remove_all_bdrv: diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h index 104824040c..e80bb5c33e 100644 --- a/include/block/blockjob_int.h +++ b/include/block/blockjob_int.h @@ -99,10 +99,11 @@ struct BlockJobDriver { * This function is not part of the public job interface; it should be * called from a wrapper that is specific to the job type. */ -void *block_job_create(const char *job_id, const BlockJobDriver *driver, - JobTxn *txn, BlockDriverState *bs, uint64_t perm, - uint64_t shared_perm, int64_t speed, int flags, - BlockCompletionFunc *cb, void *opaque, Error **errp= ); +void * GRAPH_UNLOCKED +block_job_create(const char *job_id, const BlockJobDriver *driver, + JobTxn *txn, BlockDriverState *bs, uint64_t perm, + uint64_t shared_perm, int64_t speed, int flags, + BlockCompletionFunc *cb, void *opaque, Error **errp); =20 /** * block_job_free: diff --git a/block/backup.c b/block/backup.c index 9a3c4bdc82..5bad7d116f 100644 --- a/block/backup.c +++ b/block/backup.c @@ -374,7 +374,6 @@ BlockJob *backup_job_create(const char *job_id, BlockDr= iverState *bs, assert(bs); assert(target); GLOBAL_STATE_CODE(); - GRAPH_RDLOCK_GUARD_MAINLOOP(); =20 /* QMP interface protects us from these cases */ assert(sync_mode !=3D MIRROR_SYNC_MODE_INCREMENTAL); @@ -385,31 +384,33 @@ BlockJob *backup_job_create(const char *job_id, Block= DriverState *bs, return NULL; } =20 + bdrv_graph_rdlock_main_loop(); if (!bdrv_is_inserted(bs)) { error_setg(errp, "Device is not inserted: %s", bdrv_get_device_name(bs)); - return NULL; + goto error_rdlock; } =20 if (!bdrv_is_inserted(target)) { error_setg(errp, "Device is not inserted: %s", bdrv_get_device_name(target)); - return NULL; + goto error_rdlock; } =20 if (compress && !bdrv_supports_compressed_writes(target)) { error_setg(errp, "Compression is not supported for this drive %s", bdrv_get_device_name(target)); - return NULL; + goto error_rdlock; } =20 if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) { - return NULL; + goto error_rdlock; } =20 if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) { - return NULL; + goto error_rdlock; } + bdrv_graph_rdunlock_main_loop(); =20 if (perf->max_workers < 1 || perf->max_workers > INT_MAX) { error_setg(errp, "max-workers must be between 1 and %d", INT_MAX); @@ -437,6 +438,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDr= iverState *bs, =20 len =3D bdrv_getlength(bs); if (len < 0) { + GRAPH_RDLOCK_GUARD_MAINLOOP(); error_setg_errno(errp, -len, "Unable to get length for '%s'", bdrv_get_device_or_node_name(bs)); goto error; @@ -444,6 +446,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDr= iverState *bs, =20 target_len =3D bdrv_getlength(target); if (target_len < 0) { + GRAPH_RDLOCK_GUARD_MAINLOOP(); error_setg_errno(errp, -target_len, "Unable to get length for '%s'= ", bdrv_get_device_or_node_name(bs)); goto error; @@ -493,8 +496,10 @@ BlockJob *backup_job_create(const char *job_id, BlockD= riverState *bs, block_copy_set_speed(bcs, speed); =20 /* Required permissions are taken by copy-before-write filter target */ + bdrv_graph_wrlock(target); block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL, &error_abort); + bdrv_graph_wrunlock(); =20 return &job->common; =20 @@ -507,4 +512,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDr= iverState *bs, } =20 return NULL; + +error_rdlock: + bdrv_graph_rdunlock_main_loop(); + return NULL; } diff --git a/block/commit.c b/block/commit.c index 43d1de7577..fc3ad79749 100644 --- a/block/commit.c +++ b/block/commit.c @@ -342,6 +342,7 @@ void commit_start(const char *job_id, BlockDriverState = *bs, */ iter_shared_perms =3D BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE; =20 + bdrv_graph_wrlock(top); for (iter =3D top; iter !=3D base; iter =3D bdrv_filter_or_cow_bs(iter= )) { if (iter =3D=3D filtered_base) { /* @@ -354,16 +355,20 @@ void commit_start(const char *job_id, BlockDriverStat= e *bs, ret =3D block_job_add_bdrv(&s->common, "intermediate node", iter, = 0, iter_shared_perms, errp); if (ret < 0) { + bdrv_graph_wrunlock(); goto fail; } } =20 if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) { + bdrv_graph_wrunlock(); goto fail; } s->chain_frozen =3D true; =20 ret =3D block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, = errp); + bdrv_graph_wrunlock(); + if (ret < 0) { goto fail; } diff --git a/block/mirror.c b/block/mirror.c index dcd88de2e3..b1d2a5268a 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1831,11 +1831,13 @@ static BlockJob *mirror_start_job( bdrv_disable_dirty_bitmap(s->dirty_bitmap); } =20 + bdrv_graph_wrlock(bs); ret =3D block_job_add_bdrv(&s->common, "source", bs, 0, BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ, errp); if (ret < 0) { + bdrv_graph_wrunlock(); goto fail; } =20 @@ -1880,14 +1882,17 @@ static BlockJob *mirror_start_job( ret =3D block_job_add_bdrv(&s->common, "intermediate node", it= er, 0, iter_shared_perms, errp); if (ret < 0) { + bdrv_graph_wrunlock(); goto fail; } } =20 if (bdrv_freeze_backing_chain(mirror_top_bs, target, errp) < 0) { + bdrv_graph_wrunlock(); goto fail; } } + bdrv_graph_wrunlock(); =20 QTAILQ_INIT(&s->ops_in_flight); =20 diff --git a/block/stream.c b/block/stream.c index b22d9c236b..51333e460b 100644 --- a/block/stream.c +++ b/block/stream.c @@ -352,8 +352,10 @@ void stream_start(const char *job_id, BlockDriverState= *bs, * already have our own plans. Also don't allow resize as the image si= ze is * queried only at the job start and then cached. */ + bdrv_graph_wrlock(bs); if (block_job_add_bdrv(&s->common, "active node", bs, 0, basic_flags | BLK_PERM_WRITE, errp)) { + bdrv_graph_wrunlock(); goto fail; } =20 @@ -373,9 +375,11 @@ void stream_start(const char *job_id, BlockDriverState= *bs, ret =3D block_job_add_bdrv(&s->common, "intermediate node", iter, = 0, basic_flags, errp); if (ret < 0) { + bdrv_graph_wrunlock(); goto fail; } } + bdrv_graph_wrunlock(); =20 s->base_overlay =3D base_overlay; s->above_base =3D above_base; diff --git a/blockjob.c b/blockjob.c index 48559fc154..910c4200e6 100644 --- a/blockjob.c +++ b/blockjob.c @@ -248,10 +248,8 @@ int block_job_add_bdrv(BlockJob *job, const char *name= , BlockDriverState *bs, } aio_context_acquire(ctx); } - bdrv_graph_wrlock(bs); c =3D bdrv_root_attach_child(bs, name, &child_job, 0, perm, shared_per= m, job, errp); - bdrv_graph_wrunlock(); if (need_context_ops) { aio_context_release(ctx); if (job->job.aio_context !=3D qemu_get_aio_context()) { @@ -489,7 +487,8 @@ void *block_job_create(const char *job_id, const BlockJ= obDriver *driver, BlockJob *job; int ret; GLOBAL_STATE_CODE(); - GRAPH_RDLOCK_GUARD_MAINLOOP(); + + bdrv_graph_wrlock(bs); =20 if (job_id =3D=3D NULL && !(flags & JOB_INTERNAL)) { job_id =3D bdrv_get_device_name(bs); @@ -498,6 +497,7 @@ void *block_job_create(const char *job_id, const BlockJ= obDriver *driver, job =3D job_create(job_id, &driver->job_driver, txn, bdrv_get_aio_cont= ext(bs), flags, cb, opaque, errp); if (job =3D=3D NULL) { + bdrv_graph_wrunlock(); return NULL; } =20 @@ -537,9 +537,11 @@ void *block_job_create(const char *job_id, const Block= JobDriver *driver, goto fail; } =20 + bdrv_graph_wrunlock(); return job; =20 fail: + bdrv_graph_wrunlock(); job_early_fail(&job->job); return NULL; } diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c index f67e9df01c..40d17b4c5a 100644 --- a/tests/unit/test-bdrv-drain.c +++ b/tests/unit/test-bdrv-drain.c @@ -794,7 +794,10 @@ static void test_blockjob_common_drain_node(enum drain= _type drain_type, 0, 0, NULL, NULL, &error_abort); tjob->bs =3D src; job =3D &tjob->common; + + bdrv_graph_wrlock(target); block_job_add_bdrv(job, "target", target, 0, BLK_PERM_ALL, &error_abor= t); + bdrv_graph_wrunlock(); =20 switch (result) { case TEST_JOB_SUCCESS: --=20 2.41.0