qemu/block/monitor/bitmap-qmp-cmds.c
<<
>>
Prefs
   1/*
   2 * QEMU block dirty bitmap QMP commands
   3 *
   4 * Copyright (c) 2003-2008 Fabrice Bellard
   5 *
   6 * This work is licensed under the terms of the GNU GPL, version 2 or
   7 * later.  See the COPYING file in the top-level directory.
   8 *
   9 * This file incorporates work covered by the following copyright and
  10 * permission notice:
  11 *
  12 * Copyright (c) 2003-2008 Fabrice Bellard
  13 *
  14 * Permission is hereby granted, free of charge, to any person obtaining a copy
  15 * of this software and associated documentation files (the "Software"), to deal
  16 * in the Software without restriction, including without limitation the rights
  17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  18 * copies of the Software, and to permit persons to whom the Software is
  19 * furnished to do so, subject to the following conditions:
  20 *
  21 * The above copyright notice and this permission notice shall be included in
  22 * all copies or substantial portions of the Software.
  23 *
  24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  27 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  30 * THE SOFTWARE.
  31 */
  32
  33#include "qemu/osdep.h"
  34
  35#include "block/block-io.h"
  36#include "block/block_int.h"
  37#include "block/dirty-bitmap.h"
  38#include "qapi/qapi-commands-block.h"
  39#include "qapi/error.h"
  40
  41/**
  42 * block_dirty_bitmap_lookup:
  43 * Return a dirty bitmap (if present), after validating
  44 * the node reference and bitmap names.
  45 *
  46 * @node: The name of the BDS node to search for bitmaps
  47 * @name: The name of the bitmap to search for
  48 * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
  49 * @errp: Output pointer for error information. Can be NULL.
  50 *
  51 * @return: A bitmap object on success, or NULL on failure.
  52 */
  53BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
  54                                           const char *name,
  55                                           BlockDriverState **pbs,
  56                                           Error **errp)
  57{
  58    BlockDriverState *bs;
  59    BdrvDirtyBitmap *bitmap;
  60
  61    GLOBAL_STATE_CODE();
  62
  63    if (!node) {
  64        error_setg(errp, "Node cannot be NULL");
  65        return NULL;
  66    }
  67    if (!name) {
  68        error_setg(errp, "Bitmap name cannot be NULL");
  69        return NULL;
  70    }
  71    bs = bdrv_lookup_bs(node, node, NULL);
  72    if (!bs) {
  73        error_setg(errp, "Node '%s' not found", node);
  74        return NULL;
  75    }
  76
  77    bitmap = bdrv_find_dirty_bitmap(bs, name);
  78    if (!bitmap) {
  79        error_setg(errp, "Dirty bitmap '%s' not found", name);
  80        return NULL;
  81    }
  82
  83    if (pbs) {
  84        *pbs = bs;
  85    }
  86
  87    return bitmap;
  88}
  89
  90void qmp_block_dirty_bitmap_add(const char *node, const char *name,
  91                                bool has_granularity, uint32_t granularity,
  92                                bool has_persistent, bool persistent,
  93                                bool has_disabled, bool disabled,
  94                                Error **errp)
  95{
  96    BlockDriverState *bs;
  97    BdrvDirtyBitmap *bitmap;
  98    AioContext *aio_context;
  99
 100    if (!name || name[0] == '\0') {
 101        error_setg(errp, "Bitmap name cannot be empty");
 102        return;
 103    }
 104
 105    bs = bdrv_lookup_bs(node, node, errp);
 106    if (!bs) {
 107        return;
 108    }
 109
 110    aio_context = bdrv_get_aio_context(bs);
 111    aio_context_acquire(aio_context);
 112
 113    if (has_granularity) {
 114        if (granularity < 512 || !is_power_of_2(granularity)) {
 115            error_setg(errp, "Granularity must be power of 2 "
 116                             "and at least 512");
 117            goto out;
 118        }
 119    } else {
 120        /* Default to cluster size, if available: */
 121        granularity = bdrv_get_default_bitmap_granularity(bs);
 122    }
 123
 124    if (!has_persistent) {
 125        persistent = false;
 126    }
 127
 128    if (!has_disabled) {
 129        disabled = false;
 130    }
 131
 132    if (persistent &&
 133        !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
 134    {
 135        goto out;
 136    }
 137
 138    bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
 139    if (bitmap == NULL) {
 140        goto out;
 141    }
 142
 143    if (disabled) {
 144        bdrv_disable_dirty_bitmap(bitmap);
 145    }
 146
 147    bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
 148
 149out:
 150    aio_context_release(aio_context);
 151}
 152
 153BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
 154                                           bool release,
 155                                           BlockDriverState **bitmap_bs,
 156                                           Error **errp)
 157{
 158    BlockDriverState *bs;
 159    BdrvDirtyBitmap *bitmap;
 160    AioContext *aio_context;
 161
 162    GLOBAL_STATE_CODE();
 163
 164    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
 165    if (!bitmap || !bs) {
 166        return NULL;
 167    }
 168
 169    aio_context = bdrv_get_aio_context(bs);
 170    aio_context_acquire(aio_context);
 171
 172    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
 173                                errp)) {
 174        aio_context_release(aio_context);
 175        return NULL;
 176    }
 177
 178    if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
 179        bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
 180    {
 181        aio_context_release(aio_context);
 182        return NULL;
 183    }
 184
 185    if (release) {
 186        bdrv_release_dirty_bitmap(bitmap);
 187    }
 188
 189    if (bitmap_bs) {
 190        *bitmap_bs = bs;
 191    }
 192
 193    aio_context_release(aio_context);
 194    return release ? NULL : bitmap;
 195}
 196
 197void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
 198                                   Error **errp)
 199{
 200    block_dirty_bitmap_remove(node, name, true, NULL, errp);
 201}
 202
 203/**
 204 * Completely clear a bitmap, for the purposes of synchronizing a bitmap
 205 * immediately after a full backup operation.
 206 */
 207void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
 208                                  Error **errp)
 209{
 210    BdrvDirtyBitmap *bitmap;
 211    BlockDriverState *bs;
 212
 213    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
 214    if (!bitmap || !bs) {
 215        return;
 216    }
 217
 218    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
 219        return;
 220    }
 221
 222    bdrv_clear_dirty_bitmap(bitmap, NULL);
 223}
 224
 225void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
 226                                   Error **errp)
 227{
 228    BlockDriverState *bs;
 229    BdrvDirtyBitmap *bitmap;
 230
 231    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
 232    if (!bitmap) {
 233        return;
 234    }
 235
 236    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
 237        return;
 238    }
 239
 240    bdrv_enable_dirty_bitmap(bitmap);
 241}
 242
 243void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
 244                                    Error **errp)
 245{
 246    BlockDriverState *bs;
 247    BdrvDirtyBitmap *bitmap;
 248
 249    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
 250    if (!bitmap) {
 251        return;
 252    }
 253
 254    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
 255        return;
 256    }
 257
 258    bdrv_disable_dirty_bitmap(bitmap);
 259}
 260
 261BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
 262                                          BlockDirtyBitmapOrStrList *bms,
 263                                          HBitmap **backup, Error **errp)
 264{
 265    BlockDriverState *bs;
 266    BdrvDirtyBitmap *dst, *src;
 267    BlockDirtyBitmapOrStrList *lst;
 268    HBitmap *local_backup = NULL;
 269
 270    GLOBAL_STATE_CODE();
 271
 272    dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
 273    if (!dst) {
 274        return NULL;
 275    }
 276
 277    for (lst = bms; lst; lst = lst->next) {
 278        switch (lst->value->type) {
 279            const char *name, *node;
 280        case QTYPE_QSTRING:
 281            name = lst->value->u.local;
 282            src = bdrv_find_dirty_bitmap(bs, name);
 283            if (!src) {
 284                error_setg(errp, "Dirty bitmap '%s' not found", name);
 285                goto fail;
 286            }
 287            break;
 288        case QTYPE_QDICT:
 289            node = lst->value->u.external.node;
 290            name = lst->value->u.external.name;
 291            src = block_dirty_bitmap_lookup(node, name, NULL, errp);
 292            if (!src) {
 293                goto fail;
 294            }
 295            break;
 296        default:
 297            abort();
 298        }
 299
 300        /* We do backup only for first merge operation */
 301        if (!bdrv_merge_dirty_bitmap(dst, src,
 302                                     local_backup ? NULL : &local_backup,
 303                                     errp))
 304        {
 305            goto fail;
 306        }
 307    }
 308
 309    if (backup) {
 310        *backup = local_backup;
 311    } else {
 312        hbitmap_free(local_backup);
 313    }
 314
 315    return dst;
 316
 317fail:
 318    if (local_backup) {
 319        bdrv_restore_dirty_bitmap(dst, local_backup);
 320    }
 321
 322    return NULL;
 323}
 324
 325void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
 326                                  BlockDirtyBitmapOrStrList *bitmaps,
 327                                  Error **errp)
 328{
 329    block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
 330}
 331