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; 41ca759622SEric Blake HBitmap *bitmap; /* Dirty bitmap implementation */ 42fb933437SFam Zheng HBitmap *meta; /* Meta dirty bitmap */ 434f43e953SVladimir Sementsov-Ogievskiy bool qmp_locked; /* Bitmap is locked, it can't be modified 444f43e953SVladimir Sementsov-Ogievskiy through QMP */ 45ebab2259SFam Zheng BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */ 46ebab2259SFam Zheng char *name; /* Optional non-empty unique ID */ 47993e6525SEric Blake int64_t size; /* Size of the bitmap, in bytes */ 488bfc932eSVladimir Sementsov-Ogievskiy bool disabled; /* Bitmap is disabled. It ignores all writes to 498bfc932eSVladimir Sementsov-Ogievskiy the device */ 50dc162c8eSFam Zheng int active_iterators; /* How many iterators are active */ 51d6883bc9SVladimir Sementsov-Ogievskiy bool readonly; /* Bitmap is read-only. This field also 52d6883bc9SVladimir Sementsov-Ogievskiy prevents the respective image from being 53d6883bc9SVladimir Sementsov-Ogievskiy modified (i.e. blocks writes and discards). 54d6883bc9SVladimir Sementsov-Ogievskiy Such operations must fail and both the image 55d6883bc9SVladimir Sementsov-Ogievskiy and this bitmap must remain unchanged while 56d6883bc9SVladimir Sementsov-Ogievskiy this flag is set. */ 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 BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, 102ebab2259SFam Zheng uint32_t granularity, 103ebab2259SFam Zheng const char *name, 104ebab2259SFam Zheng Error **errp) 105ebab2259SFam Zheng { 106ebab2259SFam Zheng int64_t bitmap_size; 107ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 108ebab2259SFam Zheng 109993e6525SEric Blake assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE); 110ebab2259SFam Zheng 111ebab2259SFam Zheng if (name && bdrv_find_dirty_bitmap(bs, name)) { 112ebab2259SFam Zheng error_setg(errp, "Bitmap already exists: %s", name); 113ebab2259SFam Zheng return NULL; 114ebab2259SFam Zheng } 115993e6525SEric Blake bitmap_size = bdrv_getlength(bs); 116ebab2259SFam Zheng if (bitmap_size < 0) { 117ebab2259SFam Zheng error_setg_errno(errp, -bitmap_size, "could not get length of device"); 118ebab2259SFam Zheng errno = -bitmap_size; 119ebab2259SFam Zheng return NULL; 120ebab2259SFam Zheng } 121ebab2259SFam Zheng bitmap = g_new0(BdrvDirtyBitmap, 1); 122b64bd51eSPaolo Bonzini bitmap->mutex = &bs->dirty_bitmap_mutex; 123ca759622SEric Blake bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity)); 124ebab2259SFam Zheng bitmap->size = bitmap_size; 125ebab2259SFam Zheng bitmap->name = g_strdup(name); 126ebab2259SFam Zheng bitmap->disabled = false; 1272119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 128ebab2259SFam Zheng QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list); 1292119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 130ebab2259SFam Zheng return bitmap; 131ebab2259SFam Zheng } 132ebab2259SFam Zheng 133fb933437SFam Zheng /* bdrv_create_meta_dirty_bitmap 134fb933437SFam Zheng * 135fb933437SFam Zheng * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. I.e. 136fb933437SFam Zheng * when a dirty status bit in @bitmap is changed (either from reset to set or 137fb933437SFam Zheng * the other way around), its respective meta dirty bitmap bit will be marked 138fb933437SFam Zheng * dirty as well. 139fb933437SFam Zheng * 140fb933437SFam Zheng * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap. 141fb933437SFam Zheng * @chunk_size: how many bytes of bitmap data does each bit in the meta bitmap 142fb933437SFam Zheng * track. 143fb933437SFam Zheng */ 144fb933437SFam Zheng void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap, 145fb933437SFam Zheng int chunk_size) 146fb933437SFam Zheng { 147fb933437SFam Zheng assert(!bitmap->meta); 148b64bd51eSPaolo Bonzini qemu_mutex_lock(bitmap->mutex); 149fb933437SFam Zheng bitmap->meta = hbitmap_create_meta(bitmap->bitmap, 150fb933437SFam Zheng chunk_size * BITS_PER_BYTE); 151b64bd51eSPaolo Bonzini qemu_mutex_unlock(bitmap->mutex); 152fb933437SFam Zheng } 153fb933437SFam Zheng 154fb933437SFam Zheng void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap) 155fb933437SFam Zheng { 156fb933437SFam Zheng assert(bitmap->meta); 157b64bd51eSPaolo Bonzini qemu_mutex_lock(bitmap->mutex); 158fb933437SFam Zheng hbitmap_free_meta(bitmap->bitmap); 159fb933437SFam Zheng bitmap->meta = NULL; 160b64bd51eSPaolo Bonzini qemu_mutex_unlock(bitmap->mutex); 161fb933437SFam Zheng } 162fb933437SFam Zheng 16315891facSFam Zheng int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap) 16415891facSFam Zheng { 165993e6525SEric Blake return bitmap->size; 16615891facSFam Zheng } 16715891facSFam Zheng 16815891facSFam Zheng const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap) 16915891facSFam Zheng { 17015891facSFam Zheng return bitmap->name; 17115891facSFam Zheng } 17215891facSFam Zheng 1732119882cSPaolo Bonzini /* Called with BQL taken. */ 174ebab2259SFam Zheng bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap) 175ebab2259SFam Zheng { 176ebab2259SFam Zheng return bitmap->successor; 177ebab2259SFam Zheng } 178ebab2259SFam Zheng 1794f43e953SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked) 1804f43e953SVladimir Sementsov-Ogievskiy { 1814f43e953SVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 1824f43e953SVladimir Sementsov-Ogievskiy bitmap->qmp_locked = qmp_locked; 1834f43e953SVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 1844f43e953SVladimir Sementsov-Ogievskiy } 1854f43e953SVladimir Sementsov-Ogievskiy 1864f43e953SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_qmp_locked(BdrvDirtyBitmap *bitmap) 1874f43e953SVladimir Sementsov-Ogievskiy { 1884f43e953SVladimir Sementsov-Ogievskiy return bitmap->qmp_locked; 1894f43e953SVladimir Sementsov-Ogievskiy } 1904f43e953SVladimir Sementsov-Ogievskiy 1912119882cSPaolo Bonzini /* Called with BQL taken. */ 192ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap) 193ebab2259SFam Zheng { 194ebab2259SFam Zheng return !(bitmap->disabled || bitmap->successor); 195ebab2259SFam Zheng } 196ebab2259SFam Zheng 1972119882cSPaolo Bonzini /* Called with BQL taken. */ 198ebab2259SFam Zheng DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap) 199ebab2259SFam Zheng { 200ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 201ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_FROZEN; 2024f43e953SVladimir Sementsov-Ogievskiy } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) { 2034f43e953SVladimir Sementsov-Ogievskiy return DIRTY_BITMAP_STATUS_LOCKED; 204ebab2259SFam Zheng } else if (!bdrv_dirty_bitmap_enabled(bitmap)) { 205ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_DISABLED; 206ebab2259SFam Zheng } else { 207ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_ACTIVE; 208ebab2259SFam Zheng } 209ebab2259SFam Zheng } 210ebab2259SFam Zheng 211ebab2259SFam Zheng /** 212ebab2259SFam Zheng * Create a successor bitmap destined to replace this bitmap after an operation. 213ebab2259SFam Zheng * Requires that the bitmap is not frozen and has no successor. 2142119882cSPaolo Bonzini * Called with BQL taken. 215ebab2259SFam Zheng */ 216ebab2259SFam Zheng int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, 217ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, Error **errp) 218ebab2259SFam Zheng { 219ebab2259SFam Zheng uint64_t granularity; 220ebab2259SFam Zheng BdrvDirtyBitmap *child; 221ebab2259SFam Zheng 222ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 223ebab2259SFam Zheng error_setg(errp, "Cannot create a successor for a bitmap that is " 224ebab2259SFam Zheng "currently frozen"); 225ebab2259SFam Zheng return -1; 226ebab2259SFam Zheng } 227ebab2259SFam Zheng assert(!bitmap->successor); 228ebab2259SFam Zheng 229ebab2259SFam Zheng /* Create an anonymous successor */ 230ebab2259SFam Zheng granularity = bdrv_dirty_bitmap_granularity(bitmap); 231ebab2259SFam Zheng child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); 232ebab2259SFam Zheng if (!child) { 233ebab2259SFam Zheng return -1; 234ebab2259SFam Zheng } 235ebab2259SFam Zheng 236ebab2259SFam Zheng /* Successor will be on or off based on our current state. */ 237ebab2259SFam Zheng child->disabled = bitmap->disabled; 238ebab2259SFam Zheng 239ebab2259SFam Zheng /* Install the successor and freeze the parent */ 240ebab2259SFam Zheng bitmap->successor = child; 241ebab2259SFam Zheng return 0; 242ebab2259SFam Zheng } 243ebab2259SFam Zheng 24492bcea40SVladimir Sementsov-Ogievskiy void bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap) 24592bcea40SVladimir Sementsov-Ogievskiy { 24692bcea40SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_frozen(bitmap)); 24792bcea40SVladimir Sementsov-Ogievskiy bitmap->disabled = false; 24892bcea40SVladimir Sementsov-Ogievskiy } 24992bcea40SVladimir Sementsov-Ogievskiy 250e73a265eSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 251e73a265eSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap) 252e73a265eSVladimir Sementsov-Ogievskiy { 25358f72b96SVladimir Sementsov-Ogievskiy assert(bitmap->mutex == bitmap->successor->mutex); 254e73a265eSVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 25558f72b96SVladimir Sementsov-Ogievskiy bdrv_enable_dirty_bitmap_locked(bitmap->successor); 256e73a265eSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 257e73a265eSVladimir Sementsov-Ogievskiy } 258e73a265eSVladimir Sementsov-Ogievskiy 259b133c27fSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken. */ 260b133c27fSPaolo Bonzini static void bdrv_release_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap) 261604ab74bSVladimir Sementsov-Ogievskiy { 262b133c27fSPaolo Bonzini assert(!bitmap->active_iterators); 263b133c27fSPaolo Bonzini assert(!bdrv_dirty_bitmap_frozen(bitmap)); 264b133c27fSPaolo Bonzini assert(!bitmap->meta); 265b133c27fSPaolo Bonzini QLIST_REMOVE(bitmap, list); 266b133c27fSPaolo Bonzini hbitmap_free(bitmap->bitmap); 267b133c27fSPaolo Bonzini g_free(bitmap->name); 268b133c27fSPaolo Bonzini g_free(bitmap); 269604ab74bSVladimir Sementsov-Ogievskiy } 270604ab74bSVladimir Sementsov-Ogievskiy 271ebab2259SFam Zheng /** 272ebab2259SFam Zheng * For a bitmap with a successor, yield our name to the successor, 273ebab2259SFam Zheng * delete the old bitmap, and return a handle to the new bitmap. 2742119882cSPaolo Bonzini * Called with BQL taken. 275ebab2259SFam Zheng */ 276ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs, 277ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, 278ebab2259SFam Zheng Error **errp) 279ebab2259SFam Zheng { 280ebab2259SFam Zheng char *name; 281ebab2259SFam Zheng BdrvDirtyBitmap *successor = bitmap->successor; 282ebab2259SFam Zheng 283ebab2259SFam Zheng if (successor == NULL) { 284ebab2259SFam Zheng error_setg(errp, "Cannot relinquish control if " 285ebab2259SFam Zheng "there's no successor present"); 286ebab2259SFam Zheng return NULL; 287ebab2259SFam Zheng } 288ebab2259SFam Zheng 289ebab2259SFam Zheng name = bitmap->name; 290ebab2259SFam Zheng bitmap->name = NULL; 291ebab2259SFam Zheng successor->name = name; 292ebab2259SFam Zheng bitmap->successor = NULL; 293a88b179fSVladimir Sementsov-Ogievskiy successor->persistent = bitmap->persistent; 294a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = false; 295ebab2259SFam Zheng bdrv_release_dirty_bitmap(bs, bitmap); 296ebab2259SFam Zheng 297ebab2259SFam Zheng return successor; 298ebab2259SFam Zheng } 299ebab2259SFam Zheng 300ebab2259SFam Zheng /** 301ebab2259SFam Zheng * In cases of failure where we can no longer safely delete the parent, 302ebab2259SFam Zheng * we may wish to re-join the parent and child/successor. 303ebab2259SFam Zheng * The merged parent will be un-frozen, but not explicitly re-enabled. 304044ee8e1SVladimir Sementsov-Ogievskiy * Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken. 305ebab2259SFam Zheng */ 306044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs, 307ebab2259SFam Zheng BdrvDirtyBitmap *parent, 308ebab2259SFam Zheng Error **errp) 309ebab2259SFam Zheng { 310044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *successor = parent->successor; 311ebab2259SFam Zheng 312ebab2259SFam Zheng if (!successor) { 313ebab2259SFam Zheng error_setg(errp, "Cannot reclaim a successor when none is present"); 314ebab2259SFam Zheng return NULL; 315ebab2259SFam Zheng } 316ebab2259SFam Zheng 317ebab2259SFam Zheng if (!hbitmap_merge(parent->bitmap, successor->bitmap)) { 318ebab2259SFam Zheng error_setg(errp, "Merging of parent and successor bitmap failed"); 319ebab2259SFam Zheng return NULL; 320ebab2259SFam Zheng } 321b133c27fSPaolo Bonzini bdrv_release_dirty_bitmap_locked(successor); 322ebab2259SFam Zheng parent->successor = NULL; 323ebab2259SFam Zheng 324044ee8e1SVladimir Sementsov-Ogievskiy return parent; 325044ee8e1SVladimir Sementsov-Ogievskiy } 326044ee8e1SVladimir Sementsov-Ogievskiy 327044ee8e1SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 328044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, 329044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *parent, 330044ee8e1SVladimir Sementsov-Ogievskiy Error **errp) 331044ee8e1SVladimir Sementsov-Ogievskiy { 332044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *ret; 333044ee8e1SVladimir Sementsov-Ogievskiy 334044ee8e1SVladimir Sementsov-Ogievskiy qemu_mutex_lock(parent->mutex); 335044ee8e1SVladimir Sementsov-Ogievskiy ret = bdrv_reclaim_dirty_bitmap_locked(bs, parent, errp); 336604ab74bSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(parent->mutex); 337604ab74bSVladimir Sementsov-Ogievskiy 338044ee8e1SVladimir Sementsov-Ogievskiy return ret; 339ebab2259SFam Zheng } 340ebab2259SFam Zheng 341ebab2259SFam Zheng /** 342ebab2259SFam Zheng * Truncates _all_ bitmaps attached to a BDS. 3432119882cSPaolo Bonzini * Called with BQL taken. 344ebab2259SFam Zheng */ 3451b6cc579SEric Blake void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes) 346ebab2259SFam Zheng { 347ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 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); 353ca759622SEric Blake hbitmap_truncate(bitmap->bitmap, bytes); 354993e6525SEric Blake bitmap->size = bytes; 355ebab2259SFam Zheng } 3562119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 357ebab2259SFam Zheng } 358ebab2259SFam Zheng 3592119882cSPaolo Bonzini /* Called with BQL taken. */ 360ebab2259SFam Zheng void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap) 361ebab2259SFam Zheng { 362b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 363b133c27fSPaolo Bonzini bdrv_release_dirty_bitmap_locked(bitmap); 364b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 365ebab2259SFam Zheng } 366ebab2259SFam Zheng 367ebab2259SFam Zheng /** 368ebab2259SFam Zheng * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()). 369ebab2259SFam Zheng * There must not be any frozen bitmaps attached. 37056f364e6SVladimir Sementsov-Ogievskiy * This function does not remove persistent bitmaps from the storage. 3712119882cSPaolo Bonzini * Called with BQL taken. 372ebab2259SFam Zheng */ 373ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) 374ebab2259SFam Zheng { 375b133c27fSPaolo Bonzini BdrvDirtyBitmap *bm, *next; 376b133c27fSPaolo Bonzini 377b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 378b133c27fSPaolo Bonzini QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { 379b133c27fSPaolo Bonzini if (bdrv_dirty_bitmap_name(bm)) { 380b133c27fSPaolo Bonzini bdrv_release_dirty_bitmap_locked(bm); 381b133c27fSPaolo Bonzini } 382b133c27fSPaolo Bonzini } 383b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 384615b5dcfSVladimir Sementsov-Ogievskiy } 385615b5dcfSVladimir Sementsov-Ogievskiy 386615b5dcfSVladimir Sementsov-Ogievskiy /** 387615b5dcfSVladimir Sementsov-Ogievskiy * Release all persistent dirty bitmaps attached to a BDS (for use in 388615b5dcfSVladimir Sementsov-Ogievskiy * bdrv_inactivate_recurse()). 389615b5dcfSVladimir Sementsov-Ogievskiy * There must not be any frozen bitmaps attached. 390615b5dcfSVladimir Sementsov-Ogievskiy * This function does not remove persistent bitmaps from the storage. 391b133c27fSPaolo Bonzini * Called with BQL taken. 392615b5dcfSVladimir Sementsov-Ogievskiy */ 393615b5dcfSVladimir Sementsov-Ogievskiy void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs) 394615b5dcfSVladimir Sementsov-Ogievskiy { 395b133c27fSPaolo Bonzini BdrvDirtyBitmap *bm, *next; 396b133c27fSPaolo Bonzini 397b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 398b133c27fSPaolo Bonzini QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { 399b133c27fSPaolo Bonzini if (bdrv_dirty_bitmap_get_persistance(bm)) { 400b133c27fSPaolo Bonzini bdrv_release_dirty_bitmap_locked(bm); 401b133c27fSPaolo Bonzini } 402b133c27fSPaolo Bonzini } 403b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 404ebab2259SFam Zheng } 405ebab2259SFam Zheng 40656f364e6SVladimir Sementsov-Ogievskiy /** 40756f364e6SVladimir Sementsov-Ogievskiy * Remove persistent dirty bitmap from the storage if it exists. 40856f364e6SVladimir Sementsov-Ogievskiy * Absence of bitmap is not an error, because we have the following scenario: 40956f364e6SVladimir Sementsov-Ogievskiy * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no 41056f364e6SVladimir Sementsov-Ogievskiy * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should 41156f364e6SVladimir Sementsov-Ogievskiy * not fail. 41256f364e6SVladimir Sementsov-Ogievskiy * This function doesn't release corresponding BdrvDirtyBitmap. 41356f364e6SVladimir Sementsov-Ogievskiy */ 41456f364e6SVladimir Sementsov-Ogievskiy void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, 41556f364e6SVladimir Sementsov-Ogievskiy const char *name, 41656f364e6SVladimir Sementsov-Ogievskiy Error **errp) 41756f364e6SVladimir Sementsov-Ogievskiy { 41856f364e6SVladimir Sementsov-Ogievskiy if (bs->drv && bs->drv->bdrv_remove_persistent_dirty_bitmap) { 41956f364e6SVladimir Sementsov-Ogievskiy bs->drv->bdrv_remove_persistent_dirty_bitmap(bs, name, errp); 42056f364e6SVladimir Sementsov-Ogievskiy } 42156f364e6SVladimir Sementsov-Ogievskiy } 42256f364e6SVladimir Sementsov-Ogievskiy 423ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 424ebab2259SFam Zheng { 4258b1402ceSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_lock(bitmap); 426ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 427ebab2259SFam Zheng bitmap->disabled = true; 4288b1402ceSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_unlock(bitmap); 429ebab2259SFam Zheng } 430ebab2259SFam Zheng 431ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 432ebab2259SFam Zheng { 4338b1402ceSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_lock(bitmap); 43492bcea40SVladimir Sementsov-Ogievskiy bdrv_enable_dirty_bitmap_locked(bitmap); 4358b1402ceSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_unlock(bitmap); 436ebab2259SFam Zheng } 437ebab2259SFam Zheng 438ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs) 439ebab2259SFam Zheng { 440ebab2259SFam Zheng BdrvDirtyBitmap *bm; 441ebab2259SFam Zheng BlockDirtyInfoList *list = NULL; 442ebab2259SFam Zheng BlockDirtyInfoList **plist = &list; 443ebab2259SFam Zheng 4442119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 445ebab2259SFam Zheng QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 446ebab2259SFam Zheng BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1); 447ebab2259SFam Zheng BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1); 4489a46dba7SEric Blake info->count = bdrv_get_dirty_count(bm); 449ebab2259SFam Zheng info->granularity = bdrv_dirty_bitmap_granularity(bm); 450ebab2259SFam Zheng info->has_name = !!bm->name; 451ebab2259SFam Zheng info->name = g_strdup(bm->name); 452ebab2259SFam Zheng info->status = bdrv_dirty_bitmap_status(bm); 453ebab2259SFam Zheng entry->value = info; 454ebab2259SFam Zheng *plist = entry; 455ebab2259SFam Zheng plist = &entry->next; 456ebab2259SFam Zheng } 4572119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 458ebab2259SFam Zheng 459ebab2259SFam Zheng return list; 460ebab2259SFam Zheng } 461ebab2259SFam Zheng 462b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 4633b5d4df0SEric Blake bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, 4643b5d4df0SEric Blake int64_t offset) 465ebab2259SFam Zheng { 466ebab2259SFam Zheng if (bitmap) { 467ca759622SEric Blake return hbitmap_get(bitmap->bitmap, offset); 468ebab2259SFam Zheng } else { 4693b5d4df0SEric Blake return false; 470ebab2259SFam Zheng } 471ebab2259SFam Zheng } 472ebab2259SFam Zheng 473ebab2259SFam Zheng /** 474ebab2259SFam Zheng * Chooses a default granularity based on the existing cluster size, 475ebab2259SFam Zheng * but clamped between [4K, 64K]. Defaults to 64K in the case that there 476ebab2259SFam Zheng * is no cluster size information available. 477ebab2259SFam Zheng */ 478ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs) 479ebab2259SFam Zheng { 480ebab2259SFam Zheng BlockDriverInfo bdi; 481ebab2259SFam Zheng uint32_t granularity; 482ebab2259SFam Zheng 483ebab2259SFam Zheng if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) { 484ebab2259SFam Zheng granularity = MAX(4096, bdi.cluster_size); 485ebab2259SFam Zheng granularity = MIN(65536, granularity); 486ebab2259SFam Zheng } else { 487ebab2259SFam Zheng granularity = 65536; 488ebab2259SFam Zheng } 489ebab2259SFam Zheng 490ebab2259SFam Zheng return granularity; 491ebab2259SFam Zheng } 492ebab2259SFam Zheng 493ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap) 494ebab2259SFam Zheng { 495ca759622SEric Blake return 1U << hbitmap_granularity(bitmap->bitmap); 496ebab2259SFam Zheng } 497ebab2259SFam Zheng 498715a74d8SEric Blake BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap) 499ebab2259SFam Zheng { 500dc162c8eSFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 501715a74d8SEric Blake hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0); 502dc162c8eSFam Zheng iter->bitmap = bitmap; 503dc162c8eSFam Zheng bitmap->active_iterators++; 504dc162c8eSFam Zheng return iter; 505dc162c8eSFam Zheng } 506dc162c8eSFam Zheng 5076d3f4049SFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap) 5086d3f4049SFam Zheng { 5096d3f4049SFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 5106d3f4049SFam Zheng hbitmap_iter_init(&iter->hbi, bitmap->meta, 0); 5116d3f4049SFam Zheng iter->bitmap = bitmap; 5126d3f4049SFam Zheng bitmap->active_iterators++; 5136d3f4049SFam Zheng return iter; 5146d3f4049SFam Zheng } 5156d3f4049SFam Zheng 516dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter) 517dc162c8eSFam Zheng { 518dc162c8eSFam Zheng if (!iter) { 519dc162c8eSFam Zheng return; 520dc162c8eSFam Zheng } 521dc162c8eSFam Zheng assert(iter->bitmap->active_iterators > 0); 522dc162c8eSFam Zheng iter->bitmap->active_iterators--; 523dc162c8eSFam Zheng g_free(iter); 524dc162c8eSFam Zheng } 525dc162c8eSFam Zheng 526dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter) 527dc162c8eSFam Zheng { 528a33fbb4fSMax Reitz return hbitmap_iter_next(&iter->hbi, true); 529ebab2259SFam Zheng } 530ebab2259SFam Zheng 53172d10a94SMax Reitz /** 53272d10a94SMax Reitz * Return the next consecutively dirty area in the dirty bitmap 53372d10a94SMax Reitz * belonging to the given iterator @iter. 53472d10a94SMax Reitz * 53572d10a94SMax Reitz * @max_offset: Maximum value that may be returned for 53672d10a94SMax Reitz * *offset + *bytes 53772d10a94SMax Reitz * @offset: Will contain the start offset of the next dirty area 53872d10a94SMax Reitz * @bytes: Will contain the length of the next dirty area 53972d10a94SMax Reitz * 54072d10a94SMax Reitz * Returns: True if a dirty area could be found before max_offset 54172d10a94SMax Reitz * (which means that *offset and *bytes then contain valid 54272d10a94SMax Reitz * values), false otherwise. 54372d10a94SMax Reitz * 54472d10a94SMax Reitz * Note that @iter is never advanced if false is returned. If an area 54572d10a94SMax Reitz * is found (which means that true is returned), it will be advanced 54672d10a94SMax Reitz * past that area. 54772d10a94SMax Reitz */ 54872d10a94SMax Reitz bool bdrv_dirty_iter_next_area(BdrvDirtyBitmapIter *iter, uint64_t max_offset, 54972d10a94SMax Reitz uint64_t *offset, int *bytes) 55072d10a94SMax Reitz { 55172d10a94SMax Reitz uint32_t granularity = bdrv_dirty_bitmap_granularity(iter->bitmap); 55272d10a94SMax Reitz uint64_t gran_max_offset; 55372d10a94SMax Reitz int64_t ret; 55472d10a94SMax Reitz int size; 55572d10a94SMax Reitz 55672d10a94SMax Reitz if (max_offset == iter->bitmap->size) { 55772d10a94SMax Reitz /* If max_offset points to the image end, round it up by the 55872d10a94SMax Reitz * bitmap granularity */ 55972d10a94SMax Reitz gran_max_offset = ROUND_UP(max_offset, granularity); 56072d10a94SMax Reitz } else { 56172d10a94SMax Reitz gran_max_offset = max_offset; 56272d10a94SMax Reitz } 56372d10a94SMax Reitz 56472d10a94SMax Reitz ret = hbitmap_iter_next(&iter->hbi, false); 56572d10a94SMax Reitz if (ret < 0 || ret + granularity > gran_max_offset) { 56672d10a94SMax Reitz return false; 56772d10a94SMax Reitz } 56872d10a94SMax Reitz 56972d10a94SMax Reitz *offset = ret; 57072d10a94SMax Reitz size = 0; 57172d10a94SMax Reitz 57272d10a94SMax Reitz assert(granularity <= INT_MAX); 57372d10a94SMax Reitz 57472d10a94SMax Reitz do { 57572d10a94SMax Reitz /* Advance iterator */ 57672d10a94SMax Reitz ret = hbitmap_iter_next(&iter->hbi, true); 57772d10a94SMax Reitz size += granularity; 57872d10a94SMax Reitz } while (ret + granularity <= gran_max_offset && 57972d10a94SMax Reitz hbitmap_iter_next(&iter->hbi, false) == ret + granularity && 58072d10a94SMax Reitz size <= INT_MAX - granularity); 58172d10a94SMax Reitz 58272d10a94SMax Reitz *bytes = MIN(size, max_offset - *offset); 58372d10a94SMax Reitz return true; 58472d10a94SMax Reitz } 58572d10a94SMax Reitz 586b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 587b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 588e0d7f73eSEric Blake int64_t offset, int64_t bytes) 589ebab2259SFam Zheng { 590ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 591d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 592ca759622SEric Blake hbitmap_set(bitmap->bitmap, offset, bytes); 593ebab2259SFam Zheng } 594ebab2259SFam Zheng 595b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap, 596e0d7f73eSEric Blake int64_t offset, int64_t bytes) 597b64bd51eSPaolo Bonzini { 598b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 599e0d7f73eSEric Blake bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes); 600b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 601b64bd51eSPaolo Bonzini } 602b64bd51eSPaolo Bonzini 603b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 604b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 605e0d7f73eSEric Blake int64_t offset, int64_t bytes) 606ebab2259SFam Zheng { 607ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 608d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 609ca759622SEric Blake hbitmap_reset(bitmap->bitmap, offset, bytes); 610ebab2259SFam Zheng } 611ebab2259SFam Zheng 612b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, 613e0d7f73eSEric Blake int64_t offset, int64_t bytes) 614b64bd51eSPaolo Bonzini { 615b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 616e0d7f73eSEric Blake bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes); 617b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 618b64bd51eSPaolo Bonzini } 619b64bd51eSPaolo Bonzini 620ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out) 621ebab2259SFam Zheng { 622ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 623d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 624b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 625ebab2259SFam Zheng if (!out) { 626ebab2259SFam Zheng hbitmap_reset_all(bitmap->bitmap); 627ebab2259SFam Zheng } else { 628ebab2259SFam Zheng HBitmap *backup = bitmap->bitmap; 629ca759622SEric Blake bitmap->bitmap = hbitmap_alloc(bitmap->size, 630ebab2259SFam Zheng hbitmap_granularity(backup)); 631ebab2259SFam Zheng *out = backup; 632ebab2259SFam Zheng } 633b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 634ebab2259SFam Zheng } 635ebab2259SFam Zheng 636ebab2259SFam Zheng void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in) 637ebab2259SFam Zheng { 638ebab2259SFam Zheng HBitmap *tmp = bitmap->bitmap; 639ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 640d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 641ebab2259SFam Zheng bitmap->bitmap = in; 642ebab2259SFam Zheng hbitmap_free(tmp); 643ebab2259SFam Zheng } 644ebab2259SFam Zheng 645882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap, 64686f6ae67SEric Blake uint64_t offset, uint64_t bytes) 647882c36f5SVladimir Sementsov-Ogievskiy { 648ca759622SEric Blake return hbitmap_serialization_size(bitmap->bitmap, offset, bytes); 649882c36f5SVladimir Sementsov-Ogievskiy } 650882c36f5SVladimir Sementsov-Ogievskiy 651882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap) 652882c36f5SVladimir Sementsov-Ogievskiy { 653ca759622SEric Blake return hbitmap_serialization_align(bitmap->bitmap); 654882c36f5SVladimir Sementsov-Ogievskiy } 655882c36f5SVladimir Sementsov-Ogievskiy 656882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap, 65786f6ae67SEric Blake uint8_t *buf, uint64_t offset, 65886f6ae67SEric Blake uint64_t bytes) 659882c36f5SVladimir Sementsov-Ogievskiy { 660ca759622SEric Blake hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes); 661882c36f5SVladimir Sementsov-Ogievskiy } 662882c36f5SVladimir Sementsov-Ogievskiy 663882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap, 66486f6ae67SEric Blake uint8_t *buf, uint64_t offset, 66586f6ae67SEric Blake uint64_t bytes, bool finish) 666882c36f5SVladimir Sementsov-Ogievskiy { 667ca759622SEric Blake hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish); 668882c36f5SVladimir Sementsov-Ogievskiy } 669882c36f5SVladimir Sementsov-Ogievskiy 670882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap, 67186f6ae67SEric Blake uint64_t offset, uint64_t bytes, 672882c36f5SVladimir Sementsov-Ogievskiy bool finish) 673882c36f5SVladimir Sementsov-Ogievskiy { 674ca759622SEric Blake hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish); 675882c36f5SVladimir Sementsov-Ogievskiy } 676882c36f5SVladimir Sementsov-Ogievskiy 6776bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap, 67886f6ae67SEric Blake uint64_t offset, uint64_t bytes, 6796bdc8b71SVladimir Sementsov-Ogievskiy bool finish) 6806bdc8b71SVladimir Sementsov-Ogievskiy { 681ca759622SEric Blake hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish); 6826bdc8b71SVladimir Sementsov-Ogievskiy } 6836bdc8b71SVladimir Sementsov-Ogievskiy 684882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap) 685882c36f5SVladimir Sementsov-Ogievskiy { 686882c36f5SVladimir Sementsov-Ogievskiy hbitmap_deserialize_finish(bitmap->bitmap); 687882c36f5SVladimir Sementsov-Ogievskiy } 688882c36f5SVladimir Sementsov-Ogievskiy 6890fdf1a4fSEric Blake void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes) 690ebab2259SFam Zheng { 691ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 6922119882cSPaolo Bonzini 6932119882cSPaolo Bonzini if (QLIST_EMPTY(&bs->dirty_bitmaps)) { 6942119882cSPaolo Bonzini return; 6952119882cSPaolo Bonzini } 6962119882cSPaolo Bonzini 6972119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 698ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 699ebab2259SFam Zheng if (!bdrv_dirty_bitmap_enabled(bitmap)) { 700ebab2259SFam Zheng continue; 701ebab2259SFam Zheng } 702d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 703ca759622SEric Blake hbitmap_set(bitmap->bitmap, offset, bytes); 704ebab2259SFam Zheng } 7052119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 706ebab2259SFam Zheng } 707ebab2259SFam Zheng 708ebab2259SFam Zheng /** 709dc162c8eSFam Zheng * Advance a BdrvDirtyBitmapIter to an arbitrary offset. 710ebab2259SFam Zheng */ 711715a74d8SEric Blake void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset) 712ebab2259SFam Zheng { 713ca759622SEric Blake hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset); 714ebab2259SFam Zheng } 715ebab2259SFam Zheng 716ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap) 717ebab2259SFam Zheng { 718ca759622SEric Blake return hbitmap_count(bitmap->bitmap); 719ebab2259SFam Zheng } 7206d3f4049SFam Zheng 7216d3f4049SFam Zheng int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap) 7226d3f4049SFam Zheng { 7236d3f4049SFam Zheng return hbitmap_count(bitmap->meta); 7246d3f4049SFam Zheng } 725d6883bc9SVladimir Sementsov-Ogievskiy 726d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap) 727d6883bc9SVladimir Sementsov-Ogievskiy { 728d6883bc9SVladimir Sementsov-Ogievskiy return bitmap->readonly; 729d6883bc9SVladimir Sementsov-Ogievskiy } 730d6883bc9SVladimir Sementsov-Ogievskiy 731d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 732d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value) 733d6883bc9SVladimir Sementsov-Ogievskiy { 734d6883bc9SVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 735d6883bc9SVladimir Sementsov-Ogievskiy bitmap->readonly = value; 736d6883bc9SVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 737d6883bc9SVladimir Sementsov-Ogievskiy } 738d6883bc9SVladimir Sementsov-Ogievskiy 739d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs) 740d6883bc9SVladimir Sementsov-Ogievskiy { 741d6883bc9SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 742d6883bc9SVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 743d6883bc9SVladimir Sementsov-Ogievskiy if (bm->readonly) { 744d6883bc9SVladimir Sementsov-Ogievskiy return true; 745d6883bc9SVladimir Sementsov-Ogievskiy } 746d6883bc9SVladimir Sementsov-Ogievskiy } 747d6883bc9SVladimir Sementsov-Ogievskiy 748d6883bc9SVladimir Sementsov-Ogievskiy return false; 749d6883bc9SVladimir Sementsov-Ogievskiy } 750a0319aacSVladimir Sementsov-Ogievskiy 751a0319aacSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 752a88b179fSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent) 753a88b179fSVladimir Sementsov-Ogievskiy { 754a88b179fSVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 755a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = persistent; 756a88b179fSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 757a88b179fSVladimir Sementsov-Ogievskiy } 758a88b179fSVladimir Sementsov-Ogievskiy 759a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap) 760a88b179fSVladimir Sementsov-Ogievskiy { 761a88b179fSVladimir Sementsov-Ogievskiy return bitmap->persistent; 762a88b179fSVladimir Sementsov-Ogievskiy } 763a88b179fSVladimir Sementsov-Ogievskiy 764a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs) 765a88b179fSVladimir Sementsov-Ogievskiy { 766a88b179fSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 767a88b179fSVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 768a88b179fSVladimir Sementsov-Ogievskiy if (bm->persistent && !bm->readonly) { 769a88b179fSVladimir Sementsov-Ogievskiy return true; 770a88b179fSVladimir Sementsov-Ogievskiy } 771a88b179fSVladimir Sementsov-Ogievskiy } 772a88b179fSVladimir Sementsov-Ogievskiy 773a88b179fSVladimir Sementsov-Ogievskiy return false; 774a88b179fSVladimir Sementsov-Ogievskiy } 7753dd10a06SVladimir Sementsov-Ogievskiy 7763dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, 7773dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bitmap) 7783dd10a06SVladimir Sementsov-Ogievskiy { 7793dd10a06SVladimir Sementsov-Ogievskiy return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) : 7803dd10a06SVladimir Sementsov-Ogievskiy QLIST_NEXT(bitmap, list); 7813dd10a06SVladimir Sementsov-Ogievskiy } 782a3b52535SVladimir Sementsov-Ogievskiy 783a3b52535SVladimir Sementsov-Ogievskiy char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp) 784a3b52535SVladimir Sementsov-Ogievskiy { 785a3b52535SVladimir Sementsov-Ogievskiy return hbitmap_sha256(bitmap->bitmap, errp); 786a3b52535SVladimir Sementsov-Ogievskiy } 78756207df5SVladimir Sementsov-Ogievskiy 78856207df5SVladimir Sementsov-Ogievskiy int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset) 78956207df5SVladimir Sementsov-Ogievskiy { 79056207df5SVladimir Sementsov-Ogievskiy return hbitmap_next_zero(bitmap->bitmap, offset); 79156207df5SVladimir Sementsov-Ogievskiy } 792b598e531SVladimir Sementsov-Ogievskiy 793b598e531SVladimir Sementsov-Ogievskiy void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src, 794b598e531SVladimir Sementsov-Ogievskiy Error **errp) 795b598e531SVladimir Sementsov-Ogievskiy { 796b598e531SVladimir Sementsov-Ogievskiy /* only bitmaps from one bds are supported */ 797b598e531SVladimir Sementsov-Ogievskiy assert(dest->mutex == src->mutex); 798b598e531SVladimir Sementsov-Ogievskiy 799b598e531SVladimir Sementsov-Ogievskiy qemu_mutex_lock(dest->mutex); 800b598e531SVladimir Sementsov-Ogievskiy 801*06bf5006SVladimir Sementsov-Ogievskiy if (bdrv_dirty_bitmap_frozen(dest)) { 802*06bf5006SVladimir Sementsov-Ogievskiy error_setg(errp, "Bitmap '%s' is frozen and cannot be modified", 803*06bf5006SVladimir Sementsov-Ogievskiy dest->name); 804*06bf5006SVladimir Sementsov-Ogievskiy goto out; 805*06bf5006SVladimir Sementsov-Ogievskiy } 806*06bf5006SVladimir Sementsov-Ogievskiy 807*06bf5006SVladimir Sementsov-Ogievskiy if (bdrv_dirty_bitmap_readonly(dest)) { 808*06bf5006SVladimir Sementsov-Ogievskiy error_setg(errp, "Bitmap '%s' is readonly and cannot be modified", 809*06bf5006SVladimir Sementsov-Ogievskiy dest->name); 810*06bf5006SVladimir Sementsov-Ogievskiy goto out; 811*06bf5006SVladimir Sementsov-Ogievskiy } 812b598e531SVladimir Sementsov-Ogievskiy 813b598e531SVladimir Sementsov-Ogievskiy if (!hbitmap_merge(dest->bitmap, src->bitmap)) { 814b598e531SVladimir Sementsov-Ogievskiy error_setg(errp, "Bitmaps are incompatible and can't be merged"); 815*06bf5006SVladimir Sementsov-Ogievskiy goto out; 816b598e531SVladimir Sementsov-Ogievskiy } 817b598e531SVladimir Sementsov-Ogievskiy 818*06bf5006SVladimir Sementsov-Ogievskiy out: 819b598e531SVladimir Sementsov-Ogievskiy qemu_mutex_unlock(dest->mutex); 820b598e531SVladimir Sementsov-Ogievskiy } 821