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_int.h"
  36#include "qapi/qapi-commands-block.h"
  37#include "qapi/error.h"
  38
  39/**
  40 * block_dirty_bitmap_lookup:
  41 * Return a dirty bitmap (if present), after validating
  42 * the node reference and bitmap names.
  43 *
  44 * @node: The name of the BDS node to search for bitmaps
  45 * @name: The name of the bitmap to search for
  46 * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
  47 * @errp: Output pointer for error information. Can be NULL.
  48 *
  49 * @return: A bitmap object on success, or NULL on failure.
  50 */
  51BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
  52                                           const char *name,
  53                                           BlockDriverState **pbs,
  54                                           Error **errp)
  55{
  56    BlockDriverState *bs;
  57    BdrvDirtyBitmap *bitmap;
  58
  59    if (!node) {
  60        error_setg(errp, "Node cannot be NULL");
  61        return NULL;
  62    }
  63    if (!name) {
  64        error_setg(errp, "Bitmap name cannot be NULL");
  65        return NULL;
  66    }
  67    bs = bdrv_lookup_bs(node, node, NULL);
  68    if (!bs) {
  69        error_setg(errp, "Node '%s' not found", node);
  70        return NULL;
  71    }
  72
  73    bitmap = bdrv_find_dirty_bitmap(bs, name);
  74    if (!bitmap) {
  75        error_setg(errp, "Dirty bitmap '%s' not found", name);
  76        return NULL;
  77    }
  78
  79    if (pbs) {
  80        *pbs = bs;
  81    }
  82
  83    return bitmap;
  84}
  85
  86void qmp_block_dirty_bitmap_add(const char *node, const char *name,
  87                                bool has_granularity, uint32_t granularity,
  88                                bool has_persistent, bool persistent,
  89                                bool has_disabled, bool disabled,
  90                                Error **errp)
  91{
  92    BlockDriverState *bs;
  93    BdrvDirtyBitmap *bitmap;
  94    AioContext *aio_context;
  95
  96    if (!name || name[0] == '\0') {
  97        error_setg(errp, "Bitmap name cannot be empty");
  98        return;
  99    }
 100
 101    bs = bdrv_lookup_bs(node, node, errp);
 102    if (!bs) {
 103        return;
 104    }
 105
 106    aio_context = bdrv_get_aio_context(bs);
 107    aio_context_acquire(aio_context);
 108
 109    if (has_granularity) {
 110        if (granularity < 512 || !is_power_of_2(granularity)) {
 111            error_setg(errp, "Granularity must be power of 2 "
 112                             "and at least 512");
 113            goto out;
 114        }
 115    } else {
 116        /* Default to cluster size, if available: */
 117        granularity = bdrv_get_default_bitmap_granularity(bs);
 118    }
 119
 120    if (!has_persistent) {
 121        persistent = false;
 122    }
 123
 124    if (!has_disabled) {
 125        disabled = false;
 126    }
 127
 128    if (persistent &&
 129        !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
 130    {
 131        goto out;
 132    }
 133
 134    bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
 135    if (bitmap == NULL) {
 136        goto out;
 137    }
 138
 139    if (disabled) {
 140        bdrv_disable_dirty_bitmap(bitmap);
 141    }
 142
 143    bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
 144
 145out:
 146    aio_context_release(aio_context);
 147}
 148
 149BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
 150                                           bool release,
 151                                           BlockDriverState **bitmap_bs,
 152                                           Error **errp)
 153{
 154    BlockDriverState *bs;
 155    BdrvDirtyBitmap *bitmap;
 156    AioContext *aio_context;
 157
 158    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
 159    if (!bitmap || !bs) {
 160        return NULL;
 161    }
 162
 163    aio_context = bdrv_get_aio_context(bs);
 164    aio_context_acquire(aio_context);
 165
 166    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
 167                                errp)) {
 168        aio_context_release(aio_context);
 169        return NULL;
 170    }
 171
 172    if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
 173        bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
 174    {
 175        aio_context_release(aio_context);
 176        return NULL;
 177    }
 178
 179    if (release) {
 180        bdrv_release_dirty_bitmap(bitmap);
 181    }
 182
 183    if (bitmap_bs) {
 184        *bitmap_bs = bs;
 185    }
 186
 187    aio_context_release(aio_context);
 188    return release ? NULL : bitmap;
 189}
 190
 191void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
 192                                   Error **errp)
 193{
 194    block_dirty_bitmap_remove(node, name, true, NULL, errp);
 195}
 196
 197/**
 198 * Completely clear a bitmap, for the purposes of synchronizing a bitmap
 199 * immediately after a full backup operation.
 200 */
 201void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
 202                                  Error **errp)
 203{
 204    BdrvDirtyBitmap *bitmap;
 205    BlockDriverState *bs;
 206
 207    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
 208    if (!bitmap || !bs) {
 209        return;
 210    }
 211
 212    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
 213        return;
 214    }
 215
 216    bdrv_clear_dirty_bitmap(bitmap, NULL);
 217}
 218
 219void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
 220                                   Error **errp)
 221{
 222    BlockDriverState *bs;
 223    BdrvDirtyBitmap *bitmap;
 224
 225    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
 226    if (!bitmap) {
 227        return;
 228    }
 229
 230    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
 231        return;
 232    }
 233
 234    bdrv_enable_dirty_bitmap(bitmap);
 235}
 236
 237void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
 238                                    Error **errp)
 239{
 240    BlockDriverState *bs;
 241    BdrvDirtyBitmap *bitmap;
 242
 243    bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
 244    if (!bitmap) {
 245        return;
 246    }
 247
 248    if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
 249        return;
 250    }
 251
 252    bdrv_disable_dirty_bitmap(bitmap);
 253}
 254
 255BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
 256                                          BlockDirtyBitmapMergeSourceList *bms,
 257                                          HBitmap **backup, Error **errp)
 258{
 259    BlockDriverState *bs;
 260    BdrvDirtyBitmap *dst, *src, *anon;
 261    BlockDirtyBitmapMergeSourceList *lst;
 262    Error *local_err = NULL;
 263
 264    dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
 265    if (!dst) {
 266        return NULL;
 267    }
 268
 269    anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst),
 270                                    NULL, errp);
 271    if (!anon) {
 272        return NULL;
 273    }
 274
 275    for (lst = bms; lst; lst = lst->next) {
 276        switch (lst->value->type) {
 277            const char *name, *node;
 278        case QTYPE_QSTRING:
 279            name = lst->value->u.local;
 280            src = bdrv_find_dirty_bitmap(bs, name);
 281            if (!src) {
 282                error_setg(errp, "Dirty bitmap '%s' not found", name);
 283                dst = NULL;
 284                goto out;
 285            }
 286            break;
 287        case QTYPE_QDICT:
 288            node = lst->value->u.external.node;
 289            name = lst->value->u.external.name;
 290            src = block_dirty_bitmap_lookup(node, name, NULL, errp);
 291            if (!src) {
 292                dst = NULL;
 293                goto out;
 294            }
 295            break;
 296        default:
 297            abort();
 298        }
 299
 300        bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err);
 301        if (local_err) {
 302            error_propagate(errp, local_err);
 303            dst = NULL;
 304            goto out;
 305        }
 306    }
 307
 308    /* Merge into dst; dst is unchanged on failure. */
 309    bdrv_merge_dirty_bitmap(dst, anon, backup, errp);
 310
 311 out:
 312    bdrv_release_dirty_bitmap(anon);
 313    return dst;
 314}
 315
 316void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
 317                                  BlockDirtyBitmapMergeSourceList *bitmaps,
 318                                  Error **errp)
 319{
 320    block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
 321}
 322