From nobody Sun Feb 8 22:44:43 2026 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=temperror (zoho.com: Error in retrieving data from DNS) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1550101381502965.0612910166122; Wed, 13 Feb 2019 15:43:01 -0800 (PST) Received: from localhost ([127.0.0.1]:36730 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gu4B0-0006nT-46 for importer@patchew.org; Wed, 13 Feb 2019 18:42:50 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47761) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gu497-0005c2-5j for qemu-devel@nongnu.org; Wed, 13 Feb 2019 18:40:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gu45G-0005ew-Cl for qemu-devel@nongnu.org; Wed, 13 Feb 2019 18:36:56 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46750) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gu44y-0005JO-QH; Wed, 13 Feb 2019 18:36:41 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C15A78535D; Wed, 13 Feb 2019 23:36:23 +0000 (UTC) Received: from probe.bos.redhat.com (dhcp-17-231.bos.redhat.com [10.18.17.231]) by smtp.corp.redhat.com (Postfix) with ESMTP id C788C600C0; Wed, 13 Feb 2019 23:36:22 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 13 Feb 2019 18:36:17 -0500 Message-Id: <20190213233618.22484-2-jsnow@redhat.com> In-Reply-To: <20190213233618.22484-1-jsnow@redhat.com> References: <20190213233618.22484-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 13 Feb 2019 23:36:23 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH 1/2] block/dirty-bitmaps: add inconsistent bit X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , vsementsov@virtuozzo.com, Markus Armbruster , Max Reitz , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Add an inconsistent bit to dirty-bitmaps that allows us to report a bitmap = as persistent but potentially inconsistent, i.e. if we find bitmaps on a qcow2 that have been marked as "in use". Signed-off-by: John Snow --- block/dirty-bitmap.c | 19 +++++++++++++++++++ include/block/dirty-bitmap.h | 2 ++ qapi/block-core.json | 9 +++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index fc390cae94..b1879d7fbd 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -47,6 +47,9 @@ struct BdrvDirtyBitmap { and this bitmap must remain unchanged w= hile this flag is set. */ bool persistent; /* bitmap must be saved to owner disk imag= e */ + bool inconsistent; /* bitmap is persistent, but not owned by = QEMU. + * It cannot be used at all in any way, ex= cept + * a QMP user can remove or clear it. */ bool migration; /* Bitmap is selected for migration, it sh= ould not be stored on the next inactivation (persistent flag doesn't matter until n= ext @@ -461,6 +464,8 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDrive= rState *bs) info->recording =3D bdrv_dirty_bitmap_recording(bm); info->busy =3D bdrv_dirty_bitmap_busy(bm); info->persistent =3D bm->persistent; + info->has_inconsistent =3D bm->inconsistent; + info->inconsistent =3D bm->inconsistent; entry->value =3D info; *plist =3D entry; plist =3D &entry->next; @@ -708,6 +713,15 @@ void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap= *bitmap, bool persistent) qemu_mutex_unlock(bitmap->mutex); } =20 +/* Called with BQL taken. */ +void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap, bool valu= e) +{ + qemu_mutex_lock(bitmap->mutex); + bitmap->inconsistent =3D value; + bitmap->disabled =3D value; + qemu_mutex_unlock(bitmap->mutex); +} + /* Called with BQL taken. */ void bdrv_dirty_bitmap_set_migration(BdrvDirtyBitmap *bitmap, bool migrati= on) { @@ -721,6 +735,11 @@ bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap= *bitmap) return bitmap->persistent && !bitmap->migration; } =20 +bool bdrv_dirty_bitmap_inconsistent(BdrvDirtyBitmap *bitmap) +{ + return bitmap->inconsistent; +} + bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs) { BdrvDirtyBitmap *bm; diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index ba8477b73f..c0d37702fd 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -68,6 +68,7 @@ void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap= *bitmap); void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value); void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent); +void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap, bool valu= e); void bdrv_dirty_bitmap_set_busy(BdrvDirtyBitmap *bitmap, bool busy); void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap = *src, HBitmap **backup, Error **errp); @@ -91,6 +92,7 @@ bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bi= tmap); bool bdrv_has_readonly_bitmaps(BlockDriverState *bs); bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap); bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap); +bool bdrv_dirty_bitmap_inconsistent(BdrvDirtyBitmap *bitmap); bool bdrv_dirty_bitmap_busy(BdrvDirtyBitmap *bitmap); bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs); BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, diff --git a/qapi/block-core.json b/qapi/block-core.json index 5d1d182447..f6b6dc2aff 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -470,12 +470,17 @@ # @persistent: true if the bitmap will eventually be flushed to persistent # storage (since 4.0) # +# @inconsistent: true if this is a persistent bitmap that QEMU does not ow= n. +# Implies @recording to be false and @busy to be true. To +# reclaim ownership, see @block-dirty-bitmap-remove or +# @block-dirty-bitmap-clear (since 4.0) +# # Since: 1.3 ## { 'struct': 'BlockDirtyInfo', 'data': {'*name': 'str', 'count': 'int', 'granularity': 'uint32', - 'recording': 'bool', 'busy': 'bool', - 'status': 'DirtyBitmapStatus', 'persistent': 'bool' } } + 'recording': 'bool', 'busy': 'bool', 'status': 'DirtyBitmapStat= us', + 'persistent': 'bool', '*inconsistent': 'bool' } } =20 ## # @Qcow2BitmapInfoFlags: --=20 2.17.2 From nobody Sun Feb 8 22:44:43 2026 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=temperror (zoho.com: Error in retrieving data from DNS) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1550101380600754.2234178561722; Wed, 13 Feb 2019 15:43:00 -0800 (PST) Received: from localhost ([127.0.0.1]:36728 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gu4Ay-0006lv-LY for importer@patchew.org; Wed, 13 Feb 2019 18:42:48 -0500 Received: from eggs.gnu.org ([209.51.188.92]:47743) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gu494-0005by-BW for qemu-devel@nongnu.org; Wed, 13 Feb 2019 18:40:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gu45I-0005gy-In for qemu-devel@nongnu.org; Wed, 13 Feb 2019 18:36:57 -0500 Received: from mx1.redhat.com ([209.132.183.28]:48242) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gu45E-0005K4-E6; Wed, 13 Feb 2019 18:36:54 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E05AC58586; Wed, 13 Feb 2019 23:36:24 +0000 (UTC) Received: from probe.bos.redhat.com (dhcp-17-231.bos.redhat.com [10.18.17.231]) by smtp.corp.redhat.com (Postfix) with ESMTP id E230D600C0; Wed, 13 Feb 2019 23:36:23 +0000 (UTC) From: John Snow To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Wed, 13 Feb 2019 18:36:18 -0500 Message-Id: <20190213233618.22484-3-jsnow@redhat.com> In-Reply-To: <20190213233618.22484-1-jsnow@redhat.com> References: <20190213233618.22484-1-jsnow@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 13 Feb 2019 23:36:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH 2/2] block/dirty-bitmap: implement inconsistent bit X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Fam Zheng , Kevin Wolf , vsementsov@virtuozzo.com, Markus Armbruster , Max Reitz , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: John Snow --- block/dirty-bitmap.c | 15 +++++++++++++ block/qcow2-bitmap.c | 42 ++++++++++++++++++----------------- blockdev.c | 43 ++++++++++++++++++++++++++++++++++++ include/block/dirty-bitmap.h | 1 + 4 files changed, 81 insertions(+), 20 deletions(-) diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index b1879d7fbd..06d8ee0d79 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -589,6 +589,7 @@ void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, H= Bitmap **out) *out =3D backup; } bdrv_dirty_bitmap_unlock(bitmap); + bdrv_dirty_bitmap_set_inconsistent(bitmap, false); } =20 void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup) @@ -776,6 +777,13 @@ bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap= *bitmap, return hbitmap_next_dirty_area(bitmap->bitmap, offset, bytes); } =20 +void bdrv_dirty_bitmap_add_inconsistent_hint(Error **errp) +{ + error_append_hint(errp, "Try block-dirty-bitmap-clear to mark this " + "bitmap consistent again, or block-dirty-bitmap-remo= ve " + "to delete it."); +} + void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap = *src, HBitmap **backup, Error **errp) { @@ -798,6 +806,13 @@ void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, co= nst BdrvDirtyBitmap *src, goto out; } =20 + if (bdrv_dirty_bitmap_inconsistent(dest)) { + error_setg(errp, "Bitmap '%s' is inconsistent and cannot be used a= s" + " a merge target", dest->name); + bdrv_dirty_bitmap_add_inconsistent_hint(errp); + goto out; + } + if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) { error_setg(errp, "Bitmaps are incompatible and can't be merged"); goto out; diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index 3ee524da4b..9bd8bc417f 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -343,9 +343,15 @@ static BdrvDirtyBitmap *load_bitmap(BlockDriverState *= bs, uint32_t granularity; BdrvDirtyBitmap *bitmap =3D NULL; =20 + granularity =3D 1U << bm->granularity_bits; + bitmap =3D bdrv_create_dirty_bitmap(bs, granularity, bm->name, errp); + if (bitmap =3D=3D NULL) { + goto fail; + } + if (bm->flags & BME_FLAG_IN_USE) { - error_setg(errp, "Bitmap '%s' is in use", bm->name); - goto fail; + /* Data is unusable, skip loading it */ + return bitmap; } =20 ret =3D bitmap_table_load(bs, &bm->table, &bitmap_table); @@ -356,12 +362,6 @@ static BdrvDirtyBitmap *load_bitmap(BlockDriverState *= bs, goto fail; } =20 - granularity =3D 1U << bm->granularity_bits; - bitmap =3D bdrv_create_dirty_bitmap(bs, granularity, bm->name, errp); - if (bitmap =3D=3D NULL) { - goto fail; - } - ret =3D load_bitmap_data(bs, bitmap_table, bm->table.size, bitmap); if (ret < 0) { error_setg_errno(errp, -ret, "Could not read bitmap '%s' from imag= e", @@ -962,20 +962,22 @@ bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, E= rror **errp) } =20 QSIMPLEQ_FOREACH(bm, bm_list, entry) { - if (!(bm->flags & BME_FLAG_IN_USE)) { - BdrvDirtyBitmap *bitmap =3D load_bitmap(bs, bm, errp); - if (bitmap =3D=3D NULL) { - goto fail; - } + BdrvDirtyBitmap *bitmap =3D load_bitmap(bs, bm, errp); + if (bitmap =3D=3D NULL) { + goto fail; + } + + if (bm->flags & BME_FLAG_IN_USE) { + bdrv_dirty_bitmap_set_inconsistent(bitmap, true); + } =20 - if (!(bm->flags & BME_FLAG_AUTO)) { - bdrv_disable_dirty_bitmap(bitmap); - } - bdrv_dirty_bitmap_set_persistance(bitmap, true); - bm->flags |=3D BME_FLAG_IN_USE; - created_dirty_bitmaps =3D - g_slist_append(created_dirty_bitmaps, bitmap); + if (!(bm->flags & BME_FLAG_AUTO)) { + bdrv_disable_dirty_bitmap(bitmap); } + bdrv_dirty_bitmap_set_persistance(bitmap, true); + bm->flags |=3D BME_FLAG_IN_USE; + created_dirty_bitmaps =3D + g_slist_append(created_dirty_bitmaps, bitmap); } =20 if (created_dirty_bitmaps !=3D NULL) { diff --git a/blockdev.c b/blockdev.c index 23a4bf136e..12c6f706dd 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1943,6 +1943,7 @@ typedef struct BlockDirtyBitmapState { HBitmap *backup; bool prepared; bool was_enabled; + bool was_inconsistent; } BlockDirtyBitmapState; =20 static void block_dirty_bitmap_add_prepare(BlkActionState *common, @@ -2016,6 +2017,7 @@ static void block_dirty_bitmap_clear_prepare(BlkActio= nState *common, return; } =20 + state->was_inconsistent =3D bdrv_dirty_bitmap_inconsistent(state->bitm= ap); bdrv_clear_dirty_bitmap(state->bitmap, &state->backup); } =20 @@ -2027,6 +2029,9 @@ static void block_dirty_bitmap_restore(BlkActionState= *common) if (state->backup) { bdrv_restore_dirty_bitmap(state->bitmap, state->backup); } + if (state->was_inconsistent) { + bdrv_dirty_bitmap_set_inconsistent(state->bitmap, true); + } } =20 static void block_dirty_bitmap_free_backup(BlkActionState *common) @@ -2063,6 +2068,12 @@ static void block_dirty_bitmap_enable_prepare(BlkAct= ionState *common, " and cannot be enabled", action->name); return; } + if (bdrv_dirty_bitmap_inconsistent(state->bitmap)) { + error_setg(errp, "Bitmap '%s' is inconsistent and cannot be enable= d", + action->name); + bdrv_dirty_bitmap_add_inconsistent_hint(errp); + return; + } =20 state->was_enabled =3D bdrv_dirty_bitmap_enabled(state->bitmap); bdrv_enable_dirty_bitmap(state->bitmap); @@ -2104,6 +2115,12 @@ static void block_dirty_bitmap_disable_prepare(BlkAc= tionState *common, " and cannot be disabled", action->name); return; } + if (bdrv_dirty_bitmap_inconsistent(state->bitmap)) { + error_setg(errp, "Bitmap '%s' is inconsistent and cannot be disabl= ed", + action->name); + bdrv_dirty_bitmap_add_inconsistent_hint(errp); + return; + } =20 state->was_enabled =3D bdrv_dirty_bitmap_enabled(state->bitmap); bdrv_disable_dirty_bitmap(state->bitmap); @@ -2948,6 +2965,13 @@ void qmp_block_dirty_bitmap_enable(const char *node,= const char *name, return; } =20 + if (bdrv_dirty_bitmap_inconsistent(bitmap)) { + error_setg(errp, "Bitmap '%s' is inconsistent and cannot be enable= d", + name); + bdrv_dirty_bitmap_add_inconsistent_hint(errp); + return; + } + bdrv_enable_dirty_bitmap(bitmap); } =20 @@ -2969,6 +2993,13 @@ void qmp_block_dirty_bitmap_disable(const char *node= , const char *name, return; } =20 + if (bdrv_dirty_bitmap_inconsistent(bitmap)) { + error_setg(errp, "Bitmap '%s' is inconsistent and cannot be disabl= ed", + name); + bdrv_dirty_bitmap_add_inconsistent_hint(errp); + return; + } + bdrv_disable_dirty_bitmap(bitmap); } =20 @@ -3544,6 +3575,12 @@ static BlockJob *do_drive_backup(DriveBackup *backup= , JobTxn *txn, " and cannot be used for backup", backup->bitmap); goto out; } + if (bdrv_dirty_bitmap_inconsistent(bmap)) { + error_setg(errp, "Bitmap '%s' is inconsistent and cannot be us= ed for" + " a backup operation", backup->bitmap); + bdrv_dirty_bitmap_add_inconsistent_hint(errp); + goto out; + } } if (!backup->auto_finalize) { job_flags |=3D JOB_MANUAL_FINALIZE; @@ -3657,6 +3694,12 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup,= JobTxn *txn, " and cannot be used for backup", backup->bitmap); goto out; } + if (bdrv_dirty_bitmap_inconsistent(bmap)) { + error_setg(errp, "Bitmap '%s' is inconsistent and cannot be us= ed for" + " a backup operation", backup->bitmap); + bdrv_dirty_bitmap_add_inconsistent_hint(errp); + goto out; + } } =20 if (!backup->auto_finalize) { diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index c0d37702fd..b8485d2c94 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -105,5 +105,6 @@ bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap = *bitmap, BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, Error **errp); +void bdrv_dirty_bitmap_add_inconsistent_hint(Error **errp); =20 #endif --=20 2.17.2