1ebab2259SFam Zheng /* 2ebab2259SFam Zheng * Block Dirty Bitmap 3ebab2259SFam Zheng * 4ebab2259SFam Zheng * Copyright (c) 2016 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; 41ebab2259SFam Zheng HBitmap *bitmap; /* Dirty sector 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 */ 45ebab2259SFam Zheng int64_t size; /* Size of the bitmap (Number of sectors) */ 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 uint32_t sector_granularity; 119ebab2259SFam Zheng 120ebab2259SFam Zheng assert((granularity & (granularity - 1)) == 0); 121ebab2259SFam Zheng 122ebab2259SFam Zheng if (name && bdrv_find_dirty_bitmap(bs, name)) { 123ebab2259SFam Zheng error_setg(errp, "Bitmap already exists: %s", name); 124ebab2259SFam Zheng return NULL; 125ebab2259SFam Zheng } 126ebab2259SFam Zheng sector_granularity = granularity >> BDRV_SECTOR_BITS; 127ebab2259SFam Zheng assert(sector_granularity); 128ebab2259SFam Zheng bitmap_size = bdrv_nb_sectors(bs); 129ebab2259SFam Zheng if (bitmap_size < 0) { 130ebab2259SFam Zheng error_setg_errno(errp, -bitmap_size, "could not get length of device"); 131ebab2259SFam Zheng errno = -bitmap_size; 132ebab2259SFam Zheng return NULL; 133ebab2259SFam Zheng } 134ebab2259SFam Zheng bitmap = g_new0(BdrvDirtyBitmap, 1); 135b64bd51eSPaolo Bonzini bitmap->mutex = &bs->dirty_bitmap_mutex; 136ebab2259SFam Zheng bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(sector_granularity)); 137ebab2259SFam Zheng bitmap->size = bitmap_size; 138ebab2259SFam Zheng bitmap->name = g_strdup(name); 139ebab2259SFam Zheng bitmap->disabled = false; 1402119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 141ebab2259SFam Zheng QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list); 1422119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 143ebab2259SFam Zheng return bitmap; 144ebab2259SFam Zheng } 145ebab2259SFam Zheng 146fb933437SFam Zheng /* bdrv_create_meta_dirty_bitmap 147fb933437SFam Zheng * 148fb933437SFam Zheng * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. I.e. 149fb933437SFam Zheng * when a dirty status bit in @bitmap is changed (either from reset to set or 150fb933437SFam Zheng * the other way around), its respective meta dirty bitmap bit will be marked 151fb933437SFam Zheng * dirty as well. 152fb933437SFam Zheng * 153fb933437SFam Zheng * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap. 154fb933437SFam Zheng * @chunk_size: how many bytes of bitmap data does each bit in the meta bitmap 155fb933437SFam Zheng * track. 156fb933437SFam Zheng */ 157fb933437SFam Zheng void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap, 158fb933437SFam Zheng int chunk_size) 159fb933437SFam Zheng { 160fb933437SFam Zheng assert(!bitmap->meta); 161b64bd51eSPaolo Bonzini qemu_mutex_lock(bitmap->mutex); 162fb933437SFam Zheng bitmap->meta = hbitmap_create_meta(bitmap->bitmap, 163fb933437SFam Zheng chunk_size * BITS_PER_BYTE); 164b64bd51eSPaolo Bonzini qemu_mutex_unlock(bitmap->mutex); 165fb933437SFam Zheng } 166fb933437SFam Zheng 167fb933437SFam Zheng void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap) 168fb933437SFam Zheng { 169fb933437SFam Zheng assert(bitmap->meta); 170b64bd51eSPaolo Bonzini qemu_mutex_lock(bitmap->mutex); 171fb933437SFam Zheng hbitmap_free_meta(bitmap->bitmap); 172fb933437SFam Zheng bitmap->meta = NULL; 173b64bd51eSPaolo Bonzini qemu_mutex_unlock(bitmap->mutex); 174fb933437SFam Zheng } 175fb933437SFam Zheng 176b64bd51eSPaolo Bonzini int bdrv_dirty_bitmap_get_meta_locked(BlockDriverState *bs, 177fb933437SFam Zheng BdrvDirtyBitmap *bitmap, int64_t sector, 178fb933437SFam Zheng int nb_sectors) 179fb933437SFam Zheng { 180fb933437SFam Zheng uint64_t i; 181fb933437SFam Zheng int sectors_per_bit = 1 << hbitmap_granularity(bitmap->meta); 182fb933437SFam Zheng 183fb933437SFam Zheng /* To optimize: we can make hbitmap to internally check the range in a 184fb933437SFam Zheng * coarse level, or at least do it word by word. */ 185fb933437SFam Zheng for (i = sector; i < sector + nb_sectors; i += sectors_per_bit) { 186fb933437SFam Zheng if (hbitmap_get(bitmap->meta, i)) { 187fb933437SFam Zheng return true; 188fb933437SFam Zheng } 189fb933437SFam Zheng } 190fb933437SFam Zheng return false; 191fb933437SFam Zheng } 192fb933437SFam Zheng 193b64bd51eSPaolo Bonzini int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs, 194b64bd51eSPaolo Bonzini BdrvDirtyBitmap *bitmap, int64_t sector, 195b64bd51eSPaolo Bonzini int nb_sectors) 196b64bd51eSPaolo Bonzini { 197b64bd51eSPaolo Bonzini bool dirty; 198b64bd51eSPaolo Bonzini 199b64bd51eSPaolo Bonzini qemu_mutex_lock(bitmap->mutex); 200b64bd51eSPaolo Bonzini dirty = bdrv_dirty_bitmap_get_meta_locked(bs, bitmap, sector, nb_sectors); 201b64bd51eSPaolo Bonzini qemu_mutex_unlock(bitmap->mutex); 202b64bd51eSPaolo Bonzini 203b64bd51eSPaolo Bonzini return dirty; 204b64bd51eSPaolo Bonzini } 205b64bd51eSPaolo Bonzini 206fb933437SFam Zheng void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs, 207fb933437SFam Zheng BdrvDirtyBitmap *bitmap, int64_t sector, 208fb933437SFam Zheng int nb_sectors) 209fb933437SFam Zheng { 210b64bd51eSPaolo Bonzini qemu_mutex_lock(bitmap->mutex); 211fb933437SFam Zheng hbitmap_reset(bitmap->meta, sector, nb_sectors); 212b64bd51eSPaolo Bonzini qemu_mutex_unlock(bitmap->mutex); 213fb933437SFam Zheng } 214fb933437SFam Zheng 21515891facSFam Zheng int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap) 21615891facSFam Zheng { 21715891facSFam Zheng return bitmap->size; 21815891facSFam Zheng } 21915891facSFam Zheng 22015891facSFam Zheng const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap) 22115891facSFam Zheng { 22215891facSFam Zheng return bitmap->name; 22315891facSFam Zheng } 22415891facSFam Zheng 2252119882cSPaolo Bonzini /* Called with BQL taken. */ 226ebab2259SFam Zheng bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap) 227ebab2259SFam Zheng { 228ebab2259SFam Zheng return bitmap->successor; 229ebab2259SFam Zheng } 230ebab2259SFam Zheng 2312119882cSPaolo Bonzini /* Called with BQL taken. */ 232ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap) 233ebab2259SFam Zheng { 234ebab2259SFam Zheng return !(bitmap->disabled || bitmap->successor); 235ebab2259SFam Zheng } 236ebab2259SFam Zheng 2372119882cSPaolo Bonzini /* Called with BQL taken. */ 238ebab2259SFam Zheng DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap) 239ebab2259SFam Zheng { 240ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 241ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_FROZEN; 242ebab2259SFam Zheng } else if (!bdrv_dirty_bitmap_enabled(bitmap)) { 243ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_DISABLED; 244ebab2259SFam Zheng } else { 245ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_ACTIVE; 246ebab2259SFam Zheng } 247ebab2259SFam Zheng } 248ebab2259SFam Zheng 249ebab2259SFam Zheng /** 250ebab2259SFam Zheng * Create a successor bitmap destined to replace this bitmap after an operation. 251ebab2259SFam Zheng * Requires that the bitmap is not frozen and has no successor. 2522119882cSPaolo Bonzini * Called with BQL taken. 253ebab2259SFam Zheng */ 254ebab2259SFam Zheng int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, 255ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, Error **errp) 256ebab2259SFam Zheng { 257ebab2259SFam Zheng uint64_t granularity; 258ebab2259SFam Zheng BdrvDirtyBitmap *child; 259ebab2259SFam Zheng 260ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 261ebab2259SFam Zheng error_setg(errp, "Cannot create a successor for a bitmap that is " 262ebab2259SFam Zheng "currently frozen"); 263ebab2259SFam Zheng return -1; 264ebab2259SFam Zheng } 265ebab2259SFam Zheng assert(!bitmap->successor); 266ebab2259SFam Zheng 267ebab2259SFam Zheng /* Create an anonymous successor */ 268ebab2259SFam Zheng granularity = bdrv_dirty_bitmap_granularity(bitmap); 269ebab2259SFam Zheng child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); 270ebab2259SFam Zheng if (!child) { 271ebab2259SFam Zheng return -1; 272ebab2259SFam Zheng } 273ebab2259SFam Zheng 274ebab2259SFam Zheng /* Successor will be on or off based on our current state. */ 275ebab2259SFam Zheng child->disabled = bitmap->disabled; 276ebab2259SFam Zheng 277ebab2259SFam Zheng /* Install the successor and freeze the parent */ 278ebab2259SFam Zheng bitmap->successor = child; 279ebab2259SFam Zheng return 0; 280ebab2259SFam Zheng } 281ebab2259SFam Zheng 282ebab2259SFam Zheng /** 283ebab2259SFam Zheng * For a bitmap with a successor, yield our name to the successor, 284ebab2259SFam Zheng * delete the old bitmap, and return a handle to the new bitmap. 2852119882cSPaolo Bonzini * Called with BQL taken. 286ebab2259SFam Zheng */ 287ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs, 288ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, 289ebab2259SFam Zheng Error **errp) 290ebab2259SFam Zheng { 291ebab2259SFam Zheng char *name; 292ebab2259SFam Zheng BdrvDirtyBitmap *successor = bitmap->successor; 293ebab2259SFam Zheng 294ebab2259SFam Zheng if (successor == NULL) { 295ebab2259SFam Zheng error_setg(errp, "Cannot relinquish control if " 296ebab2259SFam Zheng "there's no successor present"); 297ebab2259SFam Zheng return NULL; 298ebab2259SFam Zheng } 299ebab2259SFam Zheng 300ebab2259SFam Zheng name = bitmap->name; 301ebab2259SFam Zheng bitmap->name = NULL; 302ebab2259SFam Zheng successor->name = name; 303ebab2259SFam Zheng bitmap->successor = NULL; 304a88b179fSVladimir Sementsov-Ogievskiy successor->persistent = bitmap->persistent; 305a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = false; 306a0319aacSVladimir Sementsov-Ogievskiy successor->autoload = bitmap->autoload; 307a0319aacSVladimir Sementsov-Ogievskiy bitmap->autoload = false; 308ebab2259SFam Zheng bdrv_release_dirty_bitmap(bs, bitmap); 309ebab2259SFam Zheng 310ebab2259SFam Zheng return successor; 311ebab2259SFam Zheng } 312ebab2259SFam Zheng 313ebab2259SFam Zheng /** 314ebab2259SFam Zheng * In cases of failure where we can no longer safely delete the parent, 315ebab2259SFam Zheng * we may wish to re-join the parent and child/successor. 316ebab2259SFam Zheng * The merged parent will be un-frozen, but not explicitly re-enabled. 3172119882cSPaolo Bonzini * Called with BQL taken. 318ebab2259SFam Zheng */ 319ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, 320ebab2259SFam Zheng BdrvDirtyBitmap *parent, 321ebab2259SFam Zheng Error **errp) 322ebab2259SFam Zheng { 323ebab2259SFam Zheng BdrvDirtyBitmap *successor = parent->successor; 324ebab2259SFam Zheng 325ebab2259SFam Zheng if (!successor) { 326ebab2259SFam Zheng error_setg(errp, "Cannot reclaim a successor when none is present"); 327ebab2259SFam Zheng return NULL; 328ebab2259SFam Zheng } 329ebab2259SFam Zheng 330ebab2259SFam Zheng if (!hbitmap_merge(parent->bitmap, successor->bitmap)) { 331ebab2259SFam Zheng error_setg(errp, "Merging of parent and successor bitmap failed"); 332ebab2259SFam Zheng return NULL; 333ebab2259SFam Zheng } 334ebab2259SFam Zheng bdrv_release_dirty_bitmap(bs, successor); 335ebab2259SFam Zheng parent->successor = NULL; 336ebab2259SFam Zheng 337ebab2259SFam Zheng return parent; 338ebab2259SFam Zheng } 339ebab2259SFam Zheng 340ebab2259SFam Zheng /** 341ebab2259SFam Zheng * Truncates _all_ bitmaps attached to a BDS. 3422119882cSPaolo Bonzini * Called with BQL taken. 343ebab2259SFam Zheng */ 344ebab2259SFam Zheng void bdrv_dirty_bitmap_truncate(BlockDriverState *bs) 345ebab2259SFam Zheng { 346ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 347ebab2259SFam Zheng uint64_t size = bdrv_nb_sectors(bs); 348ebab2259SFam Zheng 3492119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 350ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 351ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 352dc162c8eSFam Zheng assert(!bitmap->active_iterators); 353ebab2259SFam Zheng hbitmap_truncate(bitmap->bitmap, size); 354ebab2259SFam Zheng bitmap->size = size; 355ebab2259SFam Zheng } 3562119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 357ebab2259SFam Zheng } 358ebab2259SFam Zheng 359*615b5dcfSVladimir Sementsov-Ogievskiy static bool bdrv_dirty_bitmap_has_name(BdrvDirtyBitmap *bitmap) 360*615b5dcfSVladimir Sementsov-Ogievskiy { 361*615b5dcfSVladimir Sementsov-Ogievskiy return !!bdrv_dirty_bitmap_name(bitmap); 362*615b5dcfSVladimir Sementsov-Ogievskiy } 363*615b5dcfSVladimir Sementsov-Ogievskiy 3642119882cSPaolo Bonzini /* Called with BQL taken. */ 365*615b5dcfSVladimir Sementsov-Ogievskiy static void bdrv_do_release_matching_dirty_bitmap( 366*615b5dcfSVladimir Sementsov-Ogievskiy BlockDriverState *bs, BdrvDirtyBitmap *bitmap, 367*615b5dcfSVladimir Sementsov-Ogievskiy bool (*cond)(BdrvDirtyBitmap *bitmap)) 368ebab2259SFam Zheng { 369ebab2259SFam Zheng BdrvDirtyBitmap *bm, *next; 3702119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 371ebab2259SFam Zheng QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { 372*615b5dcfSVladimir Sementsov-Ogievskiy if ((!bitmap || bm == bitmap) && (!cond || cond(bm))) { 373dc162c8eSFam Zheng assert(!bm->active_iterators); 374ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bm)); 375fb933437SFam Zheng assert(!bm->meta); 376ebab2259SFam Zheng QLIST_REMOVE(bm, list); 377ebab2259SFam Zheng hbitmap_free(bm->bitmap); 378ebab2259SFam Zheng g_free(bm->name); 379ebab2259SFam Zheng g_free(bm); 380ebab2259SFam Zheng 381ebab2259SFam Zheng if (bitmap) { 3822119882cSPaolo Bonzini goto out; 383ebab2259SFam Zheng } 384ebab2259SFam Zheng } 385ebab2259SFam Zheng } 3867105007aSFam Zheng if (bitmap) { 3877105007aSFam Zheng abort(); 3887105007aSFam Zheng } 3892119882cSPaolo Bonzini 3902119882cSPaolo Bonzini out: 3912119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 392ebab2259SFam Zheng } 393ebab2259SFam Zheng 3942119882cSPaolo Bonzini /* Called with BQL taken. */ 395ebab2259SFam Zheng void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap) 396ebab2259SFam Zheng { 397*615b5dcfSVladimir Sementsov-Ogievskiy bdrv_do_release_matching_dirty_bitmap(bs, bitmap, NULL); 398ebab2259SFam Zheng } 399ebab2259SFam Zheng 400ebab2259SFam Zheng /** 401ebab2259SFam Zheng * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()). 402ebab2259SFam Zheng * There must not be any frozen bitmaps attached. 40356f364e6SVladimir Sementsov-Ogievskiy * This function does not remove persistent bitmaps from the storage. 4042119882cSPaolo Bonzini * Called with BQL taken. 405ebab2259SFam Zheng */ 406ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) 407ebab2259SFam Zheng { 408*615b5dcfSVladimir Sementsov-Ogievskiy bdrv_do_release_matching_dirty_bitmap(bs, NULL, bdrv_dirty_bitmap_has_name); 409*615b5dcfSVladimir Sementsov-Ogievskiy } 410*615b5dcfSVladimir Sementsov-Ogievskiy 411*615b5dcfSVladimir Sementsov-Ogievskiy /** 412*615b5dcfSVladimir Sementsov-Ogievskiy * Release all persistent dirty bitmaps attached to a BDS (for use in 413*615b5dcfSVladimir Sementsov-Ogievskiy * bdrv_inactivate_recurse()). 414*615b5dcfSVladimir Sementsov-Ogievskiy * There must not be any frozen bitmaps attached. 415*615b5dcfSVladimir Sementsov-Ogievskiy * This function does not remove persistent bitmaps from the storage. 416*615b5dcfSVladimir Sementsov-Ogievskiy */ 417*615b5dcfSVladimir Sementsov-Ogievskiy void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs) 418*615b5dcfSVladimir Sementsov-Ogievskiy { 419*615b5dcfSVladimir Sementsov-Ogievskiy bdrv_do_release_matching_dirty_bitmap(bs, NULL, 420*615b5dcfSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_get_persistance); 421ebab2259SFam Zheng } 422ebab2259SFam Zheng 42356f364e6SVladimir Sementsov-Ogievskiy /** 42456f364e6SVladimir Sementsov-Ogievskiy * Remove persistent dirty bitmap from the storage if it exists. 42556f364e6SVladimir Sementsov-Ogievskiy * Absence of bitmap is not an error, because we have the following scenario: 42656f364e6SVladimir Sementsov-Ogievskiy * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no 42756f364e6SVladimir Sementsov-Ogievskiy * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should 42856f364e6SVladimir Sementsov-Ogievskiy * not fail. 42956f364e6SVladimir Sementsov-Ogievskiy * This function doesn't release corresponding BdrvDirtyBitmap. 43056f364e6SVladimir Sementsov-Ogievskiy */ 43156f364e6SVladimir Sementsov-Ogievskiy void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, 43256f364e6SVladimir Sementsov-Ogievskiy const char *name, 43356f364e6SVladimir Sementsov-Ogievskiy Error **errp) 43456f364e6SVladimir Sementsov-Ogievskiy { 43556f364e6SVladimir Sementsov-Ogievskiy if (bs->drv && bs->drv->bdrv_remove_persistent_dirty_bitmap) { 43656f364e6SVladimir Sementsov-Ogievskiy bs->drv->bdrv_remove_persistent_dirty_bitmap(bs, name, errp); 43756f364e6SVladimir Sementsov-Ogievskiy } 43856f364e6SVladimir Sementsov-Ogievskiy } 43956f364e6SVladimir Sementsov-Ogievskiy 4402119882cSPaolo Bonzini /* Called with BQL taken. */ 441ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 442ebab2259SFam Zheng { 443ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 444ebab2259SFam Zheng bitmap->disabled = true; 445ebab2259SFam Zheng } 446ebab2259SFam Zheng 4472119882cSPaolo Bonzini /* Called with BQL taken. */ 448ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 449ebab2259SFam Zheng { 450ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 451ebab2259SFam Zheng bitmap->disabled = false; 452ebab2259SFam Zheng } 453ebab2259SFam Zheng 454ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs) 455ebab2259SFam Zheng { 456ebab2259SFam Zheng BdrvDirtyBitmap *bm; 457ebab2259SFam Zheng BlockDirtyInfoList *list = NULL; 458ebab2259SFam Zheng BlockDirtyInfoList **plist = &list; 459ebab2259SFam Zheng 4602119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 461ebab2259SFam Zheng QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 462ebab2259SFam Zheng BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1); 463ebab2259SFam Zheng BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1); 464ebab2259SFam Zheng info->count = bdrv_get_dirty_count(bm); 465ebab2259SFam Zheng info->granularity = bdrv_dirty_bitmap_granularity(bm); 466ebab2259SFam Zheng info->has_name = !!bm->name; 467ebab2259SFam Zheng info->name = g_strdup(bm->name); 468ebab2259SFam Zheng info->status = bdrv_dirty_bitmap_status(bm); 469ebab2259SFam Zheng entry->value = info; 470ebab2259SFam Zheng *plist = entry; 471ebab2259SFam Zheng plist = &entry->next; 472ebab2259SFam Zheng } 4732119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 474ebab2259SFam Zheng 475ebab2259SFam Zheng return list; 476ebab2259SFam Zheng } 477ebab2259SFam Zheng 478b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 479b64bd51eSPaolo Bonzini int bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, 480ebab2259SFam Zheng int64_t sector) 481ebab2259SFam Zheng { 482ebab2259SFam Zheng if (bitmap) { 483ebab2259SFam Zheng return hbitmap_get(bitmap->bitmap, sector); 484ebab2259SFam Zheng } else { 485ebab2259SFam Zheng return 0; 486ebab2259SFam Zheng } 487ebab2259SFam Zheng } 488ebab2259SFam Zheng 489ebab2259SFam Zheng /** 490ebab2259SFam Zheng * Chooses a default granularity based on the existing cluster size, 491ebab2259SFam Zheng * but clamped between [4K, 64K]. Defaults to 64K in the case that there 492ebab2259SFam Zheng * is no cluster size information available. 493ebab2259SFam Zheng */ 494ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs) 495ebab2259SFam Zheng { 496ebab2259SFam Zheng BlockDriverInfo bdi; 497ebab2259SFam Zheng uint32_t granularity; 498ebab2259SFam Zheng 499ebab2259SFam Zheng if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) { 500ebab2259SFam Zheng granularity = MAX(4096, bdi.cluster_size); 501ebab2259SFam Zheng granularity = MIN(65536, granularity); 502ebab2259SFam Zheng } else { 503ebab2259SFam Zheng granularity = 65536; 504ebab2259SFam Zheng } 505ebab2259SFam Zheng 506ebab2259SFam Zheng return granularity; 507ebab2259SFam Zheng } 508ebab2259SFam Zheng 509ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap) 510ebab2259SFam Zheng { 511ebab2259SFam Zheng return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->bitmap); 512ebab2259SFam Zheng } 513ebab2259SFam Zheng 5146d3f4049SFam Zheng uint32_t bdrv_dirty_bitmap_meta_granularity(BdrvDirtyBitmap *bitmap) 5156d3f4049SFam Zheng { 5166d3f4049SFam Zheng return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->meta); 5176d3f4049SFam Zheng } 5186d3f4049SFam Zheng 519dc162c8eSFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap, 520dc162c8eSFam Zheng uint64_t first_sector) 521ebab2259SFam Zheng { 522dc162c8eSFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 523dc162c8eSFam Zheng hbitmap_iter_init(&iter->hbi, bitmap->bitmap, first_sector); 524dc162c8eSFam Zheng iter->bitmap = bitmap; 525dc162c8eSFam Zheng bitmap->active_iterators++; 526dc162c8eSFam Zheng return iter; 527dc162c8eSFam Zheng } 528dc162c8eSFam Zheng 5296d3f4049SFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap) 5306d3f4049SFam Zheng { 5316d3f4049SFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 5326d3f4049SFam Zheng hbitmap_iter_init(&iter->hbi, bitmap->meta, 0); 5336d3f4049SFam Zheng iter->bitmap = bitmap; 5346d3f4049SFam Zheng bitmap->active_iterators++; 5356d3f4049SFam Zheng return iter; 5366d3f4049SFam Zheng } 5376d3f4049SFam Zheng 538dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter) 539dc162c8eSFam Zheng { 540dc162c8eSFam Zheng if (!iter) { 541dc162c8eSFam Zheng return; 542dc162c8eSFam Zheng } 543dc162c8eSFam Zheng assert(iter->bitmap->active_iterators > 0); 544dc162c8eSFam Zheng iter->bitmap->active_iterators--; 545dc162c8eSFam Zheng g_free(iter); 546dc162c8eSFam Zheng } 547dc162c8eSFam Zheng 548dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter) 549dc162c8eSFam Zheng { 550dc162c8eSFam Zheng return hbitmap_iter_next(&iter->hbi); 551ebab2259SFam Zheng } 552ebab2259SFam Zheng 553b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 554b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 5556d078599SDenis V. Lunev int64_t cur_sector, int64_t nr_sectors) 556ebab2259SFam Zheng { 557ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 558d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 559ebab2259SFam Zheng hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors); 560ebab2259SFam Zheng } 561ebab2259SFam Zheng 562b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap, 563b64bd51eSPaolo Bonzini int64_t cur_sector, int64_t nr_sectors) 564b64bd51eSPaolo Bonzini { 565b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 566b64bd51eSPaolo Bonzini bdrv_set_dirty_bitmap_locked(bitmap, cur_sector, nr_sectors); 567b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 568b64bd51eSPaolo Bonzini } 569b64bd51eSPaolo Bonzini 570b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 571b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 5726d078599SDenis V. Lunev int64_t cur_sector, int64_t nr_sectors) 573ebab2259SFam Zheng { 574ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 575d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 576ebab2259SFam Zheng hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors); 577ebab2259SFam Zheng } 578ebab2259SFam Zheng 579b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, 580b64bd51eSPaolo Bonzini int64_t cur_sector, int64_t nr_sectors) 581b64bd51eSPaolo Bonzini { 582b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 583b64bd51eSPaolo Bonzini bdrv_reset_dirty_bitmap_locked(bitmap, cur_sector, nr_sectors); 584b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 585b64bd51eSPaolo Bonzini } 586b64bd51eSPaolo Bonzini 587ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out) 588ebab2259SFam Zheng { 589ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 590d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 591b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 592ebab2259SFam Zheng if (!out) { 593ebab2259SFam Zheng hbitmap_reset_all(bitmap->bitmap); 594ebab2259SFam Zheng } else { 595ebab2259SFam Zheng HBitmap *backup = bitmap->bitmap; 596ebab2259SFam Zheng bitmap->bitmap = hbitmap_alloc(bitmap->size, 597ebab2259SFam Zheng hbitmap_granularity(backup)); 598ebab2259SFam Zheng *out = backup; 599ebab2259SFam Zheng } 600b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 601ebab2259SFam Zheng } 602ebab2259SFam Zheng 603ebab2259SFam Zheng void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in) 604ebab2259SFam Zheng { 605ebab2259SFam Zheng HBitmap *tmp = bitmap->bitmap; 606ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 607d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 608ebab2259SFam Zheng bitmap->bitmap = in; 609ebab2259SFam Zheng hbitmap_free(tmp); 610ebab2259SFam Zheng } 611ebab2259SFam Zheng 612882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap, 613882c36f5SVladimir Sementsov-Ogievskiy uint64_t start, uint64_t count) 614882c36f5SVladimir Sementsov-Ogievskiy { 615882c36f5SVladimir Sementsov-Ogievskiy return hbitmap_serialization_size(bitmap->bitmap, start, count); 616882c36f5SVladimir Sementsov-Ogievskiy } 617882c36f5SVladimir Sementsov-Ogievskiy 618882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap) 619882c36f5SVladimir Sementsov-Ogievskiy { 620882c36f5SVladimir Sementsov-Ogievskiy return hbitmap_serialization_granularity(bitmap->bitmap); 621882c36f5SVladimir Sementsov-Ogievskiy } 622882c36f5SVladimir Sementsov-Ogievskiy 623882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap, 624882c36f5SVladimir Sementsov-Ogievskiy uint8_t *buf, uint64_t start, 625882c36f5SVladimir Sementsov-Ogievskiy uint64_t count) 626882c36f5SVladimir Sementsov-Ogievskiy { 627882c36f5SVladimir Sementsov-Ogievskiy hbitmap_serialize_part(bitmap->bitmap, buf, start, count); 628882c36f5SVladimir Sementsov-Ogievskiy } 629882c36f5SVladimir Sementsov-Ogievskiy 630882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap, 631882c36f5SVladimir Sementsov-Ogievskiy uint8_t *buf, uint64_t start, 632882c36f5SVladimir Sementsov-Ogievskiy uint64_t count, bool finish) 633882c36f5SVladimir Sementsov-Ogievskiy { 634882c36f5SVladimir Sementsov-Ogievskiy hbitmap_deserialize_part(bitmap->bitmap, buf, start, count, finish); 635882c36f5SVladimir Sementsov-Ogievskiy } 636882c36f5SVladimir Sementsov-Ogievskiy 637882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap, 638882c36f5SVladimir Sementsov-Ogievskiy uint64_t start, uint64_t count, 639882c36f5SVladimir Sementsov-Ogievskiy bool finish) 640882c36f5SVladimir Sementsov-Ogievskiy { 641882c36f5SVladimir Sementsov-Ogievskiy hbitmap_deserialize_zeroes(bitmap->bitmap, start, count, finish); 642882c36f5SVladimir Sementsov-Ogievskiy } 643882c36f5SVladimir Sementsov-Ogievskiy 6446bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap, 6456bdc8b71SVladimir Sementsov-Ogievskiy uint64_t start, uint64_t count, 6466bdc8b71SVladimir Sementsov-Ogievskiy bool finish) 6476bdc8b71SVladimir Sementsov-Ogievskiy { 6486bdc8b71SVladimir Sementsov-Ogievskiy hbitmap_deserialize_ones(bitmap->bitmap, start, count, finish); 6496bdc8b71SVladimir Sementsov-Ogievskiy } 6506bdc8b71SVladimir Sementsov-Ogievskiy 651882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap) 652882c36f5SVladimir Sementsov-Ogievskiy { 653882c36f5SVladimir Sementsov-Ogievskiy hbitmap_deserialize_finish(bitmap->bitmap); 654882c36f5SVladimir Sementsov-Ogievskiy } 655882c36f5SVladimir Sementsov-Ogievskiy 656ebab2259SFam Zheng void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, 6576d078599SDenis V. Lunev int64_t nr_sectors) 658ebab2259SFam Zheng { 659ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 6602119882cSPaolo Bonzini 6612119882cSPaolo Bonzini if (QLIST_EMPTY(&bs->dirty_bitmaps)) { 6622119882cSPaolo Bonzini return; 6632119882cSPaolo Bonzini } 6642119882cSPaolo Bonzini 6652119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 666ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 667ebab2259SFam Zheng if (!bdrv_dirty_bitmap_enabled(bitmap)) { 668ebab2259SFam Zheng continue; 669ebab2259SFam Zheng } 670d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 671ebab2259SFam Zheng hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors); 672ebab2259SFam Zheng } 6732119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 674ebab2259SFam Zheng } 675ebab2259SFam Zheng 676ebab2259SFam Zheng /** 677dc162c8eSFam Zheng * Advance a BdrvDirtyBitmapIter to an arbitrary offset. 678ebab2259SFam Zheng */ 679dc162c8eSFam Zheng void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t sector_num) 680ebab2259SFam Zheng { 681dc162c8eSFam Zheng hbitmap_iter_init(&iter->hbi, iter->hbi.hb, sector_num); 682ebab2259SFam Zheng } 683ebab2259SFam Zheng 684ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap) 685ebab2259SFam Zheng { 686ebab2259SFam Zheng return hbitmap_count(bitmap->bitmap); 687ebab2259SFam Zheng } 6886d3f4049SFam Zheng 6896d3f4049SFam Zheng int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap) 6906d3f4049SFam Zheng { 6916d3f4049SFam Zheng return hbitmap_count(bitmap->meta); 6926d3f4049SFam Zheng } 693d6883bc9SVladimir Sementsov-Ogievskiy 694d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap) 695d6883bc9SVladimir Sementsov-Ogievskiy { 696d6883bc9SVladimir Sementsov-Ogievskiy return bitmap->readonly; 697d6883bc9SVladimir Sementsov-Ogievskiy } 698d6883bc9SVladimir Sementsov-Ogievskiy 699d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 700d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value) 701d6883bc9SVladimir Sementsov-Ogievskiy { 702d6883bc9SVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 703d6883bc9SVladimir Sementsov-Ogievskiy bitmap->readonly = value; 704d6883bc9SVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 705d6883bc9SVladimir Sementsov-Ogievskiy } 706d6883bc9SVladimir Sementsov-Ogievskiy 707d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs) 708d6883bc9SVladimir Sementsov-Ogievskiy { 709d6883bc9SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 710d6883bc9SVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 711d6883bc9SVladimir Sementsov-Ogievskiy if (bm->readonly) { 712d6883bc9SVladimir Sementsov-Ogievskiy return true; 713d6883bc9SVladimir Sementsov-Ogievskiy } 714d6883bc9SVladimir Sementsov-Ogievskiy } 715d6883bc9SVladimir Sementsov-Ogievskiy 716d6883bc9SVladimir Sementsov-Ogievskiy return false; 717d6883bc9SVladimir Sementsov-Ogievskiy } 718a0319aacSVladimir Sementsov-Ogievskiy 719a0319aacSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 720a0319aacSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_autoload(BdrvDirtyBitmap *bitmap, bool autoload) 721a0319aacSVladimir Sementsov-Ogievskiy { 722a0319aacSVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 723a0319aacSVladimir Sementsov-Ogievskiy bitmap->autoload = autoload; 724a0319aacSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 725a0319aacSVladimir Sementsov-Ogievskiy } 726a0319aacSVladimir Sementsov-Ogievskiy 727a0319aacSVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap) 728a0319aacSVladimir Sementsov-Ogievskiy { 729a0319aacSVladimir Sementsov-Ogievskiy return bitmap->autoload; 730a0319aacSVladimir Sementsov-Ogievskiy } 731a88b179fSVladimir Sementsov-Ogievskiy 732a88b179fSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 733a88b179fSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent) 734a88b179fSVladimir Sementsov-Ogievskiy { 735a88b179fSVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 736a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = persistent; 737a88b179fSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 738a88b179fSVladimir Sementsov-Ogievskiy } 739a88b179fSVladimir Sementsov-Ogievskiy 740a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap) 741a88b179fSVladimir Sementsov-Ogievskiy { 742a88b179fSVladimir Sementsov-Ogievskiy return bitmap->persistent; 743a88b179fSVladimir Sementsov-Ogievskiy } 744a88b179fSVladimir Sementsov-Ogievskiy 745a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs) 746a88b179fSVladimir Sementsov-Ogievskiy { 747a88b179fSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 748a88b179fSVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 749a88b179fSVladimir Sementsov-Ogievskiy if (bm->persistent && !bm->readonly) { 750a88b179fSVladimir Sementsov-Ogievskiy return true; 751a88b179fSVladimir Sementsov-Ogievskiy } 752a88b179fSVladimir Sementsov-Ogievskiy } 753a88b179fSVladimir Sementsov-Ogievskiy 754a88b179fSVladimir Sementsov-Ogievskiy return false; 755a88b179fSVladimir Sementsov-Ogievskiy } 7563dd10a06SVladimir Sementsov-Ogievskiy 7573dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, 7583dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bitmap) 7593dd10a06SVladimir Sementsov-Ogievskiy { 7603dd10a06SVladimir Sementsov-Ogievskiy return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) : 7613dd10a06SVladimir Sementsov-Ogievskiy QLIST_NEXT(bitmap, list); 7623dd10a06SVladimir Sementsov-Ogievskiy } 763a3b52535SVladimir Sementsov-Ogievskiy 764a3b52535SVladimir Sementsov-Ogievskiy char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp) 765a3b52535SVladimir Sementsov-Ogievskiy { 766a3b52535SVladimir Sementsov-Ogievskiy return hbitmap_sha256(bitmap->bitmap, errp); 767a3b52535SVladimir Sementsov-Ogievskiy } 768