From nobody Wed Nov 27 13:34:37 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=1698422192; cv=none; d=zohomail.com; s=zohoarc; b=fB6iYbALOO3xodDXn94YvF2m38rAImoyWxQGpzQvyl9ztVv1fqwo53dY8JspcjpsmCc3sGFlTLtmLQ2IZci+a5I1bN9f/Fo8oeapMZPvQnUJ5wNpe7ZiiPUh4n7dUQJnga3BqJT0Ze/zvTTeoI/IzZlVpp7a18orRDF7igt9dTs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1698422192; 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=QhCGd7aIY/rWmKNQ/w4D3FgYNXq0m2YL5srNvTbLF7I=; b=Gh9oMjXHM5ja9UxWg588xkhLQwI3s6FoAjC+8Dv5awHPTYWz8n0nH0CXRApy2xSoN24g/zUpGBtV5lpX5+0ObhTwsgbof23oPq0aQYG4DpOyAvCoouAFn0Tj6pw32lvEtm3kt0EUKzSNNKHD5VyGYJGsy9RFvAD87/cSB6GyJ/A= 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 1698422192167279.83297887523327; Fri, 27 Oct 2023 08:56:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qwPAL-0004po-CS; Fri, 27 Oct 2023 11:54:29 -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 1qwPAE-00047N-EJ for qemu-devel@nongnu.org; Fri, 27 Oct 2023 11:54:22 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qwPA9-0002yj-Uc for qemu-devel@nongnu.org; Fri, 27 Oct 2023 11:54:21 -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-491-UwXSxYydNnKI2pl12JzkVw-1; Fri, 27 Oct 2023 11:54:11 -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 5E47E3C23646; Fri, 27 Oct 2023 15:54:11 +0000 (UTC) Received: from merkur.fritz.box (unknown [10.39.194.78]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3066A5027; Fri, 27 Oct 2023 15:54:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1698422056; 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=QhCGd7aIY/rWmKNQ/w4D3FgYNXq0m2YL5srNvTbLF7I=; b=DYpT3+1vy0Pes5SQyn8JBosmWecmlfJkF+WYcfvAIORFuVfpPQDzBobxavY3b5klbPNd2F 7N2/vLs++HEid5CQxZ2fkQtuUTGp6nyte+EPP47lXcgOf19GbEIhSmxvXTLRItYG5E3UKF HcNcOEr75qkcTiCflVEqOHOLFeQGPok= X-MC-Unique: UwXSxYydNnKI2pl12JzkVw-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 21/24] qcow2: Take locks for accessing bs->file Date: Fri, 27 Oct 2023 17:53:30 +0200 Message-ID: <20231027155333.420094-22-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.129.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_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 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: , 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: 1698422194318100007 Content-Type: text/plain; charset="utf-8" This updates the qcow2 code to add GRAPH_RDLOCK annotations for all places that read bs->file. Signed-off-by: Kevin Wolf Reviewed-by: Eric Blake --- block/qcow2.h | 48 ++++++++++++++++++++++++++----------------- block/qcow2-bitmap.c | 14 +++++++------ block/qcow2-cluster.c | 25 +++++++++++----------- block/qcow2.c | 13 ++++++++---- 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/block/qcow2.h b/block/qcow2.h index 948335979f..a9e3481c6e 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -641,7 +641,7 @@ static inline void set_l2_bitmap(BDRVQcow2State *s, uin= t64_t *l2_slice, l2_slice[idx + 1] =3D cpu_to_be64(bitmap); } =20 -static inline bool has_data_file(BlockDriverState *bs) +static inline bool GRAPH_RDLOCK has_data_file(BlockDriverState *bs) { BDRVQcow2State *s =3D bs->opaque; return (s->data_file !=3D bs->file); @@ -709,8 +709,8 @@ static inline int64_t qcow2_vm_state_offset(BDRVQcow2St= ate *s) return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits); } =20 -static inline QCow2ClusterType qcow2_get_cluster_type(BlockDriverState *bs, - uint64_t l2_entry) +static inline QCow2ClusterType GRAPH_RDLOCK +qcow2_get_cluster_type(BlockDriverState *bs, uint64_t l2_entry) { BDRVQcow2State *s =3D bs->opaque; =20 @@ -743,7 +743,7 @@ static inline QCow2ClusterType qcow2_get_cluster_type(B= lockDriverState *bs, * (this checks the whole entry and bitmap, not only the bits related * to subcluster @sc_index). */ -static inline +static inline GRAPH_RDLOCK QCow2SubclusterType qcow2_get_subcluster_type(BlockDriverState *bs, uint64_t l2_entry, uint64_t l2_bitmap, @@ -834,9 +834,9 @@ int64_t qcow2_refcount_metadata_size(int64_t clusters, = size_t cluster_size, int refcount_order, bool generous_inc= rease, uint64_t *refblock_count); =20 -int qcow2_mark_dirty(BlockDriverState *bs); -int qcow2_mark_corrupt(BlockDriverState *bs); -int qcow2_update_header(BlockDriverState *bs); +int GRAPH_RDLOCK qcow2_mark_dirty(BlockDriverState *bs); +int GRAPH_RDLOCK qcow2_mark_corrupt(BlockDriverState *bs); +int GRAPH_RDLOCK qcow2_update_header(BlockDriverState *bs); =20 void GRAPH_RDLOCK qcow2_signal_corruption(BlockDriverState *bs, bool fatal, int64_t offset, @@ -890,10 +890,11 @@ int GRAPH_RDLOCK qcow2_write_caches(BlockDriverState = *bs); int coroutine_fn qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResu= lt *res, BdrvCheckMode fix); =20 -void qcow2_process_discards(BlockDriverState *bs, int ret); +void GRAPH_RDLOCK qcow2_process_discards(BlockDriverState *bs, int ret); =20 -int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t of= fset, - int64_t size); +int GRAPH_RDLOCK +qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset, + int64_t size); int GRAPH_RDLOCK qcow2_pre_write_overlap_check(BlockDriverState *bs, int ign, int64_t offse= t, int64_t size, bool data_file); @@ -939,8 +940,9 @@ qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t = offset, int coroutine_fn GRAPH_RDLOCK qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offse= t, int compressed_size, uint64_t *host_= offset); -void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_ent= ry, - uint64_t *coffset, int *csize); +void GRAPH_RDLOCK +qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry, + uint64_t *coffset, int *csize); =20 int coroutine_fn GRAPH_RDLOCK qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m); @@ -993,8 +995,9 @@ qcow2_check_fix_snapshot_table(BlockDriverState *bs, Bd= rvCheckResult *result, BdrvCheckMode fix); =20 /* qcow2-cache.c functions */ -Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables, - unsigned table_size); +Qcow2Cache * GRAPH_RDLOCK +qcow2_cache_create(BlockDriverState *bs, int num_tables, unsigned table_si= ze); + int qcow2_cache_destroy(Qcow2Cache *c); =20 void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table); @@ -1020,17 +1023,24 @@ void *qcow2_cache_is_table_offset(Qcow2Cache *c, ui= nt64_t offset); void qcow2_cache_discard(Qcow2Cache *c, void *table); =20 /* qcow2-bitmap.c functions */ -int coroutine_fn +int coroutine_fn GRAPH_RDLOCK qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res, void **refcount_table, int64_t *refcount_table_size); + bool coroutine_fn GRAPH_RDLOCK -qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated, Error= **errp); -bool qcow2_get_bitmap_info_list(BlockDriverState *bs, - Qcow2BitmapInfoList **info_list, Error **e= rrp); +qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated, + Error **errp); + +bool GRAPH_RDLOCK +qcow2_get_bitmap_info_list(BlockDriverState *bs, + Qcow2BitmapInfoList **info_list, Error **errp); + int GRAPH_RDLOCK qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **err= p); int GRAPH_RDLOCK qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **err= p); -int coroutine_fn qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error = **errp); + +int coroutine_fn GRAPH_RDLOCK +qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp); =20 bool GRAPH_RDLOCK qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, bool release_st= ored, diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 3058309c47..0e567ed588 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -105,7 +105,7 @@ static inline bool can_write(BlockDriverState *bs) return !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIV= E); } =20 -static int update_header_sync(BlockDriverState *bs) +static int GRAPH_RDLOCK update_header_sync(BlockDriverState *bs) { int ret; =20 @@ -221,8 +221,9 @@ clear_bitmap_table(BlockDriverState *bs, uint64_t *bitm= ap_table, } } =20 -static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb, - uint64_t **bitmap_table) +static int GRAPH_RDLOCK +bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb, + uint64_t **bitmap_table) { int ret; BDRVQcow2State *s =3D bs->opaque; @@ -551,8 +552,9 @@ static uint32_t bitmap_list_count(Qcow2BitmapList *bm_l= ist) * Get bitmap list from qcow2 image. Actually reads bitmap directory, * checks it and convert to bitmap list. */ -static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, uint64_t of= fset, - uint64_t size, Error **errp) +static Qcow2BitmapList * GRAPH_RDLOCK +bitmap_list_load(BlockDriverState *bs, uint64_t offset, uint64_t size, + Error **errp) { int ret; BDRVQcow2State *s =3D bs->opaque; @@ -961,7 +963,7 @@ static void set_readonly_helper(gpointer bitmap, gpoint= er value) * If header_updated is not NULL then it is set appropriately regardless of * the return value. */ -bool coroutine_fn GRAPH_RDLOCK +bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated, Error **errp) { diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 904f00d1b3..11cf1d24e6 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -391,11 +391,10 @@ fail: * If the L2 entry is invalid return -errno and set @type to * QCOW2_SUBCLUSTER_INVALID. */ -static int qcow2_get_subcluster_range_type(BlockDriverState *bs, - uint64_t l2_entry, - uint64_t l2_bitmap, - unsigned sc_from, - QCow2SubclusterType *type) +static int GRAPH_RDLOCK +qcow2_get_subcluster_range_type(BlockDriverState *bs, uint64_t l2_entry, + uint64_t l2_bitmap, unsigned sc_from, + QCow2SubclusterType *type) { BDRVQcow2State *s =3D bs->opaque; uint32_t val; @@ -442,9 +441,10 @@ static int qcow2_get_subcluster_range_type(BlockDriver= State *bs, * On failure return -errno and update @l2_index to point to the * invalid entry. */ -static int count_contiguous_subclusters(BlockDriverState *bs, int nb_clust= ers, - unsigned sc_index, uint64_t *l2_sl= ice, - unsigned *l2_index) +static int GRAPH_RDLOCK +count_contiguous_subclusters(BlockDriverState *bs, int nb_clusters, + unsigned sc_index, uint64_t *l2_slice, + unsigned *l2_index) { BDRVQcow2State *s =3D bs->opaque; int i, count =3D 0; @@ -1329,7 +1329,8 @@ calculate_l2_meta(BlockDriverState *bs, uint64_t host= _cluster_offset, * requires a new allocation (that is, if the cluster is unallocated * or has refcount > 1 and therefore cannot be written in-place). */ -static bool cluster_needs_new_alloc(BlockDriverState *bs, uint64_t l2_entr= y) +static bool GRAPH_RDLOCK +cluster_needs_new_alloc(BlockDriverState *bs, uint64_t l2_entry) { switch (qcow2_get_cluster_type(bs, l2_entry)) { case QCOW2_CLUSTER_NORMAL: @@ -1360,9 +1361,9 @@ static bool cluster_needs_new_alloc(BlockDriverState = *bs, uint64_t l2_entry) * allocated and can be overwritten in-place (this includes clusters * of type QCOW2_CLUSTER_ZERO_ALLOC). */ -static int count_single_write_clusters(BlockDriverState *bs, int nb_cluste= rs, - uint64_t *l2_slice, int l2_index, - bool new_alloc) +static int GRAPH_RDLOCK +count_single_write_clusters(BlockDriverState *bs, int nb_clusters, + uint64_t *l2_slice, int l2_index, bool new_all= oc) { BDRVQcow2State *s =3D bs->opaque; uint64_t l2_entry =3D get_l2_entry(s, l2_slice, l2_index); diff --git a/block/qcow2.c b/block/qcow2.c index 7f022d5d78..dc42bbca3b 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -95,9 +95,10 @@ static int qcow2_probe(const uint8_t *buf, int buf_size,= const char *filename) } =20 =20 -static int qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset, - uint8_t *buf, size_t buflen, - void *opaque, Error **errp) +static int GRAPH_RDLOCK +qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset, + uint8_t *buf, size_t buflen, + void *opaque, Error **errp) { BlockDriverState *bs =3D opaque; BDRVQcow2State *s =3D bs->opaque; @@ -156,7 +157,7 @@ qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t = headerlen, void *opaque, =20 =20 /* The graph lock must be held when called in coroutine context */ -static int coroutine_mixed_fn +static int coroutine_mixed_fn GRAPH_RDLOCK qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset, const uint8_t *buf, size_t buflen, void *opaque, Error **errp) @@ -2029,6 +2030,8 @@ static void qcow2_reopen_commit(BDRVReopenState *stat= e) { BDRVQcow2State *s =3D state->bs->opaque; =20 + GRAPH_RDLOCK_GUARD_MAINLOOP(); + qcow2_update_options_commit(state->bs, state->opaque); if (!s->data_file) { /* @@ -2064,6 +2067,8 @@ static void qcow2_reopen_abort(BDRVReopenState *state) { BDRVQcow2State *s =3D state->bs->opaque; =20 + GRAPH_RDLOCK_GUARD_MAINLOOP(); + if (!s->data_file) { /* * If we don't have an external data file, s->data_file was cleare= d by --=20 2.41.0