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