1ebab2259SFam Zheng /* 2ebab2259SFam Zheng * Block Dirty Bitmap 3ebab2259SFam Zheng * 4ebab2259SFam Zheng * Copyright (c) 2016 Red Hat. Inc 5ebab2259SFam Zheng * 6ebab2259SFam Zheng * Permission is hereby granted, free of charge, to any person obtaining a copy 7ebab2259SFam Zheng * of this software and associated documentation files (the "Software"), to deal 8ebab2259SFam Zheng * in the Software without restriction, including without limitation the rights 9ebab2259SFam Zheng * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10ebab2259SFam Zheng * copies of the Software, and to permit persons to whom the Software is 11ebab2259SFam Zheng * furnished to do so, subject to the following conditions: 12ebab2259SFam Zheng * 13ebab2259SFam Zheng * The above copyright notice and this permission notice shall be included in 14ebab2259SFam Zheng * all copies or substantial portions of the Software. 15ebab2259SFam Zheng * 16ebab2259SFam Zheng * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17ebab2259SFam Zheng * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18ebab2259SFam Zheng * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19ebab2259SFam Zheng * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20ebab2259SFam Zheng * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21ebab2259SFam Zheng * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22ebab2259SFam Zheng * THE SOFTWARE. 23ebab2259SFam Zheng */ 24ebab2259SFam Zheng #include "qemu/osdep.h" 25da34e65cSMarkus Armbruster #include "qapi/error.h" 26ebab2259SFam Zheng #include "qemu-common.h" 27ebab2259SFam Zheng #include "trace.h" 28ebab2259SFam Zheng #include "block/block_int.h" 29ebab2259SFam Zheng #include "block/blockjob.h" 30ebab2259SFam Zheng 31ebab2259SFam Zheng /** 32ebab2259SFam Zheng * A BdrvDirtyBitmap can be in three possible states: 33ebab2259SFam Zheng * (1) successor is NULL and disabled is false: full r/w mode 34ebab2259SFam Zheng * (2) successor is NULL and disabled is true: read only mode ("disabled") 35ebab2259SFam Zheng * (3) successor is set: frozen mode. 36ebab2259SFam Zheng * A frozen bitmap cannot be renamed, deleted, anonymized, cleared, set, 37ebab2259SFam Zheng * or enabled. A frozen bitmap can only abdicate() or reclaim(). 38ebab2259SFam Zheng */ 39ebab2259SFam Zheng struct BdrvDirtyBitmap { 40ebab2259SFam Zheng HBitmap *bitmap; /* Dirty sector bitmap implementation */ 41*fb933437SFam Zheng HBitmap *meta; /* Meta dirty bitmap */ 42ebab2259SFam Zheng BdrvDirtyBitmap *successor; /* Anonymous child; implies frozen status */ 43ebab2259SFam Zheng char *name; /* Optional non-empty unique ID */ 44ebab2259SFam Zheng int64_t size; /* Size of the bitmap (Number of sectors) */ 45ebab2259SFam Zheng bool disabled; /* Bitmap is read-only */ 46dc162c8eSFam Zheng int active_iterators; /* How many iterators are active */ 47ebab2259SFam Zheng QLIST_ENTRY(BdrvDirtyBitmap) list; 48ebab2259SFam Zheng }; 49ebab2259SFam Zheng 50dc162c8eSFam Zheng struct BdrvDirtyBitmapIter { 51dc162c8eSFam Zheng HBitmapIter hbi; 52dc162c8eSFam Zheng BdrvDirtyBitmap *bitmap; 53dc162c8eSFam Zheng }; 54dc162c8eSFam Zheng 55ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name) 56ebab2259SFam Zheng { 57ebab2259SFam Zheng BdrvDirtyBitmap *bm; 58ebab2259SFam Zheng 59ebab2259SFam Zheng assert(name); 60ebab2259SFam Zheng QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 61ebab2259SFam Zheng if (bm->name && !strcmp(name, bm->name)) { 62ebab2259SFam Zheng return bm; 63ebab2259SFam Zheng } 64ebab2259SFam Zheng } 65ebab2259SFam Zheng return NULL; 66ebab2259SFam Zheng } 67ebab2259SFam Zheng 68ebab2259SFam Zheng void bdrv_dirty_bitmap_make_anon(BdrvDirtyBitmap *bitmap) 69ebab2259SFam Zheng { 70ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 71ebab2259SFam Zheng g_free(bitmap->name); 72ebab2259SFam Zheng bitmap->name = NULL; 73ebab2259SFam Zheng } 74ebab2259SFam Zheng 75ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs, 76ebab2259SFam Zheng uint32_t granularity, 77ebab2259SFam Zheng const char *name, 78ebab2259SFam Zheng Error **errp) 79ebab2259SFam Zheng { 80ebab2259SFam Zheng int64_t bitmap_size; 81ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 82ebab2259SFam Zheng uint32_t sector_granularity; 83ebab2259SFam Zheng 84ebab2259SFam Zheng assert((granularity & (granularity - 1)) == 0); 85ebab2259SFam Zheng 86ebab2259SFam Zheng if (name && bdrv_find_dirty_bitmap(bs, name)) { 87ebab2259SFam Zheng error_setg(errp, "Bitmap already exists: %s", name); 88ebab2259SFam Zheng return NULL; 89ebab2259SFam Zheng } 90ebab2259SFam Zheng sector_granularity = granularity >> BDRV_SECTOR_BITS; 91ebab2259SFam Zheng assert(sector_granularity); 92ebab2259SFam Zheng bitmap_size = bdrv_nb_sectors(bs); 93ebab2259SFam Zheng if (bitmap_size < 0) { 94ebab2259SFam Zheng error_setg_errno(errp, -bitmap_size, "could not get length of device"); 95ebab2259SFam Zheng errno = -bitmap_size; 96ebab2259SFam Zheng return NULL; 97ebab2259SFam Zheng } 98ebab2259SFam Zheng bitmap = g_new0(BdrvDirtyBitmap, 1); 99ebab2259SFam Zheng bitmap->bitmap = hbitmap_alloc(bitmap_size, ctz32(sector_granularity)); 100ebab2259SFam Zheng bitmap->size = bitmap_size; 101ebab2259SFam Zheng bitmap->name = g_strdup(name); 102ebab2259SFam Zheng bitmap->disabled = false; 103ebab2259SFam Zheng QLIST_INSERT_HEAD(&bs->dirty_bitmaps, bitmap, list); 104ebab2259SFam Zheng return bitmap; 105ebab2259SFam Zheng } 106ebab2259SFam Zheng 107*fb933437SFam Zheng /* bdrv_create_meta_dirty_bitmap 108*fb933437SFam Zheng * 109*fb933437SFam Zheng * Create a meta dirty bitmap that tracks the changes of bits in @bitmap. I.e. 110*fb933437SFam Zheng * when a dirty status bit in @bitmap is changed (either from reset to set or 111*fb933437SFam Zheng * the other way around), its respective meta dirty bitmap bit will be marked 112*fb933437SFam Zheng * dirty as well. 113*fb933437SFam Zheng * 114*fb933437SFam Zheng * @bitmap: the block dirty bitmap for which to create a meta dirty bitmap. 115*fb933437SFam Zheng * @chunk_size: how many bytes of bitmap data does each bit in the meta bitmap 116*fb933437SFam Zheng * track. 117*fb933437SFam Zheng */ 118*fb933437SFam Zheng void bdrv_create_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap, 119*fb933437SFam Zheng int chunk_size) 120*fb933437SFam Zheng { 121*fb933437SFam Zheng assert(!bitmap->meta); 122*fb933437SFam Zheng bitmap->meta = hbitmap_create_meta(bitmap->bitmap, 123*fb933437SFam Zheng chunk_size * BITS_PER_BYTE); 124*fb933437SFam Zheng } 125*fb933437SFam Zheng 126*fb933437SFam Zheng void bdrv_release_meta_dirty_bitmap(BdrvDirtyBitmap *bitmap) 127*fb933437SFam Zheng { 128*fb933437SFam Zheng assert(bitmap->meta); 129*fb933437SFam Zheng hbitmap_free_meta(bitmap->bitmap); 130*fb933437SFam Zheng bitmap->meta = NULL; 131*fb933437SFam Zheng } 132*fb933437SFam Zheng 133*fb933437SFam Zheng int bdrv_dirty_bitmap_get_meta(BlockDriverState *bs, 134*fb933437SFam Zheng BdrvDirtyBitmap *bitmap, int64_t sector, 135*fb933437SFam Zheng int nb_sectors) 136*fb933437SFam Zheng { 137*fb933437SFam Zheng uint64_t i; 138*fb933437SFam Zheng int sectors_per_bit = 1 << hbitmap_granularity(bitmap->meta); 139*fb933437SFam Zheng 140*fb933437SFam Zheng /* To optimize: we can make hbitmap to internally check the range in a 141*fb933437SFam Zheng * coarse level, or at least do it word by word. */ 142*fb933437SFam Zheng for (i = sector; i < sector + nb_sectors; i += sectors_per_bit) { 143*fb933437SFam Zheng if (hbitmap_get(bitmap->meta, i)) { 144*fb933437SFam Zheng return true; 145*fb933437SFam Zheng } 146*fb933437SFam Zheng } 147*fb933437SFam Zheng return false; 148*fb933437SFam Zheng } 149*fb933437SFam Zheng 150*fb933437SFam Zheng void bdrv_dirty_bitmap_reset_meta(BlockDriverState *bs, 151*fb933437SFam Zheng BdrvDirtyBitmap *bitmap, int64_t sector, 152*fb933437SFam Zheng int nb_sectors) 153*fb933437SFam Zheng { 154*fb933437SFam Zheng hbitmap_reset(bitmap->meta, sector, nb_sectors); 155*fb933437SFam Zheng } 156*fb933437SFam Zheng 157ebab2259SFam Zheng bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap) 158ebab2259SFam Zheng { 159ebab2259SFam Zheng return bitmap->successor; 160ebab2259SFam Zheng } 161ebab2259SFam Zheng 162ebab2259SFam Zheng bool bdrv_dirty_bitmap_enabled(BdrvDirtyBitmap *bitmap) 163ebab2259SFam Zheng { 164ebab2259SFam Zheng return !(bitmap->disabled || bitmap->successor); 165ebab2259SFam Zheng } 166ebab2259SFam Zheng 167ebab2259SFam Zheng DirtyBitmapStatus bdrv_dirty_bitmap_status(BdrvDirtyBitmap *bitmap) 168ebab2259SFam Zheng { 169ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 170ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_FROZEN; 171ebab2259SFam Zheng } else if (!bdrv_dirty_bitmap_enabled(bitmap)) { 172ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_DISABLED; 173ebab2259SFam Zheng } else { 174ebab2259SFam Zheng return DIRTY_BITMAP_STATUS_ACTIVE; 175ebab2259SFam Zheng } 176ebab2259SFam Zheng } 177ebab2259SFam Zheng 178ebab2259SFam Zheng /** 179ebab2259SFam Zheng * Create a successor bitmap destined to replace this bitmap after an operation. 180ebab2259SFam Zheng * Requires that the bitmap is not frozen and has no successor. 181ebab2259SFam Zheng */ 182ebab2259SFam Zheng int bdrv_dirty_bitmap_create_successor(BlockDriverState *bs, 183ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, Error **errp) 184ebab2259SFam Zheng { 185ebab2259SFam Zheng uint64_t granularity; 186ebab2259SFam Zheng BdrvDirtyBitmap *child; 187ebab2259SFam Zheng 188ebab2259SFam Zheng if (bdrv_dirty_bitmap_frozen(bitmap)) { 189ebab2259SFam Zheng error_setg(errp, "Cannot create a successor for a bitmap that is " 190ebab2259SFam Zheng "currently frozen"); 191ebab2259SFam Zheng return -1; 192ebab2259SFam Zheng } 193ebab2259SFam Zheng assert(!bitmap->successor); 194ebab2259SFam Zheng 195ebab2259SFam Zheng /* Create an anonymous successor */ 196ebab2259SFam Zheng granularity = bdrv_dirty_bitmap_granularity(bitmap); 197ebab2259SFam Zheng child = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp); 198ebab2259SFam Zheng if (!child) { 199ebab2259SFam Zheng return -1; 200ebab2259SFam Zheng } 201ebab2259SFam Zheng 202ebab2259SFam Zheng /* Successor will be on or off based on our current state. */ 203ebab2259SFam Zheng child->disabled = bitmap->disabled; 204ebab2259SFam Zheng 205ebab2259SFam Zheng /* Install the successor and freeze the parent */ 206ebab2259SFam Zheng bitmap->successor = child; 207ebab2259SFam Zheng return 0; 208ebab2259SFam Zheng } 209ebab2259SFam Zheng 210ebab2259SFam Zheng /** 211ebab2259SFam Zheng * For a bitmap with a successor, yield our name to the successor, 212ebab2259SFam Zheng * delete the old bitmap, and return a handle to the new bitmap. 213ebab2259SFam Zheng */ 214ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_dirty_bitmap_abdicate(BlockDriverState *bs, 215ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, 216ebab2259SFam Zheng Error **errp) 217ebab2259SFam Zheng { 218ebab2259SFam Zheng char *name; 219ebab2259SFam Zheng BdrvDirtyBitmap *successor = bitmap->successor; 220ebab2259SFam Zheng 221ebab2259SFam Zheng if (successor == NULL) { 222ebab2259SFam Zheng error_setg(errp, "Cannot relinquish control if " 223ebab2259SFam Zheng "there's no successor present"); 224ebab2259SFam Zheng return NULL; 225ebab2259SFam Zheng } 226ebab2259SFam Zheng 227ebab2259SFam Zheng name = bitmap->name; 228ebab2259SFam Zheng bitmap->name = NULL; 229ebab2259SFam Zheng successor->name = name; 230ebab2259SFam Zheng bitmap->successor = NULL; 231ebab2259SFam Zheng bdrv_release_dirty_bitmap(bs, bitmap); 232ebab2259SFam Zheng 233ebab2259SFam Zheng return successor; 234ebab2259SFam Zheng } 235ebab2259SFam Zheng 236ebab2259SFam Zheng /** 237ebab2259SFam Zheng * In cases of failure where we can no longer safely delete the parent, 238ebab2259SFam Zheng * we may wish to re-join the parent and child/successor. 239ebab2259SFam Zheng * The merged parent will be un-frozen, but not explicitly re-enabled. 240ebab2259SFam Zheng */ 241ebab2259SFam Zheng BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap(BlockDriverState *bs, 242ebab2259SFam Zheng BdrvDirtyBitmap *parent, 243ebab2259SFam Zheng Error **errp) 244ebab2259SFam Zheng { 245ebab2259SFam Zheng BdrvDirtyBitmap *successor = parent->successor; 246ebab2259SFam Zheng 247ebab2259SFam Zheng if (!successor) { 248ebab2259SFam Zheng error_setg(errp, "Cannot reclaim a successor when none is present"); 249ebab2259SFam Zheng return NULL; 250ebab2259SFam Zheng } 251ebab2259SFam Zheng 252ebab2259SFam Zheng if (!hbitmap_merge(parent->bitmap, successor->bitmap)) { 253ebab2259SFam Zheng error_setg(errp, "Merging of parent and successor bitmap failed"); 254ebab2259SFam Zheng return NULL; 255ebab2259SFam Zheng } 256ebab2259SFam Zheng bdrv_release_dirty_bitmap(bs, successor); 257ebab2259SFam Zheng parent->successor = NULL; 258ebab2259SFam Zheng 259ebab2259SFam Zheng return parent; 260ebab2259SFam Zheng } 261ebab2259SFam Zheng 262ebab2259SFam Zheng /** 263ebab2259SFam Zheng * Truncates _all_ bitmaps attached to a BDS. 264ebab2259SFam Zheng */ 265ebab2259SFam Zheng void bdrv_dirty_bitmap_truncate(BlockDriverState *bs) 266ebab2259SFam Zheng { 267ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 268ebab2259SFam Zheng uint64_t size = bdrv_nb_sectors(bs); 269ebab2259SFam Zheng 270ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 271ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 272dc162c8eSFam Zheng assert(!bitmap->active_iterators); 273ebab2259SFam Zheng hbitmap_truncate(bitmap->bitmap, size); 274ebab2259SFam Zheng bitmap->size = size; 275ebab2259SFam Zheng } 276ebab2259SFam Zheng } 277ebab2259SFam Zheng 278ebab2259SFam Zheng static void bdrv_do_release_matching_dirty_bitmap(BlockDriverState *bs, 279ebab2259SFam Zheng BdrvDirtyBitmap *bitmap, 280ebab2259SFam Zheng bool only_named) 281ebab2259SFam Zheng { 282ebab2259SFam Zheng BdrvDirtyBitmap *bm, *next; 283ebab2259SFam Zheng QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) { 284ebab2259SFam Zheng if ((!bitmap || bm == bitmap) && (!only_named || bm->name)) { 285dc162c8eSFam Zheng assert(!bm->active_iterators); 286ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bm)); 287*fb933437SFam Zheng assert(!bm->meta); 288ebab2259SFam Zheng QLIST_REMOVE(bm, list); 289ebab2259SFam Zheng hbitmap_free(bm->bitmap); 290ebab2259SFam Zheng g_free(bm->name); 291ebab2259SFam Zheng g_free(bm); 292ebab2259SFam Zheng 293ebab2259SFam Zheng if (bitmap) { 294ebab2259SFam Zheng return; 295ebab2259SFam Zheng } 296ebab2259SFam Zheng } 297ebab2259SFam Zheng } 298ebab2259SFam Zheng } 299ebab2259SFam Zheng 300ebab2259SFam Zheng void bdrv_release_dirty_bitmap(BlockDriverState *bs, BdrvDirtyBitmap *bitmap) 301ebab2259SFam Zheng { 302ebab2259SFam Zheng bdrv_do_release_matching_dirty_bitmap(bs, bitmap, false); 303ebab2259SFam Zheng } 304ebab2259SFam Zheng 305ebab2259SFam Zheng /** 306ebab2259SFam Zheng * Release all named dirty bitmaps attached to a BDS (for use in bdrv_close()). 307ebab2259SFam Zheng * There must not be any frozen bitmaps attached. 308ebab2259SFam Zheng */ 309ebab2259SFam Zheng void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs) 310ebab2259SFam Zheng { 311ebab2259SFam Zheng bdrv_do_release_matching_dirty_bitmap(bs, NULL, true); 312ebab2259SFam Zheng } 313ebab2259SFam Zheng 314ebab2259SFam Zheng void bdrv_disable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 315ebab2259SFam Zheng { 316ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 317ebab2259SFam Zheng bitmap->disabled = true; 318ebab2259SFam Zheng } 319ebab2259SFam Zheng 320ebab2259SFam Zheng void bdrv_enable_dirty_bitmap(BdrvDirtyBitmap *bitmap) 321ebab2259SFam Zheng { 322ebab2259SFam Zheng assert(!bdrv_dirty_bitmap_frozen(bitmap)); 323ebab2259SFam Zheng bitmap->disabled = false; 324ebab2259SFam Zheng } 325ebab2259SFam Zheng 326ebab2259SFam Zheng BlockDirtyInfoList *bdrv_query_dirty_bitmaps(BlockDriverState *bs) 327ebab2259SFam Zheng { 328ebab2259SFam Zheng BdrvDirtyBitmap *bm; 329ebab2259SFam Zheng BlockDirtyInfoList *list = NULL; 330ebab2259SFam Zheng BlockDirtyInfoList **plist = &list; 331ebab2259SFam Zheng 332ebab2259SFam Zheng QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) { 333ebab2259SFam Zheng BlockDirtyInfo *info = g_new0(BlockDirtyInfo, 1); 334ebab2259SFam Zheng BlockDirtyInfoList *entry = g_new0(BlockDirtyInfoList, 1); 335ebab2259SFam Zheng info->count = bdrv_get_dirty_count(bm); 336ebab2259SFam Zheng info->granularity = bdrv_dirty_bitmap_granularity(bm); 337ebab2259SFam Zheng info->has_name = !!bm->name; 338ebab2259SFam Zheng info->name = g_strdup(bm->name); 339ebab2259SFam Zheng info->status = bdrv_dirty_bitmap_status(bm); 340ebab2259SFam Zheng entry->value = info; 341ebab2259SFam Zheng *plist = entry; 342ebab2259SFam Zheng plist = &entry->next; 343ebab2259SFam Zheng } 344ebab2259SFam Zheng 345ebab2259SFam Zheng return list; 346ebab2259SFam Zheng } 347ebab2259SFam Zheng 348ebab2259SFam Zheng int bdrv_get_dirty(BlockDriverState *bs, BdrvDirtyBitmap *bitmap, 349ebab2259SFam Zheng int64_t sector) 350ebab2259SFam Zheng { 351ebab2259SFam Zheng if (bitmap) { 352ebab2259SFam Zheng return hbitmap_get(bitmap->bitmap, sector); 353ebab2259SFam Zheng } else { 354ebab2259SFam Zheng return 0; 355ebab2259SFam Zheng } 356ebab2259SFam Zheng } 357ebab2259SFam Zheng 358ebab2259SFam Zheng /** 359ebab2259SFam Zheng * Chooses a default granularity based on the existing cluster size, 360ebab2259SFam Zheng * but clamped between [4K, 64K]. Defaults to 64K in the case that there 361ebab2259SFam Zheng * is no cluster size information available. 362ebab2259SFam Zheng */ 363ebab2259SFam Zheng uint32_t bdrv_get_default_bitmap_granularity(BlockDriverState *bs) 364ebab2259SFam Zheng { 365ebab2259SFam Zheng BlockDriverInfo bdi; 366ebab2259SFam Zheng uint32_t granularity; 367ebab2259SFam Zheng 368ebab2259SFam Zheng if (bdrv_get_info(bs, &bdi) >= 0 && bdi.cluster_size > 0) { 369ebab2259SFam Zheng granularity = MAX(4096, bdi.cluster_size); 370ebab2259SFam Zheng granularity = MIN(65536, granularity); 371ebab2259SFam Zheng } else { 372ebab2259SFam Zheng granularity = 65536; 373ebab2259SFam Zheng } 374ebab2259SFam Zheng 375ebab2259SFam Zheng return granularity; 376ebab2259SFam Zheng } 377ebab2259SFam Zheng 378ebab2259SFam Zheng uint32_t bdrv_dirty_bitmap_granularity(BdrvDirtyBitmap *bitmap) 379ebab2259SFam Zheng { 380ebab2259SFam Zheng return BDRV_SECTOR_SIZE << hbitmap_granularity(bitmap->bitmap); 381ebab2259SFam Zheng } 382ebab2259SFam Zheng 383dc162c8eSFam Zheng BdrvDirtyBitmapIter *bdrv_dirty_iter_new(BdrvDirtyBitmap *bitmap, 384dc162c8eSFam Zheng uint64_t first_sector) 385ebab2259SFam Zheng { 386dc162c8eSFam Zheng BdrvDirtyBitmapIter *iter = g_new(BdrvDirtyBitmapIter, 1); 387dc162c8eSFam Zheng hbitmap_iter_init(&iter->hbi, bitmap->bitmap, first_sector); 388dc162c8eSFam Zheng iter->bitmap = bitmap; 389dc162c8eSFam Zheng bitmap->active_iterators++; 390dc162c8eSFam Zheng return iter; 391dc162c8eSFam Zheng } 392dc162c8eSFam Zheng 393dc162c8eSFam Zheng void bdrv_dirty_iter_free(BdrvDirtyBitmapIter *iter) 394dc162c8eSFam Zheng { 395dc162c8eSFam Zheng if (!iter) { 396dc162c8eSFam Zheng return; 397dc162c8eSFam Zheng } 398dc162c8eSFam Zheng assert(iter->bitmap->active_iterators > 0); 399dc162c8eSFam Zheng iter->bitmap->active_iterators--; 400dc162c8eSFam Zheng g_free(iter); 401dc162c8eSFam Zheng } 402dc162c8eSFam Zheng 403dc162c8eSFam Zheng int64_t bdrv_dirty_iter_next(BdrvDirtyBitmapIter *iter) 404dc162c8eSFam Zheng { 405dc162c8eSFam Zheng return hbitmap_iter_next(&iter->hbi); 406ebab2259SFam Zheng } 407ebab2259SFam Zheng 408ebab2259SFam Zheng void bdrv_set_dirty_bitmap(BdrvDirtyBitmap *bitmap, 4096d078599SDenis V. Lunev int64_t cur_sector, int64_t nr_sectors) 410ebab2259SFam Zheng { 411ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 412ebab2259SFam Zheng hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors); 413ebab2259SFam Zheng } 414ebab2259SFam Zheng 415ebab2259SFam Zheng void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap, 4166d078599SDenis V. Lunev int64_t cur_sector, int64_t nr_sectors) 417ebab2259SFam Zheng { 418ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 419ebab2259SFam Zheng hbitmap_reset(bitmap->bitmap, cur_sector, nr_sectors); 420ebab2259SFam Zheng } 421ebab2259SFam Zheng 422ebab2259SFam Zheng void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out) 423ebab2259SFam Zheng { 424ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 425ebab2259SFam Zheng if (!out) { 426ebab2259SFam Zheng hbitmap_reset_all(bitmap->bitmap); 427ebab2259SFam Zheng } else { 428ebab2259SFam Zheng HBitmap *backup = bitmap->bitmap; 429ebab2259SFam Zheng bitmap->bitmap = hbitmap_alloc(bitmap->size, 430ebab2259SFam Zheng hbitmap_granularity(backup)); 431ebab2259SFam Zheng *out = backup; 432ebab2259SFam Zheng } 433ebab2259SFam Zheng } 434ebab2259SFam Zheng 435ebab2259SFam Zheng void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in) 436ebab2259SFam Zheng { 437ebab2259SFam Zheng HBitmap *tmp = bitmap->bitmap; 438ebab2259SFam Zheng assert(bdrv_dirty_bitmap_enabled(bitmap)); 439ebab2259SFam Zheng bitmap->bitmap = in; 440ebab2259SFam Zheng hbitmap_free(tmp); 441ebab2259SFam Zheng } 442ebab2259SFam Zheng 443ebab2259SFam Zheng void bdrv_set_dirty(BlockDriverState *bs, int64_t cur_sector, 4446d078599SDenis V. Lunev int64_t nr_sectors) 445ebab2259SFam Zheng { 446ebab2259SFam Zheng BdrvDirtyBitmap *bitmap; 447ebab2259SFam Zheng QLIST_FOREACH(bitmap, &bs->dirty_bitmaps, list) { 448ebab2259SFam Zheng if (!bdrv_dirty_bitmap_enabled(bitmap)) { 449ebab2259SFam Zheng continue; 450ebab2259SFam Zheng } 451ebab2259SFam Zheng hbitmap_set(bitmap->bitmap, cur_sector, nr_sectors); 452ebab2259SFam Zheng } 453ebab2259SFam Zheng } 454ebab2259SFam Zheng 455ebab2259SFam Zheng /** 456dc162c8eSFam Zheng * Advance a BdrvDirtyBitmapIter to an arbitrary offset. 457ebab2259SFam Zheng */ 458dc162c8eSFam Zheng void bdrv_set_dirty_iter(BdrvDirtyBitmapIter *iter, int64_t sector_num) 459ebab2259SFam Zheng { 460dc162c8eSFam Zheng hbitmap_iter_init(&iter->hbi, iter->hbi.hb, sector_num); 461ebab2259SFam Zheng } 462ebab2259SFam Zheng 463ebab2259SFam Zheng int64_t bdrv_get_dirty_count(BdrvDirtyBitmap *bitmap) 464ebab2259SFam Zheng { 465ebab2259SFam Zheng return hbitmap_count(bitmap->bitmap); 466ebab2259SFam Zheng } 467