From nobody Sun Nov 9 13:00:07 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=virtuozzo.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1551112844166360.376107669324; Mon, 25 Feb 2019 08:40:44 -0800 (PST) Received: from localhost ([127.0.0.1]:40334 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gyJJ3-0006G7-25 for importer@patchew.org; Mon, 25 Feb 2019 11:40:41 -0500 Received: from eggs.gnu.org ([209.51.188.92]:45792) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gyIXX-0007xi-Di for qemu-devel@nongnu.org; Mon, 25 Feb 2019 10:51:36 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gyIXW-0006ud-4s for qemu-devel@nongnu.org; Mon, 25 Feb 2019 10:51:35 -0500 Received: from relay.sw.ru ([185.231.240.75]:59356) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gyIXV-0006oL-S6; Mon, 25 Feb 2019 10:51:34 -0500 Received: from [10.28.8.145] (helo=kvm.sw.ru) by relay.sw.ru with esmtp (Exim 4.91) (envelope-from ) id 1gyIXI-0003ep-5r; Mon, 25 Feb 2019 18:51:20 +0300 From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org, qemu-block@nongnu.org Date: Mon, 25 Feb 2019 18:51:19 +0300 Message-Id: <20190225155119.21619-1-vsementsov@virtuozzo.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20190223002209.23084-2-jsnow@redhat.com> References: <20190223002209.23084-2-jsnow@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 185.231.240.75 Subject: [Qemu-devel] [PATCH] dirty-bitmap: introduce inconsistent bitmaps 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: kwolf@redhat.com, fam@euphon.net, vsementsov@virtuozzo.com, armbru@redhat.com, mreitz@redhat.com, jsnow@redhat.com 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" This will be used to show in dirty-bitmaps list inconsistent bitmaps found in qcow2 image on open. On open, bitmap in qcow2 image considered inconsistent if it has IN_USE flag already set. Signed-off-by: Vladimir Sementsov-Ogievskiy --- Hi! It's my counter-proposal for "[PATCH v2 1/4] block/dirty-bitmaps: add inconsistent bit" by John. Difference: Require that we don't have data for such bitmaps, which is more strict than just not load them in qcow2 code. Just don't allocate HBitmap. So, we save RAM. And we don't need a lot of assertions on !bitmap->inconsistent for operations, as we'll crash with segfault. (of course, we still need checking this, to produce correct errors in QAPI, so it's only a counter-proposal to the first patch of John's series) qapi/block-core.json | 8 +++++- include/block/dirty-bitmap.h | 5 ++++ block/dirty-bitmap.c | 56 +++++++++++++++++++++++++++++------- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 6e543594b3..7620653c54 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -470,12 +470,18 @@ # @persistent: true if the bitmap will eventually be flushed to persistent # storage (since 4.0) # +# @inconsistent: true if the bitmap is inconsistent. Inconsistent bitmaps = may +# be only removed. Source of inconsistent bitmaps are persi= stent +# bitmaps which were not correctly saved on some point (for +# example, due to unexpected Qemu crash) +# # Since: 1.3 ## { 'struct': 'BlockDirtyInfo', 'data': {'*name': 'str', 'count': 'int', 'granularity': 'uint32', 'recording': 'bool', 'busy': 'bool', - 'status': 'DirtyBitmapStatus', 'persistent': 'bool' } } + 'status': 'DirtyBitmapStatus', 'persistent': 'bool', + '*inconsistent': 'bool' } } =20 ## # @Qcow2BitmapInfoFlags: diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h index ba8477b73f..f2cce7694d 100644 --- a/include/block/dirty-bitmap.h +++ b/include/block/dirty-bitmap.h @@ -9,6 +9,11 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState= *bs, uint32_t granularity, const char *name, Error **errp); +BdrvDirtyBitmap *bdrv_create_inconsistent_dirty_bitmap(BlockDriverState *b= s, + uint32_t granularit= y, + const char *name, + Error **errp); + void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap, int chunk_size); void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap); diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c index 86c3b87ab9..f3b74d0900 100644 --- a/block/dirty-bitmap.c +++ b/block/dirty-bitmap.c @@ -30,12 +30,20 @@ =20 struct BdrvDirtyBitmap { QemuMutex *mutex; - HBitmap *bitmap; /* Dirty bitmap implementation */ + HBitmap *bitmap; /* + * Dirty bitmap implementation. + * May bu NULL, in which case the bitmap is + * "inconsistent". Bitmap don't have + * bitmap data and don't support any opera= tions + * related to it. The only allowed modific= ations + * are remove and truncate. + */ HBitmap *meta; /* Meta dirty bitmap */ bool busy; /* Bitmap is busy, it can't be used via QM= P */ BdrvDirtyBitmap *successor; /* Anonymous child, if any. */ char *name; /* Optional non-empty unique ID */ int64_t size; /* Size of the bitmap, in bytes */ + uint32_t granularity; /* Granularity of the bitmap, in bytes */ bool disabled; /* Bitmap is disabled. It ignores all writ= es to the device */ int active_iterators; /* How many iterators are active */ @@ -93,10 +101,11 @@ BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverSta= te *bs, const char *name) } =20 /* Called with BQL taken. */ -BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, - uint32_t granularity, - const char *name, - Error **errp) +static BdrvDirtyBitmap *do_bdrv_create_dirty_bitmap(BlockDriverState *bs, + uint32_t granularity, + const char *name, + bool inconsistent, + Error **errp) { int64_t bitmap_size; BdrvDirtyBitmap *bitmap; @@ -115,16 +124,34 @@ BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriver= State *bs, } bitmap =3D g_new0(BdrvDirtyBitmap, 1); bitmap->mutex =3D &bs->dirty_bitmap_mutex; - bitmap->bitmap =3D hbitmap_alloc(bitmap_size, ctz32(granularity)); + bitmap->bitmap =3D + inconsistent ? NULL : hbitmap_alloc(bitmap_size, ctz32(granularity= )); bitmap->size =3D bitmap_size; + bitmap->granularity =3D granularity; bitmap->name =3D g_strdup(name); - bitmap->disabled =3D false; + bitmap->disabled =3D inconsistent; bdrv_dirty_bitmaps_lock(bs); QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list); bdrv_dirty_bitmaps_unlock(bs); return bitmap; } =20 +BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, + uint32_t granularity, + const char *name, + Error **errp) +{ + return do_bdrv_create_dirty_bitmap(bs, granularity, name, false, errp); +} + +BdrvDirtyBitmap *bdrv_create_inconsistent_dirty_bitmap(BlockDriverState *b= s, + uint32_t granularit= y, + const char *name, + Error **errp) +{ + return do_bdrv_create_dirty_bitmap(bs, granularity, name, true, errp); +} + /* bdrv_create_meta_dirty_bitmap * * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. = I.e. @@ -269,6 +296,8 @@ int bdrv_dirty_bitmap_create_successor(BlockDriverState= *bs, =20 void bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap) { + assert(bitmap->bitmap); + bitmap->disabled =3D false; } =20 @@ -288,7 +317,9 @@ static void bdrv_release_dirty_bitmap_locked(BdrvDirtyB= itmap *bitmap) assert(!bdrv_dirty_bitmap_busy(bitmap)); assert(!bitmap->meta); QLIST_REMOVE(bitmap, list); - hbitmap_free(bitmap->bitmap); + if (bitmap->bitmap) { + hbitmap_free(bitmap->bitmap); + } g_free(bitmap->name); g_free(bitmap); } @@ -380,7 +411,9 @@ void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, i= nt64_t bytes) QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { assert(!bdrv_dirty_bitmap_busy(bitmap)); assert(!bitmap->active_iterators); - hbitmap_truncate(bitmap->bitmap, bytes); + if (bitmap->bitmap) { + hbitmap_truncate(bitmap->bitmap, bytes); + } bitmap->size =3D bytes; } bdrv_dirty_bitmaps_unlock(bs); @@ -455,6 +488,7 @@ BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDrive= rState *bs) BlockDirtyInfo *info =3D g_new0(BlockDirtyInfo, 1); BlockDirtyInfoList *entry =3D g_new0(BlockDirtyInfoList, 1); info->count =3D bdrv_get_dirty_count(bm); + info->has_inconsistent =3D info->inconsistent =3D !bm->bitmap; info->granularity =3D bdrv_dirty_bitmap_granularity(bm); info->has_name =3D !!bm->name; info->name =3D g_strdup(bm->name); @@ -504,7 +538,7 @@ uint32_t bdrv_get_default_bitmap_granularity(BlockDrive= rState *bs) =20 uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap) { - return 1U << hbitmap_granularity(bitmap->bitmap); + return bitmap->granularity; } =20 BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap) @@ -668,7 +702,7 @@ void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int= 64_t offset) =20 int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap) { - return hbitmap_count(bitmap->bitmap); + return bitmap->bitmap ? hbitmap_count(bitmap->bitmap) : -1; } =20 int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap) --=20 2.18.0