1ebab2259SFam Zheng /* 2ebab2259SFam Zheng * Block Dirty Bitmap 3ebab2259SFam Zheng * 41b6cc579SEric Blake * Copyright (c) 2016-2017 Red Hat. Inc 5ebab2259SFam Zheng * 6ebab2259SFam Zheng * Permission is hereby granted, free of charge, to any person obtaining a copy 7ebab2259SFam Zheng * of this software and associated documentation files (the "Software"), to deal 8ebab2259SFam Zheng * in the Software without restriction, including without limitation the rights 9ebab2259SFam Zheng * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10ebab2259SFam Zheng * copies of the Software, and to permit persons to whom the Software is 11ebab2259SFam Zheng * furnished to do so, subject to the following conditions: 12ebab2259SFam Zheng * 13ebab2259SFam Zheng * The above copyright notice and this permission notice shall be included in 14ebab2259SFam Zheng * all copies or substantial portions of the Software. 15ebab2259SFam Zheng * 16ebab2259SFam Zheng * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17ebab2259SFam Zheng * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18ebab2259SFam Zheng * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19ebab2259SFam Zheng * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20ebab2259SFam Zheng * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21ebab2259SFam Zheng * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22ebab2259SFam Zheng * THE SOFTWARE. 23ebab2259SFam Zheng */ 24ebab2259SFam Zheng #include "qemu/osdep.h" 25da34e65cSMarkus Armbruster #include "qapi/error.h" 26ebab2259SFam Zheng #include "qemu-common.h" 27ebab2259SFam Zheng #include "trace.h" 28ebab2259SFam Zheng #include "block/block_int.h" 29ebab2259SFam Zheng #include "block/blockjob.h" 30ebab2259SFam Zheng 31ebab2259SFam Zheng /** 32ebab2259SFam Zheng * A BdrvDirtyBitmap can be in three possible states: 33ebab2259SFam Zheng * (1) successor is NULL and disabled is false: full r/w mode 34ebab2259SFam Zheng * (2) successor is NULL and disabled is true: read only mode ("disabled") 35ebab2259SFam Zheng * (3) successor is set: frozen mode. 36ebab2259SFam Zheng * A frozen bitmap cannot be renamed, deleted, anonymized, cleared, set, 37ebab2259SFam Zheng * or enabled. A frozen bitmap can only abdicate() or reclaim(). 38ebab2259SFam Zheng */ 39ebab2259SFam Zheng struct BdrvDirtyBitmap { 40b64bd51eSPaolo Bonzini QemuMutex *mutex; 41*ca759622SEric Blake HBitmap *bitmap; /* Dirty bitmap implementation */ 42fb933437SFam Zheng HBitmap *meta; /* Meta dirty bitmap */ 43ebab2259SFam Zheng BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */ 44ebab2259SFam Zheng char *name; /* Optional non-empty unique ID */ 45993e6525SEric Blake int64_t size; /* Size of the bitmap, in bytes */ 468bfc932eSVladimir Sementsov-Ogievskiy bool disabled; /* Bitmap is disabled. It ignores all writes to 478bfc932eSVladimir Sementsov-Ogievskiy the device */ 48dc162c8eSFam Zheng int active_iterators; /* How many iterators are active */ 49d6883bc9SVladimir Sementsov-Ogievskiy bool readonly; /* Bitmap is read-only. This field also 50d6883bc9SVladimir Sementsov-Ogievskiy prevents the respective image from being 51d6883bc9SVladimir Sementsov-Ogievskiy modified (i.e. blocks writes and discards). 52d6883bc9SVladimir Sementsov-Ogievskiy Such operations must fail and both the image 53d6883bc9SVladimir Sementsov-Ogievskiy and this bitmap must remain unchanged while 54d6883bc9SVladimir Sementsov-Ogievskiy this flag is set. */ 55a0319aacSVladimir Sementsov-Ogievskiy bool autoload; /* For persistent bitmaps: bitmap must be 56a0319aacSVladimir Sementsov-Ogievskiy autoloaded on image opening */ 57a88b179fSVladimir Sementsov-Ogievskiy bool persistent; /* bitmap must be saved to owner disk image */ 58ebab2259SFam Zheng QLIST_ENTRY(BdrvDirtyBitmap) list; 59ebab2259SFam Zheng }; 60ebab2259SFam Zheng 61dc162c8eSFam Zheng struct BdrvDirtyBitmapIter { 62dc162c8eSFam Zheng HBitmapIter hbi; 63dc162c8eSFam Zheng BdrvDirtyBitmap *bitmap; 64dc162c8eSFam Zheng }; 65dc162c8eSFam Zheng 662119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_lock(BlockDriverState *bs) 672119882cSPaolo Bonzini { 682119882cSPaolo Bonzini qemu_mutex_lock(&bs->dirty_bitmap_mutex); 692119882cSPaolo Bonzini } 702119882cSPaolo Bonzini 712119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_unlock(BlockDriverState *bs) 722119882cSPaolo Bonzini { 732119882cSPaolo Bonzini qemu_mutex_unlock(&bs->dirty_bitmap_mutex); 742119882cSPaolo Bonzini } 752119882cSPaolo Bonzini 76b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap) 77b64bd51eSPaolo Bonzini { 78b64bd51eSPaolo Bonzini qemu_mutex_lock(bitmap->mutex); 79b64bd51eSPaolo Bonzini } 80b64bd51eSPaolo Bonzini 81b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap) 82b64bd51eSPaolo Bonzini { 83b64bd51eSPaolo Bonzini qemu_mutex_unlock(bitmap->mutex); 84b64bd51eSPaolo Bonzini } 85b64bd51eSPaolo Bonzini 862119882cSPaolo Bonzini /* Called with BQL or dirty_bitmap lock taken. */ 87ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name) 88ebab2259SFam Zheng { 89ebab2259SFam Zheng BdrvDirtyBitmap *bm; 90ebab2259SFam Zheng 91ebab2259SFam Zheng assert(name); 92ebab2259SFam Zheng QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 93ebab2259SFam Zheng if (bm->name && !strcmp(name, bm->name)) { 94ebab2259SFam Zheng return bm; 95ebab2259SFam Zheng } 96ebab2259SFam Zheng } 97ebab2259SFam Zheng return NULL; 98ebab2259SFam Zheng } 99ebab2259SFam Zheng 1002119882cSPaolo Bonzini /* Called with BQL taken. */ 101ebab2259SFam Zheng void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) 102ebab2259SFam Zheng { 103ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 104ebab2259SFam Zheng g_free(bitmap->name); 105ebab2259SFam Zheng bitmap->name = NULL; 106a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = false; 107a0319aacSVladimir Sementsov-Ogievskiy bitmap->autoload = false; 108ebab2259SFam Zheng } 109ebab2259SFam Zheng 1102119882cSPaolo Bonzini /* Called with BQL taken. */ 111ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, 112ebab2259SFam Zheng uint32_t granularity, 113ebab2259SFam Zheng const char *name, 114ebab2259SFam Zheng Error **errp) 115ebab2259SFam Zheng { 116ebab2259SFam Zheng int64_t bitmap_size; 117ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 118ebab2259SFam Zheng 119993e6525SEric Blake assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE); 120ebab2259SFam Zheng 121ebab2259SFam Zheng if (name && bdrv_find_dirty_bitmap(bs, name)) { 122ebab2259SFam Zheng error_setg(errp, "Bitmap already exists: %s", name); 123ebab2259SFam Zheng return NULL; 124ebab2259SFam Zheng } 125993e6525SEric Blake bitmap_size = bdrv_getlength(bs); 126ebab2259SFam Zheng if (bitmap_size < 0) { 127ebab2259SFam Zheng error_setg_errno(errp, -bitmap_size, "could not get length of device"); 128ebab2259SFam Zheng errno = -bitmap_size; 129ebab2259SFam Zheng return NULL; 130ebab2259SFam Zheng } 131ebab2259SFam Zheng bitmap = g_new0(BdrvDirtyBitmap, 1); 132b64bd51eSPaolo Bonzini bitmap->mutex = &bs->dirty_bitmap_mutex; 133*ca759622SEric Blake bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity)); 134ebab2259SFam Zheng bitmap->size = bitmap_size; 135ebab2259SFam Zheng bitmap->name = g_strdup(name); 136ebab2259SFam Zheng bitmap->disabled = false; 1372119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 138ebab2259SFam Zheng QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list); 1392119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 140ebab2259SFam Zheng return bitmap; 141ebab2259SFam Zheng } 142ebab2259SFam Zheng 143fb933437SFam Zheng /* bdrv_create_meta_dirty_bitmap 144fb933437SFam Zheng * 145fb933437SFam Zheng * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. I.e. 146fb933437SFam Zheng * when a dirty status bit in @bitmap is changed (either from reset to set or 147fb933437SFam Zheng * the other way around), its respective meta dirty bitmap bit will be marked 148fb933437SFam Zheng * dirty as well. 149fb933437SFam Zheng * 150fb933437SFam Zheng * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap. 151fb933437SFam Zheng * @chunk_size: how many bytes of bitmap data does each bit in the meta bitmap 152fb933437SFam Zheng * track. 153fb933437SFam Zheng */ 154fb933437SFam Zheng void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap, 155fb933437SFam Zheng int chunk_size) 156fb933437SFam Zheng { 157fb933437SFam Zheng assert(!bitmap->meta); 158b64bd51eSPaolo Bonzini qemu_mutex_lock(bitmap->mutex); 159fb933437SFam Zheng bitmap->meta = hbitmap_create_meta(bitmap->bitmap, 160fb933437SFam Zheng chunk_size * BITS_PER_BYTE); 161b64bd51eSPaolo Bonzini qemu_mutex_unlock(bitmap->mutex); 162fb933437SFam Zheng } 163fb933437SFam Zheng 164fb933437SFam Zheng void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap) 165fb933437SFam Zheng { 166fb933437SFam Zheng assert(bitmap->meta); 167b64bd51eSPaolo Bonzini qemu_mutex_lock(bitmap->mutex); 168fb933437SFam Zheng hbitmap_free_meta(bitmap->bitmap); 169fb933437SFam Zheng bitmap->meta = NULL; 170b64bd51eSPaolo Bonzini qemu_mutex_unlock(bitmap->mutex); 171fb933437SFam Zheng } 172fb933437SFam Zheng 17315891facSFam Zheng int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap) 17415891facSFam Zheng { 175993e6525SEric Blake return bitmap->size; 17615891facSFam Zheng } 17715891facSFam Zheng 17815891facSFam Zheng const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap) 17915891facSFam Zheng { 18015891facSFam Zheng return bitmap->name; 18115891facSFam Zheng } 18215891facSFam Zheng 1832119882cSPaolo Bonzini /* Called with BQL taken. */ 184ebab2259SFam Zheng bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap) 185ebab2259SFam Zheng { 186ebab2259SFam Zheng return bitmap->successor; 187ebab2259SFam Zheng } 188ebab2259SFam Zheng 1892119882cSPaolo Bonzini /* Called with BQL taken. */ 190ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap) 191ebab2259SFam Zheng { 192ebab2259SFam Zheng return !(bitmap->disabled || bitmap->successor); 193ebab2259SFam Zheng } 194ebab2259SFam Zheng 1952119882cSPaolo Bonzini /* Called with BQL taken. */ 196ebab2259SFam Zheng DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap) 197ebab2259SFam Zheng { 198ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 199ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_FROZEN; 200ebab2259SFam Zheng } else if (!bdrv_dirty_bitmap_enabled(bitmap)) { 201ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_DISABLED; 202ebab2259SFam Zheng } else { 203ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_ACTIVE; 204ebab2259SFam Zheng } 205ebab2259SFam Zheng } 206ebab2259SFam Zheng 207ebab2259SFam Zheng /** 208ebab2259SFam Zheng * Create a successor bitmap destined to replace this bitmap after an operation. 209ebab2259SFam Zheng * Requires that the bitmap is not frozen and has no successor. 2102119882cSPaolo Bonzini * Called with BQL taken. 211ebab2259SFam Zheng */ 212ebab2259SFam Zheng int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, 213ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, Error **errp) 214ebab2259SFam Zheng { 215ebab2259SFam Zheng uint64_t granularity; 216ebab2259SFam Zheng BdrvDirtyBitmap *child; 217ebab2259SFam Zheng 218ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 219ebab2259SFam Zheng error_setg(errp, "Cannot create a successor for a bitmap that is " 220ebab2259SFam Zheng "currently frozen"); 221ebab2259SFam Zheng return -1; 222ebab2259SFam Zheng } 223ebab2259SFam Zheng assert(!bitmap->successor); 224ebab2259SFam Zheng 225ebab2259SFam Zheng /* Create an anonymous successor */ 226ebab2259SFam Zheng granularity = bdrv_dirty_bitmap_granularity(bitmap); 227ebab2259SFam Zheng child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); 228ebab2259SFam Zheng if (!child) { 229ebab2259SFam Zheng return -1; 230ebab2259SFam Zheng } 231ebab2259SFam Zheng 232ebab2259SFam Zheng /* Successor will be on or off based on our current state. */ 233ebab2259SFam Zheng child->disabled = bitmap->disabled; 234ebab2259SFam Zheng 235ebab2259SFam Zheng /* Install the successor and freeze the parent */ 236ebab2259SFam Zheng bitmap->successor = child; 237ebab2259SFam Zheng return 0; 238ebab2259SFam Zheng } 239ebab2259SFam Zheng 240ebab2259SFam Zheng /** 241ebab2259SFam Zheng * For a bitmap with a successor, yield our name to the successor, 242ebab2259SFam Zheng * delete the old bitmap, and return a handle to the new bitmap. 2432119882cSPaolo Bonzini * Called with BQL taken. 244ebab2259SFam Zheng */ 245ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs, 246ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, 247ebab2259SFam Zheng Error **errp) 248ebab2259SFam Zheng { 249ebab2259SFam Zheng char *name; 250ebab2259SFam Zheng BdrvDirtyBitmap *successor = bitmap->successor; 251ebab2259SFam Zheng 252ebab2259SFam Zheng if (successor == NULL) { 253ebab2259SFam Zheng error_setg(errp, "Cannot relinquish control if " 254ebab2259SFam Zheng "there's no successor present"); 255ebab2259SFam Zheng return NULL; 256ebab2259SFam Zheng } 257ebab2259SFam Zheng 258ebab2259SFam Zheng name = bitmap->name; 259ebab2259SFam Zheng bitmap->name = NULL; 260ebab2259SFam Zheng successor->name = name; 261ebab2259SFam Zheng bitmap->successor = NULL; 262a88b179fSVladimir Sementsov-Ogievskiy successor->persistent = bitmap->persistent; 263a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = false; 264a0319aacSVladimir Sementsov-Ogievskiy successor->autoload = bitmap->autoload; 265a0319aacSVladimir Sementsov-Ogievskiy bitmap->autoload = false; 266ebab2259SFam Zheng bdrv_release_dirty_bitmap(bs, bitmap); 267ebab2259SFam Zheng 268ebab2259SFam Zheng return successor; 269ebab2259SFam Zheng } 270ebab2259SFam Zheng 271ebab2259SFam Zheng /** 272ebab2259SFam Zheng * In cases of failure where we can no longer safely delete the parent, 273ebab2259SFam Zheng * we may wish to re-join the parent and child/successor. 274ebab2259SFam Zheng * The merged parent will be un-frozen, but not explicitly re-enabled. 2752119882cSPaolo Bonzini * Called with BQL taken. 276ebab2259SFam Zheng */ 277ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, 278ebab2259SFam Zheng BdrvDirtyBitmap *parent, 279ebab2259SFam Zheng Error **errp) 280ebab2259SFam Zheng { 281ebab2259SFam Zheng BdrvDirtyBitmap *successor = parent->successor; 282ebab2259SFam Zheng 283ebab2259SFam Zheng if (!successor) { 284ebab2259SFam Zheng error_setg(errp, "Cannot reclaim a successor when none is present"); 285ebab2259SFam Zheng return NULL; 286ebab2259SFam Zheng } 287ebab2259SFam Zheng 288ebab2259SFam Zheng if (!hbitmap_merge(parent->bitmap, successor->bitmap)) { 289ebab2259SFam Zheng error_setg(errp, "Merging of parent and successor bitmap failed"); 290ebab2259SFam Zheng return NULL; 291ebab2259SFam Zheng } 292ebab2259SFam Zheng bdrv_release_dirty_bitmap(bs, successor); 293ebab2259SFam Zheng parent->successor = NULL; 294ebab2259SFam Zheng 295ebab2259SFam Zheng return parent; 296ebab2259SFam Zheng } 297ebab2259SFam Zheng 298ebab2259SFam Zheng /** 299ebab2259SFam Zheng * Truncates _all_ bitmaps attached to a BDS. 3002119882cSPaolo Bonzini * Called with BQL taken. 301ebab2259SFam Zheng */ 3021b6cc579SEric Blake void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes) 303ebab2259SFam Zheng { 304ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 305ebab2259SFam Zheng 3062119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 307ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 308ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 309dc162c8eSFam Zheng assert(!bitmap->active_iterators); 310*ca759622SEric Blake hbitmap_truncate(bitmap->bitmap, bytes); 311993e6525SEric Blake bitmap->size = bytes; 312ebab2259SFam Zheng } 3132119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 314ebab2259SFam Zheng } 315ebab2259SFam Zheng 316615b5dcfSVladimir Sementsov-Ogievskiy static bool bdrv_dirty_bitmap_has_name(BdrvDirtyBitmap *bitmap) 317615b5dcfSVladimir Sementsov-Ogievskiy { 318615b5dcfSVladimir Sementsov-Ogievskiy return !!bdrv_dirty_bitmap_name(bitmap); 319615b5dcfSVladimir Sementsov-Ogievskiy } 320615b5dcfSVladimir Sementsov-Ogievskiy 3212119882cSPaolo Bonzini /* Called with BQL taken. */ 322615b5dcfSVladimir Sementsov-Ogievskiy static void bdrv_do_release_matching_dirty_bitmap( 323615b5dcfSVladimir Sementsov-Ogievskiy BlockDriverState *bs, BdrvDirtyBitmap *bitmap, 324615b5dcfSVladimir Sementsov-Ogievskiy bool (*cond)(BdrvDirtyBitmap *bitmap)) 325ebab2259SFam Zheng { 326ebab2259SFam Zheng BdrvDirtyBitmap *bm, *next; 3272119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 328ebab2259SFam Zheng QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { 329615b5dcfSVladimir Sementsov-Ogievskiy if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) { 330dc162c8eSFam Zheng assert(!bm->active_iterators); 331ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bm)); 332fb933437SFam Zheng assert(!bm->meta); 333ebab2259SFam Zheng QLIST_REMOVE(bm, list); 334ebab2259SFam Zheng hbitmap_free(bm->bitmap); 335ebab2259SFam Zheng g_free(bm->name); 336ebab2259SFam Zheng g_free(bm); 337ebab2259SFam Zheng 338ebab2259SFam Zheng if (bitmap) { 3392119882cSPaolo Bonzini goto out; 340ebab2259SFam Zheng } 341ebab2259SFam Zheng } 342ebab2259SFam Zheng } 3437105007aSFam Zheng if (bitmap) { 3447105007aSFam Zheng abort(); 3457105007aSFam Zheng } 3462119882cSPaolo Bonzini 3472119882cSPaolo Bonzini out: 3482119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 349ebab2259SFam Zheng } 350ebab2259SFam Zheng 3512119882cSPaolo Bonzini /* Called with BQL taken. */ 352ebab2259SFam Zheng void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap) 353ebab2259SFam Zheng { 354615b5dcfSVladimir Sementsov-Ogievskiy bdrv_do_release_matching_dirty_bitmap(bs, bitmap, NULL); 355ebab2259SFam Zheng } 356ebab2259SFam Zheng 357ebab2259SFam Zheng /** 358ebab2259SFam Zheng * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()). 359ebab2259SFam Zheng * There must not be any frozen bitmaps attached. 36056f364e6SVladimir Sementsov-Ogievskiy * This function does not remove persistent bitmaps from the storage. 3612119882cSPaolo Bonzini * Called with BQL taken. 362ebab2259SFam Zheng */ 363ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) 364ebab2259SFam Zheng { 365615b5dcfSVladimir Sementsov-Ogievskiy bdrv_do_release_matching_dirty_bitmap(bs, NULL, bdrv_dirty_bitmap_has_name); 366615b5dcfSVladimir Sementsov-Ogievskiy } 367615b5dcfSVladimir Sementsov-Ogievskiy 368615b5dcfSVladimir Sementsov-Ogievskiy /** 369615b5dcfSVladimir Sementsov-Ogievskiy * Release all persistent dirty bitmaps attached to a BDS (for use in 370615b5dcfSVladimir Sementsov-Ogievskiy * bdrv_inactivate_recurse()). 371615b5dcfSVladimir Sementsov-Ogievskiy * There must not be any frozen bitmaps attached. 372615b5dcfSVladimir Sementsov-Ogievskiy * This function does not remove persistent bitmaps from the storage. 373615b5dcfSVladimir Sementsov-Ogievskiy */ 374615b5dcfSVladimir Sementsov-Ogievskiy void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs) 375615b5dcfSVladimir Sementsov-Ogievskiy { 376615b5dcfSVladimir Sementsov-Ogievskiy bdrv_do_release_matching_dirty_bitmap(bs, NULL, 377615b5dcfSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_get_persistance); 378ebab2259SFam Zheng } 379ebab2259SFam Zheng 38056f364e6SVladimir Sementsov-Ogievskiy /** 38156f364e6SVladimir Sementsov-Ogievskiy * Remove persistent dirty bitmap from the storage if it exists. 38256f364e6SVladimir Sementsov-Ogievskiy * Absence of bitmap is not an error, because we have the following scenario: 38356f364e6SVladimir Sementsov-Ogievskiy * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no 38456f364e6SVladimir Sementsov-Ogievskiy * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should 38556f364e6SVladimir Sementsov-Ogievskiy * not fail. 38656f364e6SVladimir Sementsov-Ogievskiy * This function doesn't release corresponding BdrvDirtyBitmap. 38756f364e6SVladimir Sementsov-Ogievskiy */ 38856f364e6SVladimir Sementsov-Ogievskiy void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, 38956f364e6SVladimir Sementsov-Ogievskiy const char *name, 39056f364e6SVladimir Sementsov-Ogievskiy Error **errp) 39156f364e6SVladimir Sementsov-Ogievskiy { 39256f364e6SVladimir Sementsov-Ogievskiy if (bs->drv && bs->drv->bdrv_remove_persistent_dirty_bitmap) { 39356f364e6SVladimir Sementsov-Ogievskiy bs->drv->bdrv_remove_persistent_dirty_bitmap(bs, name, errp); 39456f364e6SVladimir Sementsov-Ogievskiy } 39556f364e6SVladimir Sementsov-Ogievskiy } 39656f364e6SVladimir Sementsov-Ogievskiy 3972119882cSPaolo Bonzini /* Called with BQL taken. */ 398ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 399ebab2259SFam Zheng { 400ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 401ebab2259SFam Zheng bitmap->disabled = true; 402ebab2259SFam Zheng } 403ebab2259SFam Zheng 4042119882cSPaolo Bonzini /* Called with BQL taken. */ 405ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 406ebab2259SFam Zheng { 407ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 408ebab2259SFam Zheng bitmap->disabled = false; 409ebab2259SFam Zheng } 410ebab2259SFam Zheng 411ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs) 412ebab2259SFam Zheng { 413ebab2259SFam Zheng BdrvDirtyBitmap *bm; 414ebab2259SFam Zheng BlockDirtyInfoList *list = NULL; 415ebab2259SFam Zheng BlockDirtyInfoList **plist = &list; 416ebab2259SFam Zheng 4172119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 418ebab2259SFam Zheng QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 419ebab2259SFam Zheng BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1); 420ebab2259SFam Zheng BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1); 4219a46dba7SEric Blake info->count = bdrv_get_dirty_count(bm); 422ebab2259SFam Zheng info->granularity = bdrv_dirty_bitmap_granularity(bm); 423ebab2259SFam Zheng info->has_name = !!bm->name; 424ebab2259SFam Zheng info->name = g_strdup(bm->name); 425ebab2259SFam Zheng info->status = bdrv_dirty_bitmap_status(bm); 426ebab2259SFam Zheng entry->value = info; 427ebab2259SFam Zheng *plist = entry; 428ebab2259SFam Zheng plist = &entry->next; 429ebab2259SFam Zheng } 4302119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 431ebab2259SFam Zheng 432ebab2259SFam Zheng return list; 433ebab2259SFam Zheng } 434ebab2259SFam Zheng 435b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 4363b5d4df0SEric Blake bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, 4373b5d4df0SEric Blake int64_t offset) 438ebab2259SFam Zheng { 439ebab2259SFam Zheng if (bitmap) { 440*ca759622SEric Blake return hbitmap_get(bitmap->bitmap, offset); 441ebab2259SFam Zheng } else { 4423b5d4df0SEric Blake return false; 443ebab2259SFam Zheng } 444ebab2259SFam Zheng } 445ebab2259SFam Zheng 446ebab2259SFam Zheng /** 447ebab2259SFam Zheng * Chooses a default granularity based on the existing cluster size, 448ebab2259SFam Zheng * but clamped between [4K, 64K]. Defaults to 64K in the case that there 449ebab2259SFam Zheng * is no cluster size information available. 450ebab2259SFam Zheng */ 451ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs) 452ebab2259SFam Zheng { 453ebab2259SFam Zheng BlockDriverInfo bdi; 454ebab2259SFam Zheng uint32_t granularity; 455ebab2259SFam Zheng 456ebab2259SFam Zheng if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) { 457ebab2259SFam Zheng granularity = MAX(4096, bdi.cluster_size); 458ebab2259SFam Zheng granularity = MIN(65536, granularity); 459ebab2259SFam Zheng } else { 460ebab2259SFam Zheng granularity = 65536; 461ebab2259SFam Zheng } 462ebab2259SFam Zheng 463ebab2259SFam Zheng return granularity; 464ebab2259SFam Zheng } 465ebab2259SFam Zheng 466ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap) 467ebab2259SFam Zheng { 468*ca759622SEric Blake return 1U << hbitmap_granularity(bitmap->bitmap); 469ebab2259SFam Zheng } 470ebab2259SFam Zheng 471715a74d8SEric Blake BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap) 472ebab2259SFam Zheng { 473dc162c8eSFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 474715a74d8SEric Blake hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0); 475dc162c8eSFam Zheng iter->bitmap = bitmap; 476dc162c8eSFam Zheng bitmap->active_iterators++; 477dc162c8eSFam Zheng return iter; 478dc162c8eSFam Zheng } 479dc162c8eSFam Zheng 4806d3f4049SFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap) 4816d3f4049SFam Zheng { 4826d3f4049SFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 4836d3f4049SFam Zheng hbitmap_iter_init(&iter->hbi, bitmap->meta, 0); 4846d3f4049SFam Zheng iter->bitmap = bitmap; 4856d3f4049SFam Zheng bitmap->active_iterators++; 4866d3f4049SFam Zheng return iter; 4876d3f4049SFam Zheng } 4886d3f4049SFam Zheng 489dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter) 490dc162c8eSFam Zheng { 491dc162c8eSFam Zheng if (!iter) { 492dc162c8eSFam Zheng return; 493dc162c8eSFam Zheng } 494dc162c8eSFam Zheng assert(iter->bitmap->active_iterators > 0); 495dc162c8eSFam Zheng iter->bitmap->active_iterators--; 496dc162c8eSFam Zheng g_free(iter); 497dc162c8eSFam Zheng } 498dc162c8eSFam Zheng 499dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter) 500dc162c8eSFam Zheng { 501*ca759622SEric Blake return hbitmap_iter_next(&iter->hbi); 502ebab2259SFam Zheng } 503ebab2259SFam Zheng 504b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 505b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 506e0d7f73eSEric Blake int64_t offset, int64_t bytes) 507ebab2259SFam Zheng { 508ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 509d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 510*ca759622SEric Blake hbitmap_set(bitmap->bitmap, offset, bytes); 511ebab2259SFam Zheng } 512ebab2259SFam Zheng 513b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap, 514e0d7f73eSEric Blake int64_t offset, int64_t bytes) 515b64bd51eSPaolo Bonzini { 516b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 517e0d7f73eSEric Blake bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes); 518b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 519b64bd51eSPaolo Bonzini } 520b64bd51eSPaolo Bonzini 521b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 522b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 523e0d7f73eSEric Blake int64_t offset, int64_t bytes) 524ebab2259SFam Zheng { 525ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 526d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 527*ca759622SEric Blake hbitmap_reset(bitmap->bitmap, offset, bytes); 528ebab2259SFam Zheng } 529ebab2259SFam Zheng 530b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, 531e0d7f73eSEric Blake int64_t offset, int64_t bytes) 532b64bd51eSPaolo Bonzini { 533b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 534e0d7f73eSEric Blake bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes); 535b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 536b64bd51eSPaolo Bonzini } 537b64bd51eSPaolo Bonzini 538ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out) 539ebab2259SFam Zheng { 540ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 541d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 542b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 543ebab2259SFam Zheng if (!out) { 544ebab2259SFam Zheng hbitmap_reset_all(bitmap->bitmap); 545ebab2259SFam Zheng } else { 546ebab2259SFam Zheng HBitmap *backup = bitmap->bitmap; 547*ca759622SEric Blake bitmap->bitmap = hbitmap_alloc(bitmap->size, 548ebab2259SFam Zheng hbitmap_granularity(backup)); 549ebab2259SFam Zheng *out = backup; 550ebab2259SFam Zheng } 551b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 552ebab2259SFam Zheng } 553ebab2259SFam Zheng 554ebab2259SFam Zheng void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in) 555ebab2259SFam Zheng { 556ebab2259SFam Zheng HBitmap *tmp = bitmap->bitmap; 557ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 558d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 559ebab2259SFam Zheng bitmap->bitmap = in; 560ebab2259SFam Zheng hbitmap_free(tmp); 561ebab2259SFam Zheng } 562ebab2259SFam Zheng 563882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap, 56486f6ae67SEric Blake uint64_t offset, uint64_t bytes) 565882c36f5SVladimir Sementsov-Ogievskiy { 566*ca759622SEric Blake return hbitmap_serialization_size(bitmap->bitmap, offset, bytes); 567882c36f5SVladimir Sementsov-Ogievskiy } 568882c36f5SVladimir Sementsov-Ogievskiy 569882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap) 570882c36f5SVladimir Sementsov-Ogievskiy { 571*ca759622SEric Blake return hbitmap_serialization_align(bitmap->bitmap); 572882c36f5SVladimir Sementsov-Ogievskiy } 573882c36f5SVladimir Sementsov-Ogievskiy 574882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap, 57586f6ae67SEric Blake uint8_t *buf, uint64_t offset, 57686f6ae67SEric Blake uint64_t bytes) 577882c36f5SVladimir Sementsov-Ogievskiy { 578*ca759622SEric Blake hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes); 579882c36f5SVladimir Sementsov-Ogievskiy } 580882c36f5SVladimir Sementsov-Ogievskiy 581882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap, 58286f6ae67SEric Blake uint8_t *buf, uint64_t offset, 58386f6ae67SEric Blake uint64_t bytes, bool finish) 584882c36f5SVladimir Sementsov-Ogievskiy { 585*ca759622SEric Blake hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish); 586882c36f5SVladimir Sementsov-Ogievskiy } 587882c36f5SVladimir Sementsov-Ogievskiy 588882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap, 58986f6ae67SEric Blake uint64_t offset, uint64_t bytes, 590882c36f5SVladimir Sementsov-Ogievskiy bool finish) 591882c36f5SVladimir Sementsov-Ogievskiy { 592*ca759622SEric Blake hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish); 593882c36f5SVladimir Sementsov-Ogievskiy } 594882c36f5SVladimir Sementsov-Ogievskiy 5956bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap, 59686f6ae67SEric Blake uint64_t offset, uint64_t bytes, 5976bdc8b71SVladimir Sementsov-Ogievskiy bool finish) 5986bdc8b71SVladimir Sementsov-Ogievskiy { 599*ca759622SEric Blake hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish); 6006bdc8b71SVladimir Sementsov-Ogievskiy } 6016bdc8b71SVladimir Sementsov-Ogievskiy 602882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap) 603882c36f5SVladimir Sementsov-Ogievskiy { 604882c36f5SVladimir Sementsov-Ogievskiy hbitmap_deserialize_finish(bitmap->bitmap); 605882c36f5SVladimir Sementsov-Ogievskiy } 606882c36f5SVladimir Sementsov-Ogievskiy 6070fdf1a4fSEric Blake void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes) 608ebab2259SFam Zheng { 609ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 6102119882cSPaolo Bonzini 6112119882cSPaolo Bonzini if (QLIST_EMPTY(&bs->dirty_bitmaps)) { 6122119882cSPaolo Bonzini return; 6132119882cSPaolo Bonzini } 6142119882cSPaolo Bonzini 6152119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 616ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 617ebab2259SFam Zheng if (!bdrv_dirty_bitmap_enabled(bitmap)) { 618ebab2259SFam Zheng continue; 619ebab2259SFam Zheng } 620d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 621*ca759622SEric Blake hbitmap_set(bitmap->bitmap, offset, bytes); 622ebab2259SFam Zheng } 6232119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 624ebab2259SFam Zheng } 625ebab2259SFam Zheng 626ebab2259SFam Zheng /** 627dc162c8eSFam Zheng * Advance a BdrvDirtyBitmapIter to an arbitrary offset. 628ebab2259SFam Zheng */ 629715a74d8SEric Blake void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset) 630ebab2259SFam Zheng { 631*ca759622SEric Blake hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset); 632ebab2259SFam Zheng } 633ebab2259SFam Zheng 634ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap) 635ebab2259SFam Zheng { 636*ca759622SEric Blake return hbitmap_count(bitmap->bitmap); 637ebab2259SFam Zheng } 6386d3f4049SFam Zheng 6396d3f4049SFam Zheng int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap) 6406d3f4049SFam Zheng { 6416d3f4049SFam Zheng return hbitmap_count(bitmap->meta); 6426d3f4049SFam Zheng } 643d6883bc9SVladimir Sementsov-Ogievskiy 644d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap) 645d6883bc9SVladimir Sementsov-Ogievskiy { 646d6883bc9SVladimir Sementsov-Ogievskiy return bitmap->readonly; 647d6883bc9SVladimir Sementsov-Ogievskiy } 648d6883bc9SVladimir Sementsov-Ogievskiy 649d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 650d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value) 651d6883bc9SVladimir Sementsov-Ogievskiy { 652d6883bc9SVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 653d6883bc9SVladimir Sementsov-Ogievskiy bitmap->readonly = value; 654d6883bc9SVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 655d6883bc9SVladimir Sementsov-Ogievskiy } 656d6883bc9SVladimir Sementsov-Ogievskiy 657d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs) 658d6883bc9SVladimir Sementsov-Ogievskiy { 659d6883bc9SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 660d6883bc9SVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 661d6883bc9SVladimir Sementsov-Ogievskiy if (bm->readonly) { 662d6883bc9SVladimir Sementsov-Ogievskiy return true; 663d6883bc9SVladimir Sementsov-Ogievskiy } 664d6883bc9SVladimir Sementsov-Ogievskiy } 665d6883bc9SVladimir Sementsov-Ogievskiy 666d6883bc9SVladimir Sementsov-Ogievskiy return false; 667d6883bc9SVladimir Sementsov-Ogievskiy } 668a0319aacSVladimir Sementsov-Ogievskiy 669a0319aacSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 670a0319aacSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload) 671a0319aacSVladimir Sementsov-Ogievskiy { 672a0319aacSVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 673a0319aacSVladimir Sementsov-Ogievskiy bitmap->autoload = autoload; 674a0319aacSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 675a0319aacSVladimir Sementsov-Ogievskiy } 676a0319aacSVladimir Sementsov-Ogievskiy 677a0319aacSVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap) 678a0319aacSVladimir Sementsov-Ogievskiy { 679a0319aacSVladimir Sementsov-Ogievskiy return bitmap->autoload; 680a0319aacSVladimir Sementsov-Ogievskiy } 681a88b179fSVladimir Sementsov-Ogievskiy 682a88b179fSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 683a88b179fSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent) 684a88b179fSVladimir Sementsov-Ogievskiy { 685a88b179fSVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 686a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = persistent; 687a88b179fSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 688a88b179fSVladimir Sementsov-Ogievskiy } 689a88b179fSVladimir Sementsov-Ogievskiy 690a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap) 691a88b179fSVladimir Sementsov-Ogievskiy { 692a88b179fSVladimir Sementsov-Ogievskiy return bitmap->persistent; 693a88b179fSVladimir Sementsov-Ogievskiy } 694a88b179fSVladimir Sementsov-Ogievskiy 695a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs) 696a88b179fSVladimir Sementsov-Ogievskiy { 697a88b179fSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 698a88b179fSVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 699a88b179fSVladimir Sementsov-Ogievskiy if (bm->persistent && !bm->readonly) { 700a88b179fSVladimir Sementsov-Ogievskiy return true; 701a88b179fSVladimir Sementsov-Ogievskiy } 702a88b179fSVladimir Sementsov-Ogievskiy } 703a88b179fSVladimir Sementsov-Ogievskiy 704a88b179fSVladimir Sementsov-Ogievskiy return false; 705a88b179fSVladimir Sementsov-Ogievskiy } 7063dd10a06SVladimir Sementsov-Ogievskiy 7073dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, 7083dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bitmap) 7093dd10a06SVladimir Sementsov-Ogievskiy { 7103dd10a06SVladimir Sementsov-Ogievskiy return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) : 7113dd10a06SVladimir Sementsov-Ogievskiy QLIST_NEXT(bitmap, list); 7123dd10a06SVladimir Sementsov-Ogievskiy } 713a3b52535SVladimir Sementsov-Ogievskiy 714a3b52535SVladimir Sementsov-Ogievskiy char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp) 715a3b52535SVladimir Sementsov-Ogievskiy { 716a3b52535SVladimir Sementsov-Ogievskiy return hbitmap_sha256(bitmap->bitmap, errp); 717a3b52535SVladimir Sementsov-Ogievskiy } 718