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 "trace.h" 27ebab2259SFam Zheng #include "block/block_int.h" 28ebab2259SFam Zheng #include "block/blockjob.h" 29d2c3080eSVladimir Sementsov-Ogievskiy #include "qemu/main-loop.h" 30ebab2259SFam Zheng 31ebab2259SFam Zheng struct BdrvDirtyBitmap { 325deb6cbdSVladimir Sementsov-Ogievskiy BlockDriverState *bs; 33ca759622SEric Blake HBitmap *bitmap; /* Dirty bitmap implementation */ 3427a1b301SJohn Snow bool busy; /* Bitmap is busy, it can't be used via QMP */ 3521d2376fSJohn Snow BdrvDirtyBitmap *successor; /* Anonymous child, if any. */ 36ebab2259SFam Zheng char *name; /* Optional non-empty unique ID */ 37993e6525SEric Blake int64_t size; /* Size of the bitmap, in bytes */ 388bfc932eSVladimir Sementsov-Ogievskiy bool disabled; /* Bitmap is disabled. It ignores all writes to 398bfc932eSVladimir Sementsov-Ogievskiy the device */ 40dc162c8eSFam Zheng int active_iterators; /* How many iterators are active */ 41d6883bc9SVladimir Sementsov-Ogievskiy bool readonly; /* Bitmap is read-only. This field also 42d6883bc9SVladimir Sementsov-Ogievskiy prevents the respective image from being 43d6883bc9SVladimir Sementsov-Ogievskiy modified (i.e. blocks writes and discards). 44d6883bc9SVladimir Sementsov-Ogievskiy Such operations must fail and both the image 45d6883bc9SVladimir Sementsov-Ogievskiy and this bitmap must remain unchanged while 46d6883bc9SVladimir Sementsov-Ogievskiy this flag is set. */ 47a88b179fSVladimir Sementsov-Ogievskiy bool persistent; /* bitmap must be saved to owner disk image */ 48b0f45559SJohn Snow bool inconsistent; /* bitmap is persistent, but inconsistent. 49b0f45559SJohn Snow It cannot be used at all in any way, except 50b0f45559SJohn Snow a QMP user can remove it. */ 51c4e4b0faSJohn Snow bool skip_store; /* We are either migrating or deleting this 52c4e4b0faSJohn Snow * bitmap; it should not be stored on the next 53c4e4b0faSJohn Snow * inactivation. */ 54ebab2259SFam Zheng QLIST_ENTRY(BdrvDirtyBitmap) list; 55ebab2259SFam Zheng }; 56ebab2259SFam Zheng 57dc162c8eSFam Zheng struct BdrvDirtyBitmapIter { 58dc162c8eSFam Zheng HBitmapIter hbi; 59dc162c8eSFam Zheng BdrvDirtyBitmap *bitmap; 60dc162c8eSFam Zheng }; 61dc162c8eSFam Zheng 622119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_lock(BlockDriverState *bs) 632119882cSPaolo Bonzini { 642119882cSPaolo Bonzini qemu_mutex_lock(&bs->dirty_bitmap_mutex); 652119882cSPaolo Bonzini } 662119882cSPaolo Bonzini 672119882cSPaolo Bonzini static inline void bdrv_dirty_bitmaps_unlock(BlockDriverState *bs) 682119882cSPaolo Bonzini { 692119882cSPaolo Bonzini qemu_mutex_unlock(&bs->dirty_bitmap_mutex); 702119882cSPaolo Bonzini } 712119882cSPaolo Bonzini 72b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_lock(BdrvDirtyBitmap *bitmap) 73b64bd51eSPaolo Bonzini { 741e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 75b64bd51eSPaolo Bonzini } 76b64bd51eSPaolo Bonzini 77b64bd51eSPaolo Bonzini void bdrv_dirty_bitmap_unlock(BdrvDirtyBitmap *bitmap) 78b64bd51eSPaolo Bonzini { 791e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 80b64bd51eSPaolo Bonzini } 81b64bd51eSPaolo Bonzini 822119882cSPaolo Bonzini /* Called with BQL or dirty_bitmap lock taken. */ 83ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name) 84ebab2259SFam Zheng { 85ebab2259SFam Zheng BdrvDirtyBitmap *bm; 86ebab2259SFam Zheng 87ebab2259SFam Zheng assert(name); 88ebab2259SFam Zheng QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 89ebab2259SFam Zheng if (bm->name && !strcmp(name, bm->name)) { 90ebab2259SFam Zheng return bm; 91ebab2259SFam Zheng } 92ebab2259SFam Zheng } 93ebab2259SFam Zheng return NULL; 94ebab2259SFam Zheng } 95ebab2259SFam Zheng 962119882cSPaolo Bonzini /* Called with BQL taken. */ 97ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, 98ebab2259SFam Zheng uint32_t granularity, 99ebab2259SFam Zheng const char *name, 100ebab2259SFam Zheng Error **errp) 101ebab2259SFam Zheng { 102ebab2259SFam Zheng int64_t bitmap_size; 103ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 104ebab2259SFam Zheng 105993e6525SEric Blake assert(is_power_of_2(granularity) && granularity >= BDRV_SECTOR_SIZE); 106ebab2259SFam Zheng 107cf7c49cfSEric Blake if (name) { 108cf7c49cfSEric Blake if (bdrv_find_dirty_bitmap(bs, name)) { 109ebab2259SFam Zheng error_setg(errp, "Bitmap already exists: %s", name); 110ebab2259SFam Zheng return NULL; 111ebab2259SFam Zheng } 112cf7c49cfSEric Blake if (strlen(name) > BDRV_BITMAP_MAX_NAME_SIZE) { 113cf7c49cfSEric Blake error_setg(errp, "Bitmap name too long: %s", name); 114cf7c49cfSEric Blake return NULL; 115cf7c49cfSEric Blake } 116cf7c49cfSEric Blake } 117993e6525SEric Blake bitmap_size = bdrv_getlength(bs); 118ebab2259SFam Zheng if (bitmap_size < 0) { 119ebab2259SFam Zheng error_setg_errno(errp, -bitmap_size, "could not get length of device"); 120ebab2259SFam Zheng errno = -bitmap_size; 121ebab2259SFam Zheng return NULL; 122ebab2259SFam Zheng } 123ebab2259SFam Zheng bitmap = g_new0(BdrvDirtyBitmap, 1); 1245deb6cbdSVladimir Sementsov-Ogievskiy bitmap->bs = bs; 125ca759622SEric Blake bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(granularity)); 126ebab2259SFam Zheng bitmap->size = bitmap_size; 127ebab2259SFam Zheng bitmap->name = g_strdup(name); 128ebab2259SFam Zheng bitmap->disabled = false; 1292119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 130ebab2259SFam Zheng QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list); 1312119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 132ebab2259SFam Zheng return bitmap; 133ebab2259SFam Zheng } 134ebab2259SFam Zheng 13515891facSFam Zheng int64_t bdrv_dirty_bitmap_size(const BdrvDirtyBitmap *bitmap) 13615891facSFam Zheng { 137993e6525SEric Blake return bitmap->size; 13815891facSFam Zheng } 13915891facSFam Zheng 14015891facSFam Zheng const char *bdrv_dirty_bitmap_name(const BdrvDirtyBitmap *bitmap) 14115891facSFam Zheng { 14215891facSFam Zheng return bitmap->name; 14315891facSFam Zheng } 14415891facSFam Zheng 1452119882cSPaolo Bonzini /* Called with BQL taken. */ 14650a47257SJohn Snow bool bdrv_dirty_bitmap_has_successor(BdrvDirtyBitmap *bitmap) 147ebab2259SFam Zheng { 148ebab2259SFam Zheng return bitmap->successor; 149ebab2259SFam Zheng } 150ebab2259SFam Zheng 1513ae96d66SJohn Snow static bool bdrv_dirty_bitmap_busy(const BdrvDirtyBitmap *bitmap) 15227a1b301SJohn Snow { 15327a1b301SJohn Snow return bitmap->busy; 154993edc0cSJohn Snow } 155993edc0cSJohn Snow 15627a1b301SJohn Snow void bdrv_dirty_bitmap_set_busy(BdrvDirtyBitmap *bitmap, bool busy) 1574f43e953SVladimir Sementsov-Ogievskiy { 1581e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 15927a1b301SJohn Snow bitmap->busy = busy; 1601e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 1614f43e953SVladimir Sementsov-Ogievskiy } 1624f43e953SVladimir Sementsov-Ogievskiy 1632119882cSPaolo Bonzini /* Called with BQL taken. */ 164ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap) 165ebab2259SFam Zheng { 1668b2e20f6SJohn Snow return !bitmap->disabled; 167ebab2259SFam Zheng } 168ebab2259SFam Zheng 1694db6ceb0SJohn Snow /* Called with BQL taken. */ 1704db6ceb0SJohn Snow static bool bdrv_dirty_bitmap_recording(BdrvDirtyBitmap *bitmap) 1714db6ceb0SJohn Snow { 1724db6ceb0SJohn Snow return !bitmap->disabled || (bitmap->successor && 1734db6ceb0SJohn Snow !bitmap->successor->disabled); 1744db6ceb0SJohn Snow } 1754db6ceb0SJohn Snow 1763ae96d66SJohn Snow int bdrv_dirty_bitmap_check(const BdrvDirtyBitmap *bitmap, uint32_t flags, 1773ae96d66SJohn Snow Error **errp) 1783ae96d66SJohn Snow { 1793ae96d66SJohn Snow if ((flags & BDRV_BITMAP_BUSY) && bdrv_dirty_bitmap_busy(bitmap)) { 1803ae96d66SJohn Snow error_setg(errp, "Bitmap '%s' is currently in use by another" 1813ae96d66SJohn Snow " operation and cannot be used", bitmap->name); 1823ae96d66SJohn Snow return -1; 1833ae96d66SJohn Snow } 1843ae96d66SJohn Snow 1853ae96d66SJohn Snow if ((flags & BDRV_BITMAP_RO) && bdrv_dirty_bitmap_readonly(bitmap)) { 1863ae96d66SJohn Snow error_setg(errp, "Bitmap '%s' is readonly and cannot be modified", 1873ae96d66SJohn Snow bitmap->name); 1883ae96d66SJohn Snow return -1; 1893ae96d66SJohn Snow } 1903ae96d66SJohn Snow 1913ae96d66SJohn Snow if ((flags & BDRV_BITMAP_INCONSISTENT) && 1923ae96d66SJohn Snow bdrv_dirty_bitmap_inconsistent(bitmap)) { 1933ae96d66SJohn Snow error_setg(errp, "Bitmap '%s' is inconsistent and cannot be used", 1943ae96d66SJohn Snow bitmap->name); 1953ae96d66SJohn Snow error_append_hint(errp, "Try block-dirty-bitmap-remove to delete" 19694075c28SEric Blake " this bitmap from disk\n"); 1973ae96d66SJohn Snow return -1; 1983ae96d66SJohn Snow } 1993ae96d66SJohn Snow 2003ae96d66SJohn Snow return 0; 2013ae96d66SJohn Snow } 2023ae96d66SJohn Snow 203ebab2259SFam Zheng /** 204ebab2259SFam Zheng * Create a successor bitmap destined to replace this bitmap after an operation. 20527a1b301SJohn Snow * Requires that the bitmap is not marked busy and has no successor. 2068b2e20f6SJohn Snow * The successor will be enabled if the parent bitmap was. 2072119882cSPaolo Bonzini * Called with BQL taken. 208ebab2259SFam Zheng */ 2095deb6cbdSVladimir Sementsov-Ogievskiy int bdrv_dirty_bitmap_create_successor(BdrvDirtyBitmap *bitmap, Error **errp) 210ebab2259SFam Zheng { 211ebab2259SFam Zheng uint64_t granularity; 212ebab2259SFam Zheng BdrvDirtyBitmap *child; 213ebab2259SFam Zheng 2143ae96d66SJohn Snow if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY, errp)) { 215ebab2259SFam Zheng return -1; 216ebab2259SFam Zheng } 21750a47257SJohn Snow if (bdrv_dirty_bitmap_has_successor(bitmap)) { 21850a47257SJohn Snow error_setg(errp, "Cannot create a successor for a bitmap that already " 21950a47257SJohn Snow "has one"); 22050a47257SJohn Snow return -1; 22150a47257SJohn Snow } 222ebab2259SFam Zheng 223ebab2259SFam Zheng /* Create an anonymous successor */ 224ebab2259SFam Zheng granularity = bdrv_dirty_bitmap_granularity(bitmap); 2255deb6cbdSVladimir Sementsov-Ogievskiy child = bdrv_create_dirty_bitmap(bitmap->bs, granularity, NULL, errp); 226ebab2259SFam Zheng if (!child) { 227ebab2259SFam Zheng return -1; 228ebab2259SFam Zheng } 229ebab2259SFam Zheng 230ebab2259SFam Zheng /* Successor will be on or off based on our current state. */ 231ebab2259SFam Zheng child->disabled = bitmap->disabled; 2328b2e20f6SJohn Snow bitmap->disabled = true; 233ebab2259SFam Zheng 23427a1b301SJohn Snow /* Install the successor and mark the parent as busy */ 235ebab2259SFam Zheng bitmap->successor = child; 23627a1b301SJohn Snow bitmap->busy = true; 237ebab2259SFam Zheng return 0; 238ebab2259SFam Zheng } 239ebab2259SFam Zheng 24092bcea40SVladimir Sementsov-Ogievskiy void bdrv_enable_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap) 24192bcea40SVladimir Sementsov-Ogievskiy { 24292bcea40SVladimir Sementsov-Ogievskiy bitmap->disabled = false; 24392bcea40SVladimir Sementsov-Ogievskiy } 24492bcea40SVladimir Sementsov-Ogievskiy 245e73a265eSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 246e73a265eSVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_enable_successor(BdrvDirtyBitmap *bitmap) 247e73a265eSVladimir Sementsov-Ogievskiy { 2481e638301SVladimir Sementsov-Ogievskiy assert(bitmap->bs == bitmap->successor->bs); 2491e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 25058f72b96SVladimir Sementsov-Ogievskiy bdrv_enable_dirty_bitmap_locked(bitmap->successor); 2511e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 252e73a265eSVladimir Sementsov-Ogievskiy } 253e73a265eSVladimir Sementsov-Ogievskiy 254b133c27fSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken. */ 255b133c27fSPaolo Bonzini static void bdrv_release_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap) 256604ab74bSVladimir Sementsov-Ogievskiy { 257b133c27fSPaolo Bonzini assert(!bitmap->active_iterators); 25827a1b301SJohn Snow assert(!bdrv_dirty_bitmap_busy(bitmap)); 25950a47257SJohn Snow assert(!bdrv_dirty_bitmap_has_successor(bitmap)); 260b133c27fSPaolo Bonzini QLIST_REMOVE(bitmap, list); 261b133c27fSPaolo Bonzini hbitmap_free(bitmap->bitmap); 262b133c27fSPaolo Bonzini g_free(bitmap->name); 263b133c27fSPaolo Bonzini g_free(bitmap); 264604ab74bSVladimir Sementsov-Ogievskiy } 265604ab74bSVladimir Sementsov-Ogievskiy 266ebab2259SFam Zheng /** 267ebab2259SFam Zheng * For a bitmap with a successor, yield our name to the successor, 268ebab2259SFam Zheng * delete the old bitmap, and return a handle to the new bitmap. 2692119882cSPaolo Bonzini * Called with BQL taken. 270ebab2259SFam Zheng */ 2715deb6cbdSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BdrvDirtyBitmap *bitmap, 272ebab2259SFam Zheng Error **errp) 273ebab2259SFam Zheng { 274ebab2259SFam Zheng char *name; 275ebab2259SFam Zheng BdrvDirtyBitmap *successor = bitmap->successor; 276ebab2259SFam Zheng 277ebab2259SFam Zheng if (successor == NULL) { 278ebab2259SFam Zheng error_setg(errp, "Cannot relinquish control if " 279ebab2259SFam Zheng "there's no successor present"); 280ebab2259SFam Zheng return NULL; 281ebab2259SFam Zheng } 282ebab2259SFam Zheng 283ebab2259SFam Zheng name = bitmap->name; 284ebab2259SFam Zheng bitmap->name = NULL; 285ebab2259SFam Zheng successor->name = name; 286ebab2259SFam Zheng bitmap->successor = NULL; 287a88b179fSVladimir Sementsov-Ogievskiy successor->persistent = bitmap->persistent; 288a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = false; 28927a1b301SJohn Snow bitmap->busy = false; 2905deb6cbdSVladimir Sementsov-Ogievskiy bdrv_release_dirty_bitmap(bitmap); 291ebab2259SFam Zheng 292ebab2259SFam Zheng return successor; 293ebab2259SFam Zheng } 294ebab2259SFam Zheng 295ebab2259SFam Zheng /** 296ebab2259SFam Zheng * In cases of failure where we can no longer safely delete the parent, 297ebab2259SFam Zheng * we may wish to re-join the parent and child/successor. 29827a1b301SJohn Snow * The merged parent will be marked as not busy. 2998b2e20f6SJohn Snow * The marged parent will be enabled if and only if the successor was enabled. 300044ee8e1SVladimir Sementsov-Ogievskiy * Called within bdrv_dirty_bitmap_lock..unlock and with BQL taken. 301ebab2259SFam Zheng */ 3025deb6cbdSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BdrvDirtyBitmap *parent, 303ebab2259SFam Zheng Error **errp) 304ebab2259SFam Zheng { 305044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *successor = parent->successor; 306ebab2259SFam Zheng 307ebab2259SFam Zheng if (!successor) { 308ebab2259SFam Zheng error_setg(errp, "Cannot reclaim a successor when none is present"); 309ebab2259SFam Zheng return NULL; 310ebab2259SFam Zheng } 311ebab2259SFam Zheng 312fa000f2fSVladimir Sementsov-Ogievskiy if (!hbitmap_merge(parent->bitmap, successor->bitmap, parent->bitmap)) { 313ebab2259SFam Zheng error_setg(errp, "Merging of parent and successor bitmap failed"); 314ebab2259SFam Zheng return NULL; 315ebab2259SFam Zheng } 3168b2e20f6SJohn Snow 3178b2e20f6SJohn Snow parent->disabled = successor->disabled; 31827a1b301SJohn Snow parent->busy = false; 319b133c27fSPaolo Bonzini bdrv_release_dirty_bitmap_locked(successor); 320ebab2259SFam Zheng parent->successor = NULL; 321ebab2259SFam Zheng 322044ee8e1SVladimir Sementsov-Ogievskiy return parent; 323044ee8e1SVladimir Sementsov-Ogievskiy } 324044ee8e1SVladimir Sementsov-Ogievskiy 325044ee8e1SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 3265deb6cbdSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BdrvDirtyBitmap *parent, 327044ee8e1SVladimir Sementsov-Ogievskiy Error **errp) 328044ee8e1SVladimir Sementsov-Ogievskiy { 329044ee8e1SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *ret; 330044ee8e1SVladimir Sementsov-Ogievskiy 3311e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(parent->bs); 3325deb6cbdSVladimir Sementsov-Ogievskiy ret = bdrv_reclaim_dirty_bitmap_locked(parent, errp); 3331e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(parent->bs); 334604ab74bSVladimir Sementsov-Ogievskiy 335044ee8e1SVladimir Sementsov-Ogievskiy return ret; 336ebab2259SFam Zheng } 337ebab2259SFam Zheng 338ebab2259SFam Zheng /** 339ebab2259SFam Zheng * Truncates _all_ bitmaps attached to a BDS. 3402119882cSPaolo Bonzini * Called with BQL taken. 341ebab2259SFam Zheng */ 3421b6cc579SEric Blake void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes) 343ebab2259SFam Zheng { 344ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 345ebab2259SFam Zheng 3462119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 347ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 34827a1b301SJohn Snow assert(!bdrv_dirty_bitmap_busy(bitmap)); 34950a47257SJohn Snow assert(!bdrv_dirty_bitmap_has_successor(bitmap)); 350dc162c8eSFam Zheng assert(!bitmap->active_iterators); 351ca759622SEric Blake hbitmap_truncate(bitmap->bitmap, bytes); 352993e6525SEric Blake bitmap->size = bytes; 353ebab2259SFam Zheng } 3542119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 355ebab2259SFam Zheng } 356ebab2259SFam Zheng 3572119882cSPaolo Bonzini /* Called with BQL taken. */ 3585deb6cbdSVladimir Sementsov-Ogievskiy void bdrv_release_dirty_bitmap(BdrvDirtyBitmap *bitmap) 359ebab2259SFam Zheng { 3605deb6cbdSVladimir Sementsov-Ogievskiy BlockDriverState *bs = bitmap->bs; 3615deb6cbdSVladimir Sementsov-Ogievskiy 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()). 36927a1b301SJohn Snow * There must not be any busy 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 /** 38756f364e6SVladimir Sementsov-Ogievskiy * Remove persistent dirty bitmap from the storage if it exists. 38856f364e6SVladimir Sementsov-Ogievskiy * Absence of bitmap is not an error, because we have the following scenario: 38956f364e6SVladimir Sementsov-Ogievskiy * BdrvDirtyBitmap can have .persistent = true but not yet saved and have no 39056f364e6SVladimir Sementsov-Ogievskiy * stored version. For such bitmap bdrv_remove_persistent_dirty_bitmap() should 39156f364e6SVladimir Sementsov-Ogievskiy * not fail. 39256f364e6SVladimir Sementsov-Ogievskiy * This function doesn't release corresponding BdrvDirtyBitmap. 39356f364e6SVladimir Sementsov-Ogievskiy */ 394d2c3080eSVladimir Sementsov-Ogievskiy static int coroutine_fn 395d2c3080eSVladimir Sementsov-Ogievskiy bdrv_co_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, 39656f364e6SVladimir Sementsov-Ogievskiy Error **errp) 39756f364e6SVladimir Sementsov-Ogievskiy { 398d2c3080eSVladimir Sementsov-Ogievskiy if (bs->drv && bs->drv->bdrv_co_remove_persistent_dirty_bitmap) { 399d2c3080eSVladimir Sementsov-Ogievskiy return bs->drv->bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp); 40056f364e6SVladimir Sementsov-Ogievskiy } 401b56a1e31SVladimir Sementsov-Ogievskiy 402b56a1e31SVladimir Sementsov-Ogievskiy return 0; 40356f364e6SVladimir Sementsov-Ogievskiy } 40456f364e6SVladimir Sementsov-Ogievskiy 405d2c3080eSVladimir Sementsov-Ogievskiy typedef struct BdrvRemovePersistentDirtyBitmapCo { 406d2c3080eSVladimir Sementsov-Ogievskiy BlockDriverState *bs; 407d2c3080eSVladimir Sementsov-Ogievskiy const char *name; 408d2c3080eSVladimir Sementsov-Ogievskiy Error **errp; 409d2c3080eSVladimir Sementsov-Ogievskiy int ret; 410d2c3080eSVladimir Sementsov-Ogievskiy } BdrvRemovePersistentDirtyBitmapCo; 411d2c3080eSVladimir Sementsov-Ogievskiy 412d2c3080eSVladimir Sementsov-Ogievskiy static void coroutine_fn 413d2c3080eSVladimir Sementsov-Ogievskiy bdrv_co_remove_persistent_dirty_bitmap_entry(void *opaque) 414d2c3080eSVladimir Sementsov-Ogievskiy { 415d2c3080eSVladimir Sementsov-Ogievskiy BdrvRemovePersistentDirtyBitmapCo *s = opaque; 416d2c3080eSVladimir Sementsov-Ogievskiy 417d2c3080eSVladimir Sementsov-Ogievskiy s->ret = bdrv_co_remove_persistent_dirty_bitmap(s->bs, s->name, s->errp); 418d2c3080eSVladimir Sementsov-Ogievskiy aio_wait_kick(); 419d2c3080eSVladimir Sementsov-Ogievskiy } 420d2c3080eSVladimir Sementsov-Ogievskiy 421d2c3080eSVladimir Sementsov-Ogievskiy int bdrv_remove_persistent_dirty_bitmap(BlockDriverState *bs, const char *name, 422d2c3080eSVladimir Sementsov-Ogievskiy Error **errp) 423d2c3080eSVladimir Sementsov-Ogievskiy { 424d2c3080eSVladimir Sementsov-Ogievskiy if (qemu_in_coroutine()) { 425d2c3080eSVladimir Sementsov-Ogievskiy return bdrv_co_remove_persistent_dirty_bitmap(bs, name, errp); 426d2c3080eSVladimir Sementsov-Ogievskiy } else { 427d2c3080eSVladimir Sementsov-Ogievskiy Coroutine *co; 428d2c3080eSVladimir Sementsov-Ogievskiy BdrvRemovePersistentDirtyBitmapCo s = { 429d2c3080eSVladimir Sementsov-Ogievskiy .bs = bs, 430d2c3080eSVladimir Sementsov-Ogievskiy .name = name, 431d2c3080eSVladimir Sementsov-Ogievskiy .errp = errp, 432d2c3080eSVladimir Sementsov-Ogievskiy .ret = -EINPROGRESS, 433d2c3080eSVladimir Sementsov-Ogievskiy }; 434d2c3080eSVladimir Sementsov-Ogievskiy 435d2c3080eSVladimir Sementsov-Ogievskiy co = qemu_coroutine_create(bdrv_co_remove_persistent_dirty_bitmap_entry, 436d2c3080eSVladimir Sementsov-Ogievskiy &s); 437d2c3080eSVladimir Sementsov-Ogievskiy bdrv_coroutine_enter(bs, co); 438d2c3080eSVladimir Sementsov-Ogievskiy BDRV_POLL_WHILE(bs, s.ret == -EINPROGRESS); 439d2c3080eSVladimir Sementsov-Ogievskiy 440d2c3080eSVladimir Sementsov-Ogievskiy return s.ret; 441d2c3080eSVladimir Sementsov-Ogievskiy } 442d2c3080eSVladimir Sementsov-Ogievskiy } 443d2c3080eSVladimir Sementsov-Ogievskiy 444ef893b5cSEric Blake bool 445ef893b5cSEric Blake bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs) 446ef893b5cSEric Blake { 447ef893b5cSEric Blake if (bs->drv && bs->drv->bdrv_supports_persistent_dirty_bitmap) { 448ef893b5cSEric Blake return bs->drv->bdrv_supports_persistent_dirty_bitmap(bs); 449ef893b5cSEric Blake } 450ef893b5cSEric Blake return false; 451ef893b5cSEric Blake } 452ef893b5cSEric Blake 453d2c3080eSVladimir Sementsov-Ogievskiy static bool coroutine_fn 454d2c3080eSVladimir Sementsov-Ogievskiy bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, 45585cc8a4fSVladimir Sementsov-Ogievskiy uint32_t granularity, Error **errp) 45685cc8a4fSVladimir Sementsov-Ogievskiy { 45785cc8a4fSVladimir Sementsov-Ogievskiy BlockDriver *drv = bs->drv; 45885cc8a4fSVladimir Sementsov-Ogievskiy 45985cc8a4fSVladimir Sementsov-Ogievskiy if (!drv) { 46085cc8a4fSVladimir Sementsov-Ogievskiy error_setg_errno(errp, ENOMEDIUM, 46185cc8a4fSVladimir Sementsov-Ogievskiy "Can't store persistent bitmaps to %s", 46285cc8a4fSVladimir Sementsov-Ogievskiy bdrv_get_device_or_node_name(bs)); 46385cc8a4fSVladimir Sementsov-Ogievskiy return false; 46485cc8a4fSVladimir Sementsov-Ogievskiy } 46585cc8a4fSVladimir Sementsov-Ogievskiy 466d2c3080eSVladimir Sementsov-Ogievskiy if (!drv->bdrv_co_can_store_new_dirty_bitmap) { 46785cc8a4fSVladimir Sementsov-Ogievskiy error_setg_errno(errp, ENOTSUP, 46885cc8a4fSVladimir Sementsov-Ogievskiy "Can't store persistent bitmaps to %s", 46985cc8a4fSVladimir Sementsov-Ogievskiy bdrv_get_device_or_node_name(bs)); 47085cc8a4fSVladimir Sementsov-Ogievskiy return false; 47185cc8a4fSVladimir Sementsov-Ogievskiy } 47285cc8a4fSVladimir Sementsov-Ogievskiy 473d2c3080eSVladimir Sementsov-Ogievskiy return drv->bdrv_co_can_store_new_dirty_bitmap(bs, name, granularity, errp); 474d2c3080eSVladimir Sementsov-Ogievskiy } 475d2c3080eSVladimir Sementsov-Ogievskiy 476d2c3080eSVladimir Sementsov-Ogievskiy typedef struct BdrvCanStoreNewDirtyBitmapCo { 477d2c3080eSVladimir Sementsov-Ogievskiy BlockDriverState *bs; 478d2c3080eSVladimir Sementsov-Ogievskiy const char *name; 479d2c3080eSVladimir Sementsov-Ogievskiy uint32_t granularity; 480d2c3080eSVladimir Sementsov-Ogievskiy Error **errp; 481d2c3080eSVladimir Sementsov-Ogievskiy bool ret; 482d2c3080eSVladimir Sementsov-Ogievskiy 483d2c3080eSVladimir Sementsov-Ogievskiy bool in_progress; 484d2c3080eSVladimir Sementsov-Ogievskiy } BdrvCanStoreNewDirtyBitmapCo; 485d2c3080eSVladimir Sementsov-Ogievskiy 486d2c3080eSVladimir Sementsov-Ogievskiy static void coroutine_fn bdrv_co_can_store_new_dirty_bitmap_entry(void *opaque) 487d2c3080eSVladimir Sementsov-Ogievskiy { 488d2c3080eSVladimir Sementsov-Ogievskiy BdrvCanStoreNewDirtyBitmapCo *s = opaque; 489d2c3080eSVladimir Sementsov-Ogievskiy 490d2c3080eSVladimir Sementsov-Ogievskiy s->ret = bdrv_co_can_store_new_dirty_bitmap(s->bs, s->name, s->granularity, 491d2c3080eSVladimir Sementsov-Ogievskiy s->errp); 492d2c3080eSVladimir Sementsov-Ogievskiy s->in_progress = false; 493d2c3080eSVladimir Sementsov-Ogievskiy aio_wait_kick(); 494d2c3080eSVladimir Sementsov-Ogievskiy } 495d2c3080eSVladimir Sementsov-Ogievskiy 496d2c3080eSVladimir Sementsov-Ogievskiy bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name, 497d2c3080eSVladimir Sementsov-Ogievskiy uint32_t granularity, Error **errp) 498d2c3080eSVladimir Sementsov-Ogievskiy { 499384a48fbSEmanuele Giuseppe Esposito IO_CODE(); 500d2c3080eSVladimir Sementsov-Ogievskiy if (qemu_in_coroutine()) { 501d2c3080eSVladimir Sementsov-Ogievskiy return bdrv_co_can_store_new_dirty_bitmap(bs, name, granularity, errp); 502d2c3080eSVladimir Sementsov-Ogievskiy } else { 503d2c3080eSVladimir Sementsov-Ogievskiy Coroutine *co; 504d2c3080eSVladimir Sementsov-Ogievskiy BdrvCanStoreNewDirtyBitmapCo s = { 505d2c3080eSVladimir Sementsov-Ogievskiy .bs = bs, 506d2c3080eSVladimir Sementsov-Ogievskiy .name = name, 507d2c3080eSVladimir Sementsov-Ogievskiy .granularity = granularity, 508d2c3080eSVladimir Sementsov-Ogievskiy .errp = errp, 509d2c3080eSVladimir Sementsov-Ogievskiy .in_progress = true, 510d2c3080eSVladimir Sementsov-Ogievskiy }; 511d2c3080eSVladimir Sementsov-Ogievskiy 512d2c3080eSVladimir Sementsov-Ogievskiy co = qemu_coroutine_create(bdrv_co_can_store_new_dirty_bitmap_entry, 513d2c3080eSVladimir Sementsov-Ogievskiy &s); 514d2c3080eSVladimir Sementsov-Ogievskiy bdrv_coroutine_enter(bs, co); 515d2c3080eSVladimir Sementsov-Ogievskiy BDRV_POLL_WHILE(bs, s.in_progress); 516d2c3080eSVladimir Sementsov-Ogievskiy 517d2c3080eSVladimir Sementsov-Ogievskiy return s.ret; 518d2c3080eSVladimir Sementsov-Ogievskiy } 51985cc8a4fSVladimir Sementsov-Ogievskiy } 52085cc8a4fSVladimir Sementsov-Ogievskiy 521ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 522ebab2259SFam Zheng { 5231e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 524ebab2259SFam Zheng bitmap->disabled = true; 5251e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 526ebab2259SFam Zheng } 527ebab2259SFam Zheng 528ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 529ebab2259SFam Zheng { 5301e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 53192bcea40SVladimir Sementsov-Ogievskiy bdrv_enable_dirty_bitmap_locked(bitmap); 5321e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 533ebab2259SFam Zheng } 534ebab2259SFam Zheng 535ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs) 536ebab2259SFam Zheng { 537ebab2259SFam Zheng BdrvDirtyBitmap *bm; 538ebab2259SFam Zheng BlockDirtyInfoList *list = NULL; 539c3033fd3SEric Blake BlockDirtyInfoList **tail = &list; 540ebab2259SFam Zheng 5412119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 542ebab2259SFam Zheng QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 543ebab2259SFam Zheng BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1); 544c3033fd3SEric Blake 5459a46dba7SEric Blake info->count = bdrv_get_dirty_count(bm); 546ebab2259SFam Zheng info->granularity = bdrv_dirty_bitmap_granularity(bm); 547ebab2259SFam Zheng info->has_name = !!bm->name; 548ebab2259SFam Zheng info->name = g_strdup(bm->name); 5494db6ceb0SJohn Snow info->recording = bdrv_dirty_bitmap_recording(bm); 55027a1b301SJohn Snow info->busy = bdrv_dirty_bitmap_busy(bm); 551f67cf661SEric Blake info->persistent = bm->persistent; 552b0f45559SJohn Snow info->has_inconsistent = bm->inconsistent; 553b0f45559SJohn Snow info->inconsistent = bm->inconsistent; 554c3033fd3SEric Blake QAPI_LIST_APPEND(tail, info); 555ebab2259SFam Zheng } 5562119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 557ebab2259SFam Zheng 558ebab2259SFam Zheng return list; 559ebab2259SFam Zheng } 560ebab2259SFam Zheng 561b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 56228636b82SJohn Snow bool bdrv_dirty_bitmap_get_locked(BdrvDirtyBitmap *bitmap, int64_t offset) 563ebab2259SFam Zheng { 564ca759622SEric Blake return hbitmap_get(bitmap->bitmap, offset); 565ebab2259SFam Zheng } 56628636b82SJohn Snow 56728636b82SJohn Snow bool bdrv_dirty_bitmap_get(BdrvDirtyBitmap *bitmap, int64_t offset) 56828636b82SJohn Snow { 56928636b82SJohn Snow bool ret; 5701e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 57128636b82SJohn Snow ret = bdrv_dirty_bitmap_get_locked(bitmap, offset); 5721e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 57328636b82SJohn Snow 57428636b82SJohn Snow return ret; 575ebab2259SFam Zheng } 576ebab2259SFam Zheng 577ebab2259SFam Zheng /** 578ebab2259SFam Zheng * Chooses a default granularity based on the existing cluster size, 579ebab2259SFam Zheng * but clamped between [4K, 64K]. Defaults to 64K in the case that there 580ebab2259SFam Zheng * is no cluster size information available. 581ebab2259SFam Zheng */ 582ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs) 583ebab2259SFam Zheng { 584ebab2259SFam Zheng BlockDriverInfo bdi; 585ebab2259SFam Zheng uint32_t granularity; 586ebab2259SFam Zheng 587ebab2259SFam Zheng if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) { 588ebab2259SFam Zheng granularity = MAX(4096, bdi.cluster_size); 589ebab2259SFam Zheng granularity = MIN(65536, granularity); 590ebab2259SFam Zheng } else { 591ebab2259SFam Zheng granularity = 65536; 592ebab2259SFam Zheng } 593ebab2259SFam Zheng 594ebab2259SFam Zheng return granularity; 595ebab2259SFam Zheng } 596ebab2259SFam Zheng 597ba06ff1aSVladimir Sementsov-Ogievskiy uint32_t bdrv_dirty_bitmap_granularity(const BdrvDirtyBitmap *bitmap) 598ebab2259SFam Zheng { 599ca759622SEric Blake return 1U << hbitmap_granularity(bitmap->bitmap); 600ebab2259SFam Zheng } 601ebab2259SFam Zheng 602715a74d8SEric Blake BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap) 603ebab2259SFam Zheng { 604dc162c8eSFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 605715a74d8SEric Blake hbitmap_iter_init(&iter->hbi, bitmap->bitmap, 0); 606dc162c8eSFam Zheng iter->bitmap = bitmap; 607dc162c8eSFam Zheng bitmap->active_iterators++; 608dc162c8eSFam Zheng return iter; 609dc162c8eSFam Zheng } 610dc162c8eSFam Zheng 611dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter) 612dc162c8eSFam Zheng { 613dc162c8eSFam Zheng if (!iter) { 614dc162c8eSFam Zheng return; 615dc162c8eSFam Zheng } 616dc162c8eSFam Zheng assert(iter->bitmap->active_iterators > 0); 617dc162c8eSFam Zheng iter->bitmap->active_iterators--; 618dc162c8eSFam Zheng g_free(iter); 619dc162c8eSFam Zheng } 620dc162c8eSFam Zheng 621dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter) 622dc162c8eSFam Zheng { 62319c021e1SVladimir Sementsov-Ogievskiy return hbitmap_iter_next(&iter->hbi); 624ebab2259SFam Zheng } 625ebab2259SFam Zheng 626b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 627b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 628e0d7f73eSEric Blake int64_t offset, int64_t bytes) 629ebab2259SFam Zheng { 630d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 631ca759622SEric Blake hbitmap_set(bitmap->bitmap, offset, bytes); 632ebab2259SFam Zheng } 633ebab2259SFam Zheng 634b64bd51eSPaolo Bonzini void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap, 635e0d7f73eSEric Blake int64_t offset, int64_t bytes) 636b64bd51eSPaolo Bonzini { 6371e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 638e0d7f73eSEric Blake bdrv_set_dirty_bitmap_locked(bitmap, offset, bytes); 6391e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 640b64bd51eSPaolo Bonzini } 641b64bd51eSPaolo Bonzini 642b64bd51eSPaolo Bonzini /* Called within bdrv_dirty_bitmap_lock..unlock */ 643b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap_locked(BdrvDirtyBitmap *bitmap, 644e0d7f73eSEric Blake int64_t offset, int64_t bytes) 645ebab2259SFam Zheng { 646d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 647ca759622SEric Blake hbitmap_reset(bitmap->bitmap, offset, bytes); 648ebab2259SFam Zheng } 649ebab2259SFam Zheng 650b64bd51eSPaolo Bonzini void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, 651e0d7f73eSEric Blake int64_t offset, int64_t bytes) 652b64bd51eSPaolo Bonzini { 6531e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 654e0d7f73eSEric Blake bdrv_reset_dirty_bitmap_locked(bitmap, offset, bytes); 6551e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 656b64bd51eSPaolo Bonzini } 657b64bd51eSPaolo Bonzini 658ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out) 659ebab2259SFam Zheng { 660967d7905SEmanuele Giuseppe Esposito IO_CODE(); 661d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 6621e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 663ebab2259SFam Zheng if (!out) { 664ebab2259SFam Zheng hbitmap_reset_all(bitmap->bitmap); 665ebab2259SFam Zheng } else { 666ebab2259SFam Zheng HBitmap *backup = bitmap->bitmap; 667ca759622SEric Blake bitmap->bitmap = hbitmap_alloc(bitmap->size, 668ebab2259SFam Zheng hbitmap_granularity(backup)); 669ebab2259SFam Zheng *out = backup; 670ebab2259SFam Zheng } 6711e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 672ebab2259SFam Zheng } 673ebab2259SFam Zheng 67456bd6624SVladimir Sementsov-Ogievskiy void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup) 675ebab2259SFam Zheng { 676ebab2259SFam Zheng HBitmap *tmp = bitmap->bitmap; 677d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 678b4ad82aaSEmanuele Giuseppe Esposito GLOBAL_STATE_CODE(); 67956bd6624SVladimir Sementsov-Ogievskiy bitmap->bitmap = backup; 680ebab2259SFam Zheng hbitmap_free(tmp); 681ebab2259SFam Zheng } 682ebab2259SFam Zheng 683882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_size(const BdrvDirtyBitmap *bitmap, 68486f6ae67SEric Blake uint64_t offset, uint64_t bytes) 685882c36f5SVladimir Sementsov-Ogievskiy { 686ca759622SEric Blake return hbitmap_serialization_size(bitmap->bitmap, offset, bytes); 687882c36f5SVladimir Sementsov-Ogievskiy } 688882c36f5SVladimir Sementsov-Ogievskiy 689882c36f5SVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_align(const BdrvDirtyBitmap *bitmap) 690882c36f5SVladimir Sementsov-Ogievskiy { 691ca759622SEric Blake return hbitmap_serialization_align(bitmap->bitmap); 692882c36f5SVladimir Sementsov-Ogievskiy } 693882c36f5SVladimir Sementsov-Ogievskiy 69435f428baSVladimir Sementsov-Ogievskiy /* Return the disk size covered by a chunk of serialized bitmap data. */ 69535f428baSVladimir Sementsov-Ogievskiy uint64_t bdrv_dirty_bitmap_serialization_coverage(int serialized_chunk_size, 69635f428baSVladimir Sementsov-Ogievskiy const BdrvDirtyBitmap *bitmap) 69735f428baSVladimir Sementsov-Ogievskiy { 69835f428baSVladimir Sementsov-Ogievskiy uint64_t granularity = bdrv_dirty_bitmap_granularity(bitmap); 69935f428baSVladimir Sementsov-Ogievskiy uint64_t limit = granularity * (serialized_chunk_size << 3); 70035f428baSVladimir Sementsov-Ogievskiy 70135f428baSVladimir Sementsov-Ogievskiy assert(QEMU_IS_ALIGNED(limit, 70235f428baSVladimir Sementsov-Ogievskiy bdrv_dirty_bitmap_serialization_align(bitmap))); 70335f428baSVladimir Sementsov-Ogievskiy return limit; 70435f428baSVladimir Sementsov-Ogievskiy } 70535f428baSVladimir Sementsov-Ogievskiy 70635f428baSVladimir Sementsov-Ogievskiy 707882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_serialize_part(const BdrvDirtyBitmap *bitmap, 70886f6ae67SEric Blake uint8_t *buf, uint64_t offset, 70986f6ae67SEric Blake uint64_t bytes) 710882c36f5SVladimir Sementsov-Ogievskiy { 711ca759622SEric Blake hbitmap_serialize_part(bitmap->bitmap, buf, offset, bytes); 712882c36f5SVladimir Sementsov-Ogievskiy } 713882c36f5SVladimir Sementsov-Ogievskiy 714882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_part(BdrvDirtyBitmap *bitmap, 71586f6ae67SEric Blake uint8_t *buf, uint64_t offset, 71686f6ae67SEric Blake uint64_t bytes, bool finish) 717882c36f5SVladimir Sementsov-Ogievskiy { 718ca759622SEric Blake hbitmap_deserialize_part(bitmap->bitmap, buf, offset, bytes, finish); 719882c36f5SVladimir Sementsov-Ogievskiy } 720882c36f5SVladimir Sementsov-Ogievskiy 721882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_zeroes(BdrvDirtyBitmap *bitmap, 72286f6ae67SEric Blake uint64_t offset, uint64_t bytes, 723882c36f5SVladimir Sementsov-Ogievskiy bool finish) 724882c36f5SVladimir Sementsov-Ogievskiy { 725ca759622SEric Blake hbitmap_deserialize_zeroes(bitmap->bitmap, offset, bytes, finish); 726882c36f5SVladimir Sementsov-Ogievskiy } 727882c36f5SVladimir Sementsov-Ogievskiy 7286bdc8b71SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_ones(BdrvDirtyBitmap *bitmap, 72986f6ae67SEric Blake uint64_t offset, uint64_t bytes, 7306bdc8b71SVladimir Sementsov-Ogievskiy bool finish) 7316bdc8b71SVladimir Sementsov-Ogievskiy { 732ca759622SEric Blake hbitmap_deserialize_ones(bitmap->bitmap, offset, bytes, finish); 7336bdc8b71SVladimir Sementsov-Ogievskiy } 7346bdc8b71SVladimir Sementsov-Ogievskiy 735882c36f5SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_deserialize_finish(BdrvDirtyBitmap *bitmap) 736882c36f5SVladimir Sementsov-Ogievskiy { 737882c36f5SVladimir Sementsov-Ogievskiy hbitmap_deserialize_finish(bitmap->bitmap); 738882c36f5SVladimir Sementsov-Ogievskiy } 739882c36f5SVladimir Sementsov-Ogievskiy 7400fdf1a4fSEric Blake void bdrv_set_dirty(BlockDriverState *bs, int64_t offset, int64_t bytes) 741ebab2259SFam Zheng { 742ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 743967d7905SEmanuele Giuseppe Esposito IO_CODE(); 7442119882cSPaolo Bonzini 7452119882cSPaolo Bonzini if (QLIST_EMPTY(&bs->dirty_bitmaps)) { 7462119882cSPaolo Bonzini return; 7472119882cSPaolo Bonzini } 7482119882cSPaolo Bonzini 7492119882cSPaolo Bonzini bdrv_dirty_bitmaps_lock(bs); 750ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 751ebab2259SFam Zheng if (!bdrv_dirty_bitmap_enabled(bitmap)) { 752ebab2259SFam Zheng continue; 753ebab2259SFam Zheng } 754d6883bc9SVladimir Sementsov-Ogievskiy assert(!bdrv_dirty_bitmap_readonly(bitmap)); 755ca759622SEric Blake hbitmap_set(bitmap->bitmap, offset, bytes); 756ebab2259SFam Zheng } 7572119882cSPaolo Bonzini bdrv_dirty_bitmaps_unlock(bs); 758ebab2259SFam Zheng } 759ebab2259SFam Zheng 760ebab2259SFam Zheng /** 761dc162c8eSFam Zheng * Advance a BdrvDirtyBitmapIter to an arbitrary offset. 762ebab2259SFam Zheng */ 763715a74d8SEric Blake void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t offset) 764ebab2259SFam Zheng { 765ca759622SEric Blake hbitmap_iter_init(&iter->hbi, iter->hbi.hb, offset); 766ebab2259SFam Zheng } 767ebab2259SFam Zheng 768ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap) 769ebab2259SFam Zheng { 770ca759622SEric Blake return hbitmap_count(bitmap->bitmap); 771ebab2259SFam Zheng } 7726d3f4049SFam Zheng 773d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap) 774d6883bc9SVladimir Sementsov-Ogievskiy { 775d6883bc9SVladimir Sementsov-Ogievskiy return bitmap->readonly; 776d6883bc9SVladimir Sementsov-Ogievskiy } 777d6883bc9SVladimir Sementsov-Ogievskiy 778d6883bc9SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 779d6883bc9SVladimir Sementsov-Ogievskiy void bdrv_dirty_bitmap_set_readonly(BdrvDirtyBitmap *bitmap, bool value) 780d6883bc9SVladimir Sementsov-Ogievskiy { 7811e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 782d6883bc9SVladimir Sementsov-Ogievskiy bitmap->readonly = value; 7831e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 784d6883bc9SVladimir Sementsov-Ogievskiy } 785d6883bc9SVladimir Sementsov-Ogievskiy 786d6883bc9SVladimir Sementsov-Ogievskiy bool bdrv_has_readonly_bitmaps(BlockDriverState *bs) 787d6883bc9SVladimir Sementsov-Ogievskiy { 788d6883bc9SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 789d6883bc9SVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 790d6883bc9SVladimir Sementsov-Ogievskiy if (bm->readonly) { 791d6883bc9SVladimir Sementsov-Ogievskiy return true; 792d6883bc9SVladimir Sementsov-Ogievskiy } 793d6883bc9SVladimir Sementsov-Ogievskiy } 794d6883bc9SVladimir Sementsov-Ogievskiy 795d6883bc9SVladimir Sementsov-Ogievskiy return false; 796d6883bc9SVladimir Sementsov-Ogievskiy } 797a0319aacSVladimir Sementsov-Ogievskiy 7987ae89a0dSVladimir Sementsov-Ogievskiy bool bdrv_has_named_bitmaps(BlockDriverState *bs) 7997ae89a0dSVladimir Sementsov-Ogievskiy { 8007ae89a0dSVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bm; 8017ae89a0dSVladimir Sementsov-Ogievskiy 8027ae89a0dSVladimir Sementsov-Ogievskiy QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 8037ae89a0dSVladimir Sementsov-Ogievskiy if (bdrv_dirty_bitmap_name(bm)) { 8047ae89a0dSVladimir Sementsov-Ogievskiy return true; 8057ae89a0dSVladimir Sementsov-Ogievskiy } 8067ae89a0dSVladimir Sementsov-Ogievskiy } 8077ae89a0dSVladimir Sementsov-Ogievskiy 8087ae89a0dSVladimir Sementsov-Ogievskiy return false; 8097ae89a0dSVladimir Sementsov-Ogievskiy } 8107ae89a0dSVladimir Sementsov-Ogievskiy 811a0319aacSVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 812796a3798SEric Blake void bdrv_dirty_bitmap_set_persistence(BdrvDirtyBitmap *bitmap, bool persistent) 813a88b179fSVladimir Sementsov-Ogievskiy { 8141e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 815a88b179fSVladimir Sementsov-Ogievskiy bitmap->persistent = persistent; 8161e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 817a88b179fSVladimir Sementsov-Ogievskiy } 818a88b179fSVladimir Sementsov-Ogievskiy 8199c98f145SVladimir Sementsov-Ogievskiy /* Called with BQL taken. */ 820b0f45559SJohn Snow void bdrv_dirty_bitmap_set_inconsistent(BdrvDirtyBitmap *bitmap) 821b0f45559SJohn Snow { 8221e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 823b0f45559SJohn Snow assert(bitmap->persistent == true); 824b0f45559SJohn Snow bitmap->inconsistent = true; 825b0f45559SJohn Snow bitmap->disabled = true; 8261e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 827b0f45559SJohn Snow } 828b0f45559SJohn Snow 829b0f45559SJohn Snow /* Called with BQL taken. */ 830c4e4b0faSJohn Snow void bdrv_dirty_bitmap_skip_store(BdrvDirtyBitmap *bitmap, bool skip) 8319c98f145SVladimir Sementsov-Ogievskiy { 8321e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(bitmap->bs); 833c4e4b0faSJohn Snow bitmap->skip_store = skip; 8341e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(bitmap->bs); 8359c98f145SVladimir Sementsov-Ogievskiy } 8369c98f145SVladimir Sementsov-Ogievskiy 837796a3798SEric Blake bool bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap *bitmap) 838a88b179fSVladimir Sementsov-Ogievskiy { 839c4e4b0faSJohn Snow return bitmap->persistent && !bitmap->skip_store; 840a88b179fSVladimir Sementsov-Ogievskiy } 841a88b179fSVladimir Sementsov-Ogievskiy 842b0f45559SJohn Snow bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap) 843b0f45559SJohn Snow { 844b0f45559SJohn Snow return bitmap->inconsistent; 845b0f45559SJohn Snow } 846b0f45559SJohn Snow 847ef9041a7SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_first(BlockDriverState *bs) 8483dd10a06SVladimir Sementsov-Ogievskiy { 849ef9041a7SVladimir Sementsov-Ogievskiy return QLIST_FIRST(&bs->dirty_bitmaps); 850ef9041a7SVladimir Sementsov-Ogievskiy } 851ef9041a7SVladimir Sementsov-Ogievskiy 852ef9041a7SVladimir Sementsov-Ogievskiy BdrvDirtyBitmap *bdrv_dirty_bitmap_next(BdrvDirtyBitmap *bitmap) 853ef9041a7SVladimir Sementsov-Ogievskiy { 854ef9041a7SVladimir Sementsov-Ogievskiy return QLIST_NEXT(bitmap, list); 8553dd10a06SVladimir Sementsov-Ogievskiy } 856a3b52535SVladimir Sementsov-Ogievskiy 857a3b52535SVladimir Sementsov-Ogievskiy char *bdrv_dirty_bitmap_sha256(const BdrvDirtyBitmap *bitmap, Error **errp) 858a3b52535SVladimir Sementsov-Ogievskiy { 859a3b52535SVladimir Sementsov-Ogievskiy return hbitmap_sha256(bitmap->bitmap, errp); 860a3b52535SVladimir Sementsov-Ogievskiy } 86156207df5SVladimir Sementsov-Ogievskiy 8629399c54bSVladimir Sementsov-Ogievskiy int64_t bdrv_dirty_bitmap_next_dirty(BdrvDirtyBitmap *bitmap, int64_t offset, 8639399c54bSVladimir Sementsov-Ogievskiy int64_t bytes) 8649399c54bSVladimir Sementsov-Ogievskiy { 8659399c54bSVladimir Sementsov-Ogievskiy return hbitmap_next_dirty(bitmap->bitmap, offset, bytes); 8669399c54bSVladimir Sementsov-Ogievskiy } 8679399c54bSVladimir Sementsov-Ogievskiy 868642700fdSVladimir Sementsov-Ogievskiy int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, int64_t offset, 869642700fdSVladimir Sementsov-Ogievskiy int64_t bytes) 87056207df5SVladimir Sementsov-Ogievskiy { 87176d570dcSVladimir Sementsov-Ogievskiy return hbitmap_next_zero(bitmap->bitmap, offset, bytes); 87256207df5SVladimir Sementsov-Ogievskiy } 873b598e531SVladimir Sementsov-Ogievskiy 874a78a1a48SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_next_dirty_area(BdrvDirtyBitmap *bitmap, 875299ea9ffSVladimir Sementsov-Ogievskiy int64_t start, int64_t end, int64_t max_dirty_count, 876299ea9ffSVladimir Sementsov-Ogievskiy int64_t *dirty_start, int64_t *dirty_count) 877a78a1a48SVladimir Sementsov-Ogievskiy { 878299ea9ffSVladimir Sementsov-Ogievskiy return hbitmap_next_dirty_area(bitmap->bitmap, start, end, max_dirty_count, 879299ea9ffSVladimir Sementsov-Ogievskiy dirty_start, dirty_count); 880a78a1a48SVladimir Sementsov-Ogievskiy } 881a78a1a48SVladimir Sementsov-Ogievskiy 882*a6426475SVladimir Sementsov-Ogievskiy bool bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap, int64_t offset, 883*a6426475SVladimir Sementsov-Ogievskiy int64_t bytes, int64_t *count) 884*a6426475SVladimir Sementsov-Ogievskiy { 885*a6426475SVladimir Sementsov-Ogievskiy return hbitmap_status(bitmap->bitmap, offset, bytes, count); 886*a6426475SVladimir Sementsov-Ogievskiy } 887*a6426475SVladimir Sementsov-Ogievskiy 888b7661ca5SJohn Snow /** 889b7661ca5SJohn Snow * bdrv_merge_dirty_bitmap: merge src into dest. 890b7661ca5SJohn Snow * Ensures permissions on bitmaps are reasonable; use for public API. 891b7661ca5SJohn Snow * 892b7661ca5SJohn Snow * @backup: If provided, make a copy of dest here prior to merge. 89334ffacb7SVladimir Sementsov-Ogievskiy * 89434ffacb7SVladimir Sementsov-Ogievskiy * Returns true on success, false on failure. In case of failure bitmaps are 89534ffacb7SVladimir Sementsov-Ogievskiy * untouched. 896b7661ca5SJohn Snow */ 89734ffacb7SVladimir Sementsov-Ogievskiy bool bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src, 898fa000f2fSVladimir Sementsov-Ogievskiy HBitmap **backup, Error **errp) 899b598e531SVladimir Sementsov-Ogievskiy { 90034ffacb7SVladimir Sementsov-Ogievskiy bool ret = false; 901fa000f2fSVladimir Sementsov-Ogievskiy 9021e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(dest->bs); 9031e638301SVladimir Sementsov-Ogievskiy if (src->bs != dest->bs) { 9041e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(src->bs); 905eff0829bSVladimir Sementsov-Ogievskiy } 906b598e531SVladimir Sementsov-Ogievskiy 9073ae96d66SJohn Snow if (bdrv_dirty_bitmap_check(dest, BDRV_BITMAP_DEFAULT, errp)) { 90806bf5006SVladimir Sementsov-Ogievskiy goto out; 90906bf5006SVladimir Sementsov-Ogievskiy } 91006bf5006SVladimir Sementsov-Ogievskiy 911cb8e58e3SJohn Snow if (bdrv_dirty_bitmap_check(src, BDRV_BITMAP_ALLOW_RO, errp)) { 912cb8e58e3SJohn Snow goto out; 913cb8e58e3SJohn Snow } 914b598e531SVladimir Sementsov-Ogievskiy 915fa000f2fSVladimir Sementsov-Ogievskiy if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) { 916b598e531SVladimir Sementsov-Ogievskiy error_setg(errp, "Bitmaps are incompatible and can't be merged"); 91706bf5006SVladimir Sementsov-Ogievskiy goto out; 918b598e531SVladimir Sementsov-Ogievskiy } 919b598e531SVladimir Sementsov-Ogievskiy 920b7661ca5SJohn Snow ret = bdrv_dirty_bitmap_merge_internal(dest, src, backup, false); 921fa000f2fSVladimir Sementsov-Ogievskiy assert(ret); 922fa000f2fSVladimir Sementsov-Ogievskiy 92306bf5006SVladimir Sementsov-Ogievskiy out: 9241e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(dest->bs); 9251e638301SVladimir Sementsov-Ogievskiy if (src->bs != dest->bs) { 9261e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(src->bs); 927eff0829bSVladimir Sementsov-Ogievskiy } 92834ffacb7SVladimir Sementsov-Ogievskiy 92934ffacb7SVladimir Sementsov-Ogievskiy return ret; 930b598e531SVladimir Sementsov-Ogievskiy } 931b7661ca5SJohn Snow 932b7661ca5SJohn Snow /** 933b7661ca5SJohn Snow * bdrv_dirty_bitmap_merge_internal: merge src into dest. 934b7661ca5SJohn Snow * Does NOT check bitmap permissions; not suitable for use as public API. 935b7661ca5SJohn Snow * 936b7661ca5SJohn Snow * @backup: If provided, make a copy of dest here prior to merge. 937b7661ca5SJohn Snow * @lock: If true, lock and unlock bitmaps on the way in/out. 938b7661ca5SJohn Snow * returns true if the merge succeeded; false if unattempted. 939b7661ca5SJohn Snow */ 940b7661ca5SJohn Snow bool bdrv_dirty_bitmap_merge_internal(BdrvDirtyBitmap *dest, 941b7661ca5SJohn Snow const BdrvDirtyBitmap *src, 942b7661ca5SJohn Snow HBitmap **backup, 943b7661ca5SJohn Snow bool lock) 944b7661ca5SJohn Snow { 945b7661ca5SJohn Snow bool ret; 946967d7905SEmanuele Giuseppe Esposito IO_CODE(); 947b7661ca5SJohn Snow 948b7661ca5SJohn Snow assert(!bdrv_dirty_bitmap_readonly(dest)); 949b7661ca5SJohn Snow assert(!bdrv_dirty_bitmap_inconsistent(dest)); 950b7661ca5SJohn Snow assert(!bdrv_dirty_bitmap_inconsistent(src)); 951b7661ca5SJohn Snow 952b7661ca5SJohn Snow if (lock) { 9531e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(dest->bs); 9541e638301SVladimir Sementsov-Ogievskiy if (src->bs != dest->bs) { 9551e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_lock(src->bs); 956b7661ca5SJohn Snow } 957b7661ca5SJohn Snow } 958b7661ca5SJohn Snow 959b7661ca5SJohn Snow if (backup) { 960b7661ca5SJohn Snow *backup = dest->bitmap; 961b7661ca5SJohn Snow dest->bitmap = hbitmap_alloc(dest->size, hbitmap_granularity(*backup)); 962b7661ca5SJohn Snow ret = hbitmap_merge(*backup, src->bitmap, dest->bitmap); 963b7661ca5SJohn Snow } else { 964b7661ca5SJohn Snow ret = hbitmap_merge(dest->bitmap, src->bitmap, dest->bitmap); 965b7661ca5SJohn Snow } 966b7661ca5SJohn Snow 967b7661ca5SJohn Snow if (lock) { 9681e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(dest->bs); 9691e638301SVladimir Sementsov-Ogievskiy if (src->bs != dest->bs) { 9701e638301SVladimir Sementsov-Ogievskiy bdrv_dirty_bitmaps_unlock(src->bs); 971b7661ca5SJohn Snow } 972b7661ca5SJohn Snow } 973b7661ca5SJohn Snow 974b7661ca5SJohn Snow return ret; 975b7661ca5SJohn Snow } 976