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 179993edc0cSJohn Snow /* Both conditions disallow user-modification via QMP. */ 180993edc0cSJohn Snow bool bdrv_dirty_bitmap_user_locked(BdrvDirtyBitmap *bitmap) { 181993edc0cSJohn Snow return bdrv_dirty_bitmap_frozen(bitmap) || 182993edc0cSJohn Snow bdrv_dirty_bitmap_qmp_locked(bitmap); 183993edc0cSJohn Snow } 184993edc0cSJohn Snow 1854f43e953SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked) 1864f43e953SVladimir Sementsov-Ogievskiy { 1874f43e953SVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 1884f43e953SVladimir Sementsov-Ogievskiy bitmap->qmp_locked = qmp_locked; 1894f43e953SVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 1904f43e953SVladimir Sementsov-Ogievskiy } 1914f43e953SVladimir Sementsov-Ogievskiy 1924f43e953SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_qmp_locked(BdrvDirtyBitmap *bitmap) 1934f43e953SVladimir Sementsov-Ogievskiy { 1944f43e953SVladimir Sementsov-Ogievskiy return bitmap->qmp_locked; 1954f43e953SVladimir Sementsov-Ogievskiy } 1964f43e953SVladimir Sementsov-Ogievskiy 1972119882cSPaolo Bonzini /* Called with BQL taken. */ 198ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap) 199ebab2259SFam Zheng { 200ebab2259SFam Zheng return !(bitmap->disabled || bitmap->successor); 201ebab2259SFam Zheng } 202ebab2259SFam Zheng 2032119882cSPaolo Bonzini /* Called with BQL taken. */ 204ebab2259SFam Zheng DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap) 205ebab2259SFam Zheng { 206ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 207ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_FROZEN; 2084f43e953SVladimir Sementsov-Ogievskiy } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) { 2094f43e953SVladimir Sementsov-Ogievskiy return DIRTY_BITMAP_STATUS_LOCKED; 210ebab2259SFam Zheng } else if (!bdrv_dirty_bitmap_enabled(bitmap)) { 211ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_DISABLED; 212ebab2259SFam Zheng } else { 213ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_ACTIVE; 214ebab2259SFam Zheng } 215ebab2259SFam Zheng } 216ebab2259SFam Zheng 217ebab2259SFam Zheng /** 218ebab2259SFam Zheng * Create a successor bitmap destined to replace this bitmap after an operation. 219ebab2259SFam Zheng * Requires that the bitmap is not frozen and has no successor. 2202119882cSPaolo Bonzini * Called with BQL taken. 221ebab2259SFam Zheng */ 222ebab2259SFam Zheng int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, 223ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, Error **errp) 224ebab2259SFam Zheng { 225ebab2259SFam Zheng uint64_t granularity; 226ebab2259SFam Zheng BdrvDirtyBitmap *child; 227ebab2259SFam Zheng 228ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 229ebab2259SFam Zheng error_setg(errp, "Cannot create a successor for a bitmap that is " 230ebab2259SFam Zheng "currently frozen"); 231ebab2259SFam Zheng return -1; 232ebab2259SFam Zheng } 233ebab2259SFam Zheng assert(!bitmap->successor); 234ebab2259SFam Zheng 235ebab2259SFam Zheng /* Create an anonymous successor */ 236ebab2259SFam Zheng granularity = bdrv_dirty_bitmap_granularity(bitmap); 237ebab2259SFam Zheng child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); 238ebab2259SFam Zheng if (!child) { 239ebab2259SFam Zheng return -1; 240ebab2259SFam Zheng } 241ebab2259SFam Zheng 242ebab2259SFam Zheng /* Successor will be on or off based on our current state. */ 243ebab2259SFam Zheng child->disabled = bitmap->disabled; 244ebab2259SFam Zheng 245ebab2259SFam Zheng /* Install the successor and freeze the parent */ 246ebab2259SFam Zheng bitmap->successor = child; 247ebab2259SFam Zheng return 0; 248ebab2259SFam Zheng } 249ebab2259SFam Zheng 25092bcea40SVladimir Sementsov-Ogievskiy void bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap) 25192bcea40SVladimir Sementsov-Ogievskiy { 25292bcea40SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_frozen(bitmap)); 25392bcea40SVladimir Sementsov-Ogievskiy bitmap->disabled = false; 25492bcea40SVladimir Sementsov-Ogievskiy } 25592bcea40SVladimir Sementsov-Ogievskiy 256e73a265eSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 257e73a265eSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap) 258e73a265eSVladimir Sementsov-Ogievskiy { 25958f72b96SVladimir Sementsov-Ogievskiy assert(bitmap->mutex == bitmap->successor->mutex); 260e73a265eSVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 26158f72b96SVladimir Sementsov-Ogievskiy bdrv_enable_dirty_bitmap_locked(bitmap->successor); 262e73a265eSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 263e73a265eSVladimir Sementsov-Ogievskiy } 264e73a265eSVladimir Sementsov-Ogievskiy 265b133c27fSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken. */ 266b133c27fSPaolo Bonzini static void bdrv_release_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap) 267604ab74bSVladimir Sementsov-Ogievskiy { 268b133c27fSPaolo Bonzini assert(!bitmap->active_iterators); 269b133c27fSPaolo Bonzini assert(!bdrv_dirty_bitmap_frozen(bitmap)); 270b133c27fSPaolo Bonzini assert(!bitmap->meta); 271b133c27fSPaolo Bonzini QLIST_REMOVE(bitmap, list); 272b133c27fSPaolo Bonzini hbitmap_free(bitmap->bitmap); 273b133c27fSPaolo Bonzini g_free(bitmap->name); 274b133c27fSPaolo Bonzini g_free(bitmap); 275604ab74bSVladimir Sementsov-Ogievskiy } 276604ab74bSVladimir Sementsov-Ogievskiy 277ebab2259SFam Zheng /** 278ebab2259SFam Zheng * For a bitmap with a successor, yield our name to the successor, 279ebab2259SFam Zheng * delete the old bitmap, and return a handle to the new bitmap. 2802119882cSPaolo Bonzini * Called with BQL taken. 281ebab2259SFam Zheng */ 282ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs, 283ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, 284ebab2259SFam Zheng Error **errp) 285ebab2259SFam Zheng { 286ebab2259SFam Zheng char *name; 287ebab2259SFam Zheng BdrvDirtyBitmap *successor = bitmap->successor; 288ebab2259SFam Zheng 289ebab2259SFam Zheng if (successor == NULL) { 290ebab2259SFam Zheng error_setg(errp, "Cannot relinquish control if " 291ebab2259SFam Zheng "there's no successor present"); 292ebab2259SFam Zheng return NULL; 293ebab2259SFam Zheng } 294ebab2259SFam Zheng 295ebab2259SFam Zheng name = bitmap->name; 296ebab2259SFam Zheng bitmap->name = NULL; 297ebab2259SFam Zheng successor->name = name; 298ebab2259SFam Zheng bitmap->successor = NULL; 299a88b179fSVladimir Sementsov-Ogievskiy successor->persistent = bitmap->persistent; 300a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = false; 301ebab2259SFam Zheng bdrv_release_dirty_bitmap(bs, bitmap); 302ebab2259SFam Zheng 303ebab2259SFam Zheng return successor; 304ebab2259SFam Zheng } 305ebab2259SFam Zheng 306ebab2259SFam Zheng /** 307ebab2259SFam Zheng * In cases of failure where we can no longer safely delete the parent, 308ebab2259SFam Zheng * we may wish to re-join the parent and child/successor. 309ebab2259SFam Zheng * The merged parent will be un-frozen, but not explicitly re-enabled. 310044ee8e1SVladimir Sementsov-Ogievskiy * Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken. 311ebab2259SFam Zheng */ 312044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs, 313ebab2259SFam Zheng BdrvDirtyBitmap *parent, 314ebab2259SFam Zheng Error **errp) 315ebab2259SFam Zheng { 316044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *successor = parent->successor; 317ebab2259SFam Zheng 318ebab2259SFam Zheng if (!successor) { 319ebab2259SFam Zheng error_setg(errp, "Cannot reclaim a successor when none is present"); 320ebab2259SFam Zheng return NULL; 321ebab2259SFam Zheng } 322ebab2259SFam Zheng 323fa000f2fSVladimir Sementsov-Ogievskiy if (!hbitmap_merge(parent->bitmap, successor->bitmap, parent->bitmap)) { 324ebab2259SFam Zheng error_setg(errp, "Merging of parent and successor bitmap failed"); 325ebab2259SFam Zheng return NULL; 326ebab2259SFam Zheng } 327b133c27fSPaolo Bonzini bdrv_release_dirty_bitmap_locked(successor); 328ebab2259SFam Zheng parent->successor = NULL; 329ebab2259SFam Zheng 330044ee8e1SVladimir Sementsov-Ogievskiy return parent; 331044ee8e1SVladimir Sementsov-Ogievskiy } 332044ee8e1SVladimir Sementsov-Ogievskiy 333044ee8e1SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 334044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, 335044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *parent, 336044ee8e1SVladimir Sementsov-Ogievskiy Error **errp) 337044ee8e1SVladimir Sementsov-Ogievskiy { 338044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *ret; 339044ee8e1SVladimir Sementsov-Ogievskiy 340044ee8e1SVladimir Sementsov-Ogievskiy qemu_mutex_lock(parent->mutex); 341044ee8e1SVladimir Sementsov-Ogievskiy ret = bdrv_reclaim_dirty_bitmap_locked(bs, parent, errp); 342604ab74bSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(parent->mutex); 343604ab74bSVladimir Sementsov-Ogievskiy 344044ee8e1SVladimir Sementsov-Ogievskiy return ret; 345ebab2259SFam Zheng } 346ebab2259SFam Zheng 347ebab2259SFam Zheng /** 348ebab2259SFam Zheng * Truncates _all_ bitmaps attached to a BDS. 3492119882cSPaolo Bonzini * Called with BQL taken. 350ebab2259SFam Zheng */ 3511b6cc579SEric Blake void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes) 352ebab2259SFam Zheng { 353ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 354ebab2259SFam Zheng 3552119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 356ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 357ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 358dc162c8eSFam Zheng assert(!bitmap->active_iterators); 359ca759622SEric Blake hbitmap_truncate(bitmap->bitmap, bytes); 360993e6525SEric Blake bitmap->size = bytes; 361ebab2259SFam Zheng } 3622119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 363ebab2259SFam Zheng } 364ebab2259SFam Zheng 3652119882cSPaolo Bonzini /* Called with BQL taken. */ 366ebab2259SFam Zheng void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap) 367ebab2259SFam Zheng { 368b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 369b133c27fSPaolo Bonzini bdrv_release_dirty_bitmap_locked(bitmap); 370b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 371ebab2259SFam Zheng } 372ebab2259SFam Zheng 373ebab2259SFam Zheng /** 374ebab2259SFam Zheng * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()). 375ebab2259SFam Zheng * There must not be any frozen bitmaps attached. 37656f364e6SVladimir Sementsov-Ogievskiy * This function does not remove persistent bitmaps from the storage. 3772119882cSPaolo Bonzini * Called with BQL taken. 378ebab2259SFam Zheng */ 379ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) 380ebab2259SFam Zheng { 381b133c27fSPaolo Bonzini BdrvDirtyBitmap *bm, *next; 382b133c27fSPaolo Bonzini 383b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 384b133c27fSPaolo Bonzini QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { 385b133c27fSPaolo Bonzini if (bdrv_dirty_bitmap_name(bm)) { 386b133c27fSPaolo Bonzini bdrv_release_dirty_bitmap_locked(bm); 387b133c27fSPaolo Bonzini } 388b133c27fSPaolo Bonzini } 389b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 390615b5dcfSVladimir Sementsov-Ogievskiy } 391615b5dcfSVladimir Sementsov-Ogievskiy 392615b5dcfSVladimir Sementsov-Ogievskiy /** 393615b5dcfSVladimir Sementsov-Ogievskiy * Release all persistent dirty bitmaps attached to a BDS (for use in 394615b5dcfSVladimir Sementsov-Ogievskiy * bdrv_inactivate_recurse()). 395615b5dcfSVladimir Sementsov-Ogievskiy * There must not be any frozen bitmaps attached. 396615b5dcfSVladimir Sementsov-Ogievskiy * This function does not remove persistent bitmaps from the storage. 397b133c27fSPaolo Bonzini * Called with BQL taken. 398615b5dcfSVladimir Sementsov-Ogievskiy */ 399615b5dcfSVladimir Sementsov-Ogievskiy void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs) 400615b5dcfSVladimir Sementsov-Ogievskiy { 401b133c27fSPaolo Bonzini BdrvDirtyBitmap *bm, *next; 402b133c27fSPaolo Bonzini 403b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 404b133c27fSPaolo Bonzini QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { 405b133c27fSPaolo Bonzini if (bdrv_dirty_bitmap_get_persistance(bm)) { 406b133c27fSPaolo Bonzini bdrv_release_dirty_bitmap_locked(bm); 407b133c27fSPaolo Bonzini } 408b133c27fSPaolo Bonzini } 409b133c27fSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 410ebab2259SFam Zheng } 411ebab2259SFam Zheng 41256f364e6SVladimir Sementsov-Ogievskiy /** 41356f364e6SVladimir Sementsov-Ogievskiy * Remove persistent dirty bitmap from the storage if it exists. 41456f364e6SVladimir Sementsov-Ogievskiy * Absence of bitmap is not an error, because we have the following scenario: 41556f364e6SVladimir Sementsov-Ogievskiy * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no 41656f364e6SVladimir Sementsov-Ogievskiy * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should 41756f364e6SVladimir Sementsov-Ogievskiy * not fail. 41856f364e6SVladimir Sementsov-Ogievskiy * This function doesn't release corresponding BdrvDirtyBitmap. 41956f364e6SVladimir Sementsov-Ogievskiy */ 42056f364e6SVladimir Sementsov-Ogievskiy void bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, 42156f364e6SVladimir Sementsov-Ogievskiy const char *name, 42256f364e6SVladimir Sementsov-Ogievskiy Error **errp) 42356f364e6SVladimir Sementsov-Ogievskiy { 42456f364e6SVladimir Sementsov-Ogievskiy if (bs->drv && bs->drv->bdrv_remove_persistent_dirty_bitmap) { 42556f364e6SVladimir Sementsov-Ogievskiy bs->drv->bdrv_remove_persistent_dirty_bitmap(bs, name, errp); 42656f364e6SVladimir Sementsov-Ogievskiy } 42756f364e6SVladimir Sementsov-Ogievskiy } 42856f364e6SVladimir Sementsov-Ogievskiy 429ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 430ebab2259SFam Zheng { 4318b1402ceSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_lock(bitmap); 432ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 433ebab2259SFam Zheng bitmap->disabled = true; 4348b1402ceSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_unlock(bitmap); 435ebab2259SFam Zheng } 436ebab2259SFam Zheng 437ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 438ebab2259SFam Zheng { 4398b1402ceSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_lock(bitmap); 44092bcea40SVladimir Sementsov-Ogievskiy bdrv_enable_dirty_bitmap_locked(bitmap); 4418b1402ceSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_unlock(bitmap); 442ebab2259SFam Zheng } 443ebab2259SFam Zheng 444ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs) 445ebab2259SFam Zheng { 446ebab2259SFam Zheng BdrvDirtyBitmap *bm; 447ebab2259SFam Zheng BlockDirtyInfoList *list = NULL; 448ebab2259SFam Zheng BlockDirtyInfoList **plist = &list; 449ebab2259SFam Zheng 4502119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 451ebab2259SFam Zheng QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 452ebab2259SFam Zheng BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1); 453ebab2259SFam Zheng BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1); 4549a46dba7SEric Blake info->count = bdrv_get_dirty_count(bm); 455ebab2259SFam Zheng info->granularity = bdrv_dirty_bitmap_granularity(bm); 456ebab2259SFam Zheng info->has_name = !!bm->name; 457ebab2259SFam Zheng info->name = g_strdup(bm->name); 458ebab2259SFam Zheng info->status = bdrv_dirty_bitmap_status(bm); 459ebab2259SFam Zheng entry->value = info; 460ebab2259SFam Zheng *plist = entry; 461ebab2259SFam Zheng plist = &entry->next; 462ebab2259SFam Zheng } 4632119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 464ebab2259SFam Zheng 465ebab2259SFam Zheng return list; 466ebab2259SFam Zheng } 467ebab2259SFam Zheng 468b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 4693b5d4df0SEric Blake bool bdrv_get_dirty_locked(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, 4703b5d4df0SEric Blake int64_t offset) 471ebab2259SFam Zheng { 472ebab2259SFam Zheng if (bitmap) { 473ca759622SEric Blake return hbitmap_get(bitmap->bitmap, offset); 474ebab2259SFam Zheng } else { 4753b5d4df0SEric Blake return false; 476ebab2259SFam Zheng } 477ebab2259SFam Zheng } 478ebab2259SFam Zheng 479ebab2259SFam Zheng /** 480ebab2259SFam Zheng * Chooses a default granularity based on the existing cluster size, 481ebab2259SFam Zheng * but clamped between [4K, 64K]. Defaults to 64K in the case that there 482ebab2259SFam Zheng * is no cluster size information available. 483ebab2259SFam Zheng */ 484ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs) 485ebab2259SFam Zheng { 486ebab2259SFam Zheng BlockDriverInfo bdi; 487ebab2259SFam Zheng uint32_t granularity; 488ebab2259SFam Zheng 489ebab2259SFam Zheng if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) { 490ebab2259SFam Zheng granularity = MAX(4096, bdi.cluster_size); 491ebab2259SFam Zheng granularity = MIN(65536, granularity); 492ebab2259SFam Zheng } else { 493ebab2259SFam Zheng granularity = 65536; 494ebab2259SFam Zheng } 495ebab2259SFam Zheng 496ebab2259SFam Zheng return granularity; 497ebab2259SFam Zheng } 498ebab2259SFam Zheng 499ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap) 500ebab2259SFam Zheng { 501ca759622SEric Blake return 1U << hbitmap_granularity(bitmap->bitmap); 502ebab2259SFam Zheng } 503ebab2259SFam Zheng 504715a74d8SEric Blake BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap) 505ebab2259SFam Zheng { 506dc162c8eSFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 507715a74d8SEric Blake hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0); 508dc162c8eSFam Zheng iter->bitmap = bitmap; 509dc162c8eSFam Zheng bitmap->active_iterators++; 510dc162c8eSFam Zheng return iter; 511dc162c8eSFam Zheng } 512dc162c8eSFam Zheng 5136d3f4049SFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_meta_iter_new(BdrvDirtyBitmap *bitmap) 5146d3f4049SFam Zheng { 5156d3f4049SFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 5166d3f4049SFam Zheng hbitmap_iter_init(&iter->hbi, bitmap->meta, 0); 5176d3f4049SFam Zheng iter->bitmap = bitmap; 5186d3f4049SFam Zheng bitmap->active_iterators++; 5196d3f4049SFam Zheng return iter; 5206d3f4049SFam Zheng } 5216d3f4049SFam Zheng 522dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter) 523dc162c8eSFam Zheng { 524dc162c8eSFam Zheng if (!iter) { 525dc162c8eSFam Zheng return; 526dc162c8eSFam Zheng } 527dc162c8eSFam Zheng assert(iter->bitmap->active_iterators > 0); 528dc162c8eSFam Zheng iter->bitmap->active_iterators--; 529dc162c8eSFam Zheng g_free(iter); 530dc162c8eSFam Zheng } 531dc162c8eSFam Zheng 532dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter) 533dc162c8eSFam Zheng { 534a33fbb4fSMax Reitz return hbitmap_iter_next(&iter->hbi, true); 535ebab2259SFam Zheng } 536ebab2259SFam Zheng 53772d10a94SMax Reitz /** 53872d10a94SMax Reitz * Return the next consecutively dirty area in the dirty bitmap 53972d10a94SMax Reitz * belonging to the given iterator @iter. 54072d10a94SMax Reitz * 54172d10a94SMax Reitz * @max_offset: Maximum value that may be returned for 54272d10a94SMax Reitz * *offset + *bytes 54372d10a94SMax Reitz * @offset: Will contain the start offset of the next dirty area 54472d10a94SMax Reitz * @bytes: Will contain the length of the next dirty area 54572d10a94SMax Reitz * 54672d10a94SMax Reitz * Returns: True if a dirty area could be found before max_offset 54772d10a94SMax Reitz * (which means that *offset and *bytes then contain valid 54872d10a94SMax Reitz * values), false otherwise. 54972d10a94SMax Reitz * 55072d10a94SMax Reitz * Note that @iter is never advanced if false is returned. If an area 55172d10a94SMax Reitz * is found (which means that true is returned), it will be advanced 55272d10a94SMax Reitz * past that area. 55372d10a94SMax Reitz */ 55472d10a94SMax Reitz bool bdrv_dirty_iter_next_area(BdrvDirtyBitmapIter *iter, uint64_t max_offset, 55572d10a94SMax Reitz uint64_t *offset, int *bytes) 55672d10a94SMax Reitz { 55772d10a94SMax Reitz uint32_t granularity = bdrv_dirty_bitmap_granularity(iter->bitmap); 55872d10a94SMax Reitz uint64_t gran_max_offset; 55972d10a94SMax Reitz int64_t ret; 56072d10a94SMax Reitz int size; 56172d10a94SMax Reitz 56272d10a94SMax Reitz if (max_offset == iter->bitmap->size) { 56372d10a94SMax Reitz /* If max_offset points to the image end, round it up by the 56472d10a94SMax Reitz * bitmap granularity */ 56572d10a94SMax Reitz gran_max_offset = ROUND_UP(max_offset, granularity); 56672d10a94SMax Reitz } else { 56772d10a94SMax Reitz gran_max_offset = max_offset; 56872d10a94SMax Reitz } 56972d10a94SMax Reitz 57072d10a94SMax Reitz ret = hbitmap_iter_next(&iter->hbi, false); 57172d10a94SMax Reitz if (ret < 0 || ret + granularity > gran_max_offset) { 57272d10a94SMax Reitz return false; 57372d10a94SMax Reitz } 57472d10a94SMax Reitz 57572d10a94SMax Reitz *offset = ret; 57672d10a94SMax Reitz size = 0; 57772d10a94SMax Reitz 57872d10a94SMax Reitz assert(granularity <= INT_MAX); 57972d10a94SMax Reitz 58072d10a94SMax Reitz do { 58172d10a94SMax Reitz /* Advance iterator */ 58272d10a94SMax Reitz ret = hbitmap_iter_next(&iter->hbi, true); 58372d10a94SMax Reitz size += granularity; 58472d10a94SMax Reitz } while (ret + granularity <= gran_max_offset && 58572d10a94SMax Reitz hbitmap_iter_next(&iter->hbi, false) == ret + granularity && 58672d10a94SMax Reitz size <= INT_MAX - granularity); 58772d10a94SMax Reitz 58872d10a94SMax Reitz *bytes = MIN(size, max_offset - *offset); 58972d10a94SMax Reitz return true; 59072d10a94SMax Reitz } 59172d10a94SMax Reitz 592b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 593b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 594e0d7f73eSEric Blake int64_t offset, int64_t bytes) 595ebab2259SFam Zheng { 596ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 597d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 598ca759622SEric Blake hbitmap_set(bitmap->bitmap, offset, bytes); 599ebab2259SFam Zheng } 600ebab2259SFam Zheng 601b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap, 602e0d7f73eSEric Blake int64_t offset, int64_t bytes) 603b64bd51eSPaolo Bonzini { 604b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 605e0d7f73eSEric Blake bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes); 606b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 607b64bd51eSPaolo Bonzini } 608b64bd51eSPaolo Bonzini 609b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 610b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 611e0d7f73eSEric Blake int64_t offset, int64_t bytes) 612ebab2259SFam Zheng { 613ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 614d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 615ca759622SEric Blake hbitmap_reset(bitmap->bitmap, offset, bytes); 616ebab2259SFam Zheng } 617ebab2259SFam Zheng 618b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, 619e0d7f73eSEric Blake int64_t offset, int64_t bytes) 620b64bd51eSPaolo Bonzini { 621b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 622e0d7f73eSEric Blake bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes); 623b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 624b64bd51eSPaolo Bonzini } 625b64bd51eSPaolo Bonzini 626ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out) 627ebab2259SFam Zheng { 628ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 629d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 630b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_lock(bitmap); 631ebab2259SFam Zheng if (!out) { 632ebab2259SFam Zheng hbitmap_reset_all(bitmap->bitmap); 633ebab2259SFam Zheng } else { 634ebab2259SFam Zheng HBitmap *backup = bitmap->bitmap; 635ca759622SEric Blake bitmap->bitmap = hbitmap_alloc(bitmap->size, 636ebab2259SFam Zheng hbitmap_granularity(backup)); 637ebab2259SFam Zheng *out = backup; 638ebab2259SFam Zheng } 639b64bd51eSPaolo Bonzini bdrv_dirty_bitmap_unlock(bitmap); 640ebab2259SFam Zheng } 641ebab2259SFam Zheng 64256bd6624SVladimir Sementsov-Ogievskiy void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup) 643ebab2259SFam Zheng { 644ebab2259SFam Zheng HBitmap *tmp = bitmap->bitmap; 645ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 646d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 64756bd6624SVladimir Sementsov-Ogievskiy bitmap->bitmap = backup; 648ebab2259SFam Zheng hbitmap_free(tmp); 649ebab2259SFam Zheng } 650ebab2259SFam Zheng 651882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap, 65286f6ae67SEric Blake uint64_t offset, uint64_t bytes) 653882c36f5SVladimir Sementsov-Ogievskiy { 654ca759622SEric Blake return hbitmap_serialization_size(bitmap->bitmap, offset, bytes); 655882c36f5SVladimir Sementsov-Ogievskiy } 656882c36f5SVladimir Sementsov-Ogievskiy 657882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap) 658882c36f5SVladimir Sementsov-Ogievskiy { 659ca759622SEric Blake return hbitmap_serialization_align(bitmap->bitmap); 660882c36f5SVladimir Sementsov-Ogievskiy } 661882c36f5SVladimir Sementsov-Ogievskiy 662882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap, 66386f6ae67SEric Blake uint8_t *buf, uint64_t offset, 66486f6ae67SEric Blake uint64_t bytes) 665882c36f5SVladimir Sementsov-Ogievskiy { 666ca759622SEric Blake hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes); 667882c36f5SVladimir Sementsov-Ogievskiy } 668882c36f5SVladimir Sementsov-Ogievskiy 669882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap, 67086f6ae67SEric Blake uint8_t *buf, uint64_t offset, 67186f6ae67SEric Blake uint64_t bytes, bool finish) 672882c36f5SVladimir Sementsov-Ogievskiy { 673ca759622SEric Blake hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish); 674882c36f5SVladimir Sementsov-Ogievskiy } 675882c36f5SVladimir Sementsov-Ogievskiy 676882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap, 67786f6ae67SEric Blake uint64_t offset, uint64_t bytes, 678882c36f5SVladimir Sementsov-Ogievskiy bool finish) 679882c36f5SVladimir Sementsov-Ogievskiy { 680ca759622SEric Blake hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish); 681882c36f5SVladimir Sementsov-Ogievskiy } 682882c36f5SVladimir Sementsov-Ogievskiy 6836bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap, 68486f6ae67SEric Blake uint64_t offset, uint64_t bytes, 6856bdc8b71SVladimir Sementsov-Ogievskiy bool finish) 6866bdc8b71SVladimir Sementsov-Ogievskiy { 687ca759622SEric Blake hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish); 6886bdc8b71SVladimir Sementsov-Ogievskiy } 6896bdc8b71SVladimir Sementsov-Ogievskiy 690882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap) 691882c36f5SVladimir Sementsov-Ogievskiy { 692882c36f5SVladimir Sementsov-Ogievskiy hbitmap_deserialize_finish(bitmap->bitmap); 693882c36f5SVladimir Sementsov-Ogievskiy } 694882c36f5SVladimir Sementsov-Ogievskiy 6950fdf1a4fSEric Blake void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes) 696ebab2259SFam Zheng { 697ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 6982119882cSPaolo Bonzini 6992119882cSPaolo Bonzini if (QLIST_EMPTY(&bs->dirty_bitmaps)) { 7002119882cSPaolo Bonzini return; 7012119882cSPaolo Bonzini } 7022119882cSPaolo Bonzini 7032119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 704ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 705ebab2259SFam Zheng if (!bdrv_dirty_bitmap_enabled(bitmap)) { 706ebab2259SFam Zheng continue; 707ebab2259SFam Zheng } 708d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 709ca759622SEric Blake hbitmap_set(bitmap->bitmap, offset, bytes); 710ebab2259SFam Zheng } 7112119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 712ebab2259SFam Zheng } 713ebab2259SFam Zheng 714ebab2259SFam Zheng /** 715dc162c8eSFam Zheng * Advance a BdrvDirtyBitmapIter to an arbitrary offset. 716ebab2259SFam Zheng */ 717715a74d8SEric Blake void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset) 718ebab2259SFam Zheng { 719ca759622SEric Blake hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset); 720ebab2259SFam Zheng } 721ebab2259SFam Zheng 722ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap) 723ebab2259SFam Zheng { 724ca759622SEric Blake return hbitmap_count(bitmap->bitmap); 725ebab2259SFam Zheng } 7266d3f4049SFam Zheng 7276d3f4049SFam Zheng int64_t bdrv_get_meta_dirty_count(BdrvDirtyBitmap *bitmap) 7286d3f4049SFam Zheng { 7296d3f4049SFam Zheng return hbitmap_count(bitmap->meta); 7306d3f4049SFam Zheng } 731d6883bc9SVladimir Sementsov-Ogievskiy 732d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap) 733d6883bc9SVladimir Sementsov-Ogievskiy { 734d6883bc9SVladimir Sementsov-Ogievskiy return bitmap->readonly; 735d6883bc9SVladimir Sementsov-Ogievskiy } 736d6883bc9SVladimir Sementsov-Ogievskiy 737d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 738d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value) 739d6883bc9SVladimir Sementsov-Ogievskiy { 740d6883bc9SVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 741d6883bc9SVladimir Sementsov-Ogievskiy bitmap->readonly = value; 742d6883bc9SVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 743d6883bc9SVladimir Sementsov-Ogievskiy } 744d6883bc9SVladimir Sementsov-Ogievskiy 745d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs) 746d6883bc9SVladimir Sementsov-Ogievskiy { 747d6883bc9SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 748d6883bc9SVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 749d6883bc9SVladimir Sementsov-Ogievskiy if (bm->readonly) { 750d6883bc9SVladimir Sementsov-Ogievskiy return true; 751d6883bc9SVladimir Sementsov-Ogievskiy } 752d6883bc9SVladimir Sementsov-Ogievskiy } 753d6883bc9SVladimir Sementsov-Ogievskiy 754d6883bc9SVladimir Sementsov-Ogievskiy return false; 755d6883bc9SVladimir Sementsov-Ogievskiy } 756a0319aacSVladimir Sementsov-Ogievskiy 757a0319aacSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 758a88b179fSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent) 759a88b179fSVladimir Sementsov-Ogievskiy { 760a88b179fSVladimir Sementsov-Ogievskiy qemu_mutex_lock(bitmap->mutex); 761a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = persistent; 762a88b179fSVladimir Sementsov-Ogievskiy qemu_mutex_unlock(bitmap->mutex); 763a88b179fSVladimir Sementsov-Ogievskiy } 764a88b179fSVladimir Sementsov-Ogievskiy 765a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap) 766a88b179fSVladimir Sementsov-Ogievskiy { 767a88b179fSVladimir Sementsov-Ogievskiy return bitmap->persistent; 768a88b179fSVladimir Sementsov-Ogievskiy } 769a88b179fSVladimir Sementsov-Ogievskiy 770a88b179fSVladimir Sementsov-Ogievskiy bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs) 771a88b179fSVladimir Sementsov-Ogievskiy { 772a88b179fSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 773a88b179fSVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 774a88b179fSVladimir Sementsov-Ogievskiy if (bm->persistent && !bm->readonly) { 775a88b179fSVladimir Sementsov-Ogievskiy return true; 776a88b179fSVladimir Sementsov-Ogievskiy } 777a88b179fSVladimir Sementsov-Ogievskiy } 778a88b179fSVladimir Sementsov-Ogievskiy 779a88b179fSVladimir Sementsov-Ogievskiy return false; 780a88b179fSVladimir Sementsov-Ogievskiy } 7813dd10a06SVladimir Sementsov-Ogievskiy 7823dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BlockDriverState *bs, 7833dd10a06SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bitmap) 7843dd10a06SVladimir Sementsov-Ogievskiy { 7853dd10a06SVladimir Sementsov-Ogievskiy return bitmap == NULL ? QLIST_FIRST(&bs->dirty_bitmaps) : 7863dd10a06SVladimir Sementsov-Ogievskiy QLIST_NEXT(bitmap, list); 7873dd10a06SVladimir Sementsov-Ogievskiy } 788a3b52535SVladimir Sementsov-Ogievskiy 789a3b52535SVladimir Sementsov-Ogievskiy char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp) 790a3b52535SVladimir Sementsov-Ogievskiy { 791a3b52535SVladimir Sementsov-Ogievskiy return hbitmap_sha256(bitmap->bitmap, errp); 792a3b52535SVladimir Sementsov-Ogievskiy } 79356207df5SVladimir Sementsov-Ogievskiy 79456207df5SVladimir Sementsov-Ogievskiy int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset) 79556207df5SVladimir Sementsov-Ogievskiy { 79656207df5SVladimir Sementsov-Ogievskiy return hbitmap_next_zero(bitmap->bitmap, offset); 79756207df5SVladimir Sementsov-Ogievskiy } 798b598e531SVladimir Sementsov-Ogievskiy 799b598e531SVladimir Sementsov-Ogievskiy void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src, 800fa000f2fSVladimir Sementsov-Ogievskiy HBitmap **backup, Error **errp) 801b598e531SVladimir Sementsov-Ogievskiy { 802fa000f2fSVladimir Sementsov-Ogievskiy bool ret; 803fa000f2fSVladimir Sementsov-Ogievskiy 804b598e531SVladimir Sementsov-Ogievskiy /* only bitmaps from one bds are supported */ 805b598e531SVladimir Sementsov-Ogievskiy assert(dest->mutex == src->mutex); 806b598e531SVladimir Sementsov-Ogievskiy 807b598e531SVladimir Sementsov-Ogievskiy qemu_mutex_lock(dest->mutex); 808b598e531SVladimir Sementsov-Ogievskiy 809*283d7a04SJohn Snow if (bdrv_dirty_bitmap_user_locked(dest)) { 810*283d7a04SJohn Snow error_setg(errp, "Bitmap '%s' is currently in use by another" 811*283d7a04SJohn Snow " operation and cannot be modified", dest->name); 81206bf5006SVladimir Sementsov-Ogievskiy goto out; 81306bf5006SVladimir Sementsov-Ogievskiy } 81406bf5006SVladimir Sementsov-Ogievskiy 81506bf5006SVladimir Sementsov-Ogievskiy if (bdrv_dirty_bitmap_readonly(dest)) { 81606bf5006SVladimir Sementsov-Ogievskiy error_setg(errp, "Bitmap '%s' is readonly and cannot be modified", 81706bf5006SVladimir Sementsov-Ogievskiy dest->name); 81806bf5006SVladimir Sementsov-Ogievskiy goto out; 81906bf5006SVladimir Sementsov-Ogievskiy } 820b598e531SVladimir Sementsov-Ogievskiy 821fa000f2fSVladimir Sementsov-Ogievskiy if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) { 822b598e531SVladimir Sementsov-Ogievskiy error_setg(errp, "Bitmaps are incompatible and can't be merged"); 82306bf5006SVladimir Sementsov-Ogievskiy goto out; 824b598e531SVladimir Sementsov-Ogievskiy } 825b598e531SVladimir Sementsov-Ogievskiy 826fa000f2fSVladimir Sementsov-Ogievskiy if (backup) { 827fa000f2fSVladimir Sementsov-Ogievskiy *backup = dest->bitmap; 828fa000f2fSVladimir Sementsov-Ogievskiy dest->bitmap = hbitmap_alloc(dest->size, hbitmap_granularity(*backup)); 829fa000f2fSVladimir Sementsov-Ogievskiy ret = hbitmap_merge(*backup, src->bitmap, dest->bitmap); 830fa000f2fSVladimir Sementsov-Ogievskiy } else { 831fa000f2fSVladimir Sementsov-Ogievskiy ret = hbitmap_merge(dest->bitmap, src->bitmap, dest->bitmap); 832fa000f2fSVladimir Sementsov-Ogievskiy } 833fa000f2fSVladimir Sementsov-Ogievskiy assert(ret); 834fa000f2fSVladimir Sementsov-Ogievskiy 83506bf5006SVladimir Sementsov-Ogievskiy out: 836b598e531SVladimir Sementsov-Ogievskiy qemu_mutex_unlock(dest->mutex); 837b598e531SVladimir Sementsov-Ogievskiy } 838