qemu/block/snapshot.c
<<
>>
Prefs
   1/*
   2 * Block layer snapshot related functions
   3 *
   4 * Copyright (c) 2003-2008 Fabrice Bellard
   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
  25#include "qemu/osdep.h"
  26#include "block/snapshot.h"
  27#include "block/block_int.h"
  28#include "block/qdict.h"
  29#include "qapi/error.h"
  30#include "qapi/qmp/qdict.h"
  31#include "qapi/qmp/qerror.h"
  32#include "qapi/qmp/qstring.h"
  33#include "qemu/option.h"
  34
  35QemuOptsList internal_snapshot_opts = {
  36    .name = "snapshot",
  37    .head = QTAILQ_HEAD_INITIALIZER(internal_snapshot_opts.head),
  38    .desc = {
  39        {
  40            .name = SNAPSHOT_OPT_ID,
  41            .type = QEMU_OPT_STRING,
  42            .help = "snapshot id"
  43        },{
  44            .name = SNAPSHOT_OPT_NAME,
  45            .type = QEMU_OPT_STRING,
  46            .help = "snapshot name"
  47        },{
  48            /* end of list */
  49        }
  50    },
  51};
  52
  53int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
  54                       const char *name)
  55{
  56    QEMUSnapshotInfo *sn_tab, *sn;
  57    int nb_sns, i, ret;
  58
  59    ret = -ENOENT;
  60    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
  61    if (nb_sns < 0) {
  62        return ret;
  63    }
  64    for (i = 0; i < nb_sns; i++) {
  65        sn = &sn_tab[i];
  66        if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
  67            *sn_info = *sn;
  68            ret = 0;
  69            break;
  70        }
  71    }
  72    g_free(sn_tab);
  73    return ret;
  74}
  75
  76/**
  77 * Look up an internal snapshot by @id and @name.
  78 * @bs: block device to search
  79 * @id: unique snapshot ID, or NULL
  80 * @name: snapshot name, or NULL
  81 * @sn_info: location to store information on the snapshot found
  82 * @errp: location to store error, will be set only for exception
  83 *
  84 * This function will traverse snapshot list in @bs to search the matching
  85 * one, @id and @name are the matching condition:
  86 * If both @id and @name are specified, find the first one with id @id and
  87 * name @name.
  88 * If only @id is specified, find the first one with id @id.
  89 * If only @name is specified, find the first one with name @name.
  90 * if none is specified, abort().
  91 *
  92 * Returns: true when a snapshot is found and @sn_info will be filled, false
  93 * when error or not found. If all operation succeed but no matching one is
  94 * found, @errp will NOT be set.
  95 */
  96bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
  97                                       const char *id,
  98                                       const char *name,
  99                                       QEMUSnapshotInfo *sn_info,
 100                                       Error **errp)
 101{
 102    QEMUSnapshotInfo *sn_tab, *sn;
 103    int nb_sns, i;
 104    bool ret = false;
 105
 106    assert(id || name);
 107
 108    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
 109    if (nb_sns < 0) {
 110        error_setg_errno(errp, -nb_sns, "Failed to get a snapshot list");
 111        return false;
 112    } else if (nb_sns == 0) {
 113        return false;
 114    }
 115
 116    if (id && name) {
 117        for (i = 0; i < nb_sns; i++) {
 118            sn = &sn_tab[i];
 119            if (!strcmp(sn->id_str, id) && !strcmp(sn->name, name)) {
 120                *sn_info = *sn;
 121                ret = true;
 122                break;
 123            }
 124        }
 125    } else if (id) {
 126        for (i = 0; i < nb_sns; i++) {
 127            sn = &sn_tab[i];
 128            if (!strcmp(sn->id_str, id)) {
 129                *sn_info = *sn;
 130                ret = true;
 131                break;
 132            }
 133        }
 134    } else if (name) {
 135        for (i = 0; i < nb_sns; i++) {
 136            sn = &sn_tab[i];
 137            if (!strcmp(sn->name, name)) {
 138                *sn_info = *sn;
 139                ret = true;
 140                break;
 141            }
 142        }
 143    }
 144
 145    g_free(sn_tab);
 146    return ret;
 147}
 148
 149int bdrv_can_snapshot(BlockDriverState *bs)
 150{
 151    BlockDriver *drv = bs->drv;
 152    if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
 153        return 0;
 154    }
 155
 156    if (!drv->bdrv_snapshot_create) {
 157        if (bs->file != NULL) {
 158            return bdrv_can_snapshot(bs->file->bs);
 159        }
 160        return 0;
 161    }
 162
 163    return 1;
 164}
 165
 166int bdrv_snapshot_create(BlockDriverState *bs,
 167                         QEMUSnapshotInfo *sn_info)
 168{
 169    BlockDriver *drv = bs->drv;
 170    if (!drv) {
 171        return -ENOMEDIUM;
 172    }
 173    if (drv->bdrv_snapshot_create) {
 174        return drv->bdrv_snapshot_create(bs, sn_info);
 175    }
 176    if (bs->file) {
 177        return bdrv_snapshot_create(bs->file->bs, sn_info);
 178    }
 179    return -ENOTSUP;
 180}
 181
 182int bdrv_snapshot_goto(BlockDriverState *bs,
 183                       const char *snapshot_id,
 184                       Error **errp)
 185{
 186    BlockDriver *drv = bs->drv;
 187    int ret, open_ret;
 188
 189    if (!drv) {
 190        error_setg(errp, "Block driver is closed");
 191        return -ENOMEDIUM;
 192    }
 193
 194    if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {
 195        error_setg(errp, "Device has active dirty bitmaps");
 196        return -EBUSY;
 197    }
 198
 199    if (drv->bdrv_snapshot_goto) {
 200        ret = drv->bdrv_snapshot_goto(bs, snapshot_id);
 201        if (ret < 0) {
 202            error_setg_errno(errp, -ret, "Failed to load snapshot");
 203        }
 204        return ret;
 205    }
 206
 207    if (bs->file) {
 208        BlockDriverState *file;
 209        QDict *options = qdict_clone_shallow(bs->options);
 210        QDict *file_options;
 211        Error *local_err = NULL;
 212
 213        file = bs->file->bs;
 214        /* Prevent it from getting deleted when detached from bs */
 215        bdrv_ref(file);
 216
 217        qdict_extract_subqdict(options, &file_options, "file.");
 218        qobject_unref(file_options);
 219        qdict_put_str(options, "file", bdrv_get_node_name(file));
 220
 221        if (drv->bdrv_close) {
 222            drv->bdrv_close(bs);
 223        }
 224        bdrv_unref_child(bs, bs->file);
 225        bs->file = NULL;
 226
 227        ret = bdrv_snapshot_goto(file, snapshot_id, errp);
 228        open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
 229        qobject_unref(options);
 230        if (open_ret < 0) {
 231            bdrv_unref(file);
 232            bs->drv = NULL;
 233            /* A bdrv_snapshot_goto() error takes precedence */
 234            error_propagate(errp, local_err);
 235            return ret < 0 ? ret : open_ret;
 236        }
 237
 238        assert(bs->file->bs == file);
 239        bdrv_unref(file);
 240        return ret;
 241    }
 242
 243    error_setg(errp, "Block driver does not support snapshots");
 244    return -ENOTSUP;
 245}
 246
 247/**
 248 * Delete an internal snapshot by @snapshot_id and @name.
 249 * @bs: block device used in the operation
 250 * @snapshot_id: unique snapshot ID, or NULL
 251 * @name: snapshot name, or NULL
 252 * @errp: location to store error
 253 *
 254 * If both @snapshot_id and @name are specified, delete the first one with
 255 * id @snapshot_id and name @name.
 256 * If only @snapshot_id is specified, delete the first one with id
 257 * @snapshot_id.
 258 * If only @name is specified, delete the first one with name @name.
 259 * if none is specified, return -EINVAL.
 260 *
 261 * Returns: 0 on success, -errno on failure. If @bs is not inserted, return
 262 * -ENOMEDIUM. If @snapshot_id and @name are both NULL, return -EINVAL. If @bs
 263 * does not support internal snapshot deletion, return -ENOTSUP. If @bs does
 264 * not support parameter @snapshot_id or @name, or one of them is not correctly
 265 * specified, return -EINVAL. If @bs can't find one matching @id and @name,
 266 * return -ENOENT. If @errp != NULL, it will always be filled with error
 267 * message on failure.
 268 */
 269int bdrv_snapshot_delete(BlockDriverState *bs,
 270                         const char *snapshot_id,
 271                         const char *name,
 272                         Error **errp)
 273{
 274    BlockDriver *drv = bs->drv;
 275    int ret;
 276
 277    if (!drv) {
 278        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
 279        return -ENOMEDIUM;
 280    }
 281    if (!snapshot_id && !name) {
 282        error_setg(errp, "snapshot_id and name are both NULL");
 283        return -EINVAL;
 284    }
 285
 286    /* drain all pending i/o before deleting snapshot */
 287    bdrv_drained_begin(bs);
 288
 289    if (drv->bdrv_snapshot_delete) {
 290        ret = drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
 291    } else if (bs->file) {
 292        ret = bdrv_snapshot_delete(bs->file->bs, snapshot_id, name, errp);
 293    } else {
 294        error_setg(errp, "Block format '%s' used by device '%s' "
 295                   "does not support internal snapshot deletion",
 296                   drv->format_name, bdrv_get_device_name(bs));
 297        ret = -ENOTSUP;
 298    }
 299
 300    bdrv_drained_end(bs);
 301    return ret;
 302}
 303
 304int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
 305                                       const char *id_or_name,
 306                                       Error **errp)
 307{
 308    int ret;
 309    Error *local_err = NULL;
 310
 311    ret = bdrv_snapshot_delete(bs, id_or_name, NULL, &local_err);
 312    if (ret == -ENOENT || ret == -EINVAL) {
 313        error_free(local_err);
 314        local_err = NULL;
 315        ret = bdrv_snapshot_delete(bs, NULL, id_or_name, &local_err);
 316    }
 317
 318    if (ret < 0) {
 319        error_propagate(errp, local_err);
 320    }
 321    return ret;
 322}
 323
 324int bdrv_snapshot_list(BlockDriverState *bs,
 325                       QEMUSnapshotInfo **psn_info)
 326{
 327    BlockDriver *drv = bs->drv;
 328    if (!drv) {
 329        return -ENOMEDIUM;
 330    }
 331    if (drv->bdrv_snapshot_list) {
 332        return drv->bdrv_snapshot_list(bs, psn_info);
 333    }
 334    if (bs->file) {
 335        return bdrv_snapshot_list(bs->file->bs, psn_info);
 336    }
 337    return -ENOTSUP;
 338}
 339
 340/**
 341 * Temporarily load an internal snapshot by @snapshot_id and @name.
 342 * @bs: block device used in the operation
 343 * @snapshot_id: unique snapshot ID, or NULL
 344 * @name: snapshot name, or NULL
 345 * @errp: location to store error
 346 *
 347 * If both @snapshot_id and @name are specified, load the first one with
 348 * id @snapshot_id and name @name.
 349 * If only @snapshot_id is specified, load the first one with id
 350 * @snapshot_id.
 351 * If only @name is specified, load the first one with name @name.
 352 * if none is specified, return -EINVAL.
 353 *
 354 * Returns: 0 on success, -errno on fail. If @bs is not inserted, return
 355 * -ENOMEDIUM. If @bs is not readonly, return -EINVAL. If @bs did not support
 356 * internal snapshot, return -ENOTSUP. If qemu can't find a matching @id and
 357 * @name, return -ENOENT. If @errp != NULL, it will always be filled on
 358 * failure.
 359 */
 360int bdrv_snapshot_load_tmp(BlockDriverState *bs,
 361                           const char *snapshot_id,
 362                           const char *name,
 363                           Error **errp)
 364{
 365    BlockDriver *drv = bs->drv;
 366
 367    if (!drv) {
 368        error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
 369        return -ENOMEDIUM;
 370    }
 371    if (!snapshot_id && !name) {
 372        error_setg(errp, "snapshot_id and name are both NULL");
 373        return -EINVAL;
 374    }
 375    if (!bs->read_only) {
 376        error_setg(errp, "Device is not readonly");
 377        return -EINVAL;
 378    }
 379    if (drv->bdrv_snapshot_load_tmp) {
 380        return drv->bdrv_snapshot_load_tmp(bs, snapshot_id, name, errp);
 381    }
 382    error_setg(errp, "Block format '%s' used by device '%s' "
 383               "does not support temporarily loading internal snapshots",
 384               drv->format_name, bdrv_get_device_name(bs));
 385    return -ENOTSUP;
 386}
 387
 388int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
 389                                         const char *id_or_name,
 390                                         Error **errp)
 391{
 392    int ret;
 393    Error *local_err = NULL;
 394
 395    ret = bdrv_snapshot_load_tmp(bs, id_or_name, NULL, &local_err);
 396    if (ret == -ENOENT || ret == -EINVAL) {
 397        error_free(local_err);
 398        local_err = NULL;
 399        ret = bdrv_snapshot_load_tmp(bs, NULL, id_or_name, &local_err);
 400    }
 401
 402    error_propagate(errp, local_err);
 403
 404    return ret;
 405}
 406
 407
 408/* Group operations. All block drivers are involved.
 409 * These functions will properly handle dataplane (take aio_context_acquire
 410 * when appropriate for appropriate block drivers) */
 411
 412bool bdrv_all_can_snapshot(BlockDriverState **first_bad_bs)
 413{
 414    bool ok = true;
 415    BlockDriverState *bs;
 416    BdrvNextIterator it;
 417
 418    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
 419        AioContext *ctx = bdrv_get_aio_context(bs);
 420
 421        aio_context_acquire(ctx);
 422        if (bdrv_is_inserted(bs) && !bdrv_is_read_only(bs)) {
 423            ok = bdrv_can_snapshot(bs);
 424        }
 425        aio_context_release(ctx);
 426        if (!ok) {
 427            bdrv_next_cleanup(&it);
 428            goto fail;
 429        }
 430    }
 431
 432fail:
 433    *first_bad_bs = bs;
 434    return ok;
 435}
 436
 437int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs,
 438                             Error **err)
 439{
 440    int ret = 0;
 441    BlockDriverState *bs;
 442    BdrvNextIterator it;
 443    QEMUSnapshotInfo sn1, *snapshot = &sn1;
 444
 445    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
 446        AioContext *ctx = bdrv_get_aio_context(bs);
 447
 448        aio_context_acquire(ctx);
 449        if (bdrv_can_snapshot(bs) &&
 450                bdrv_snapshot_find(bs, snapshot, name) >= 0) {
 451            ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
 452        }
 453        aio_context_release(ctx);
 454        if (ret < 0) {
 455            bdrv_next_cleanup(&it);
 456            goto fail;
 457        }
 458    }
 459
 460fail:
 461    *first_bad_bs = bs;
 462    return ret;
 463}
 464
 465
 466int bdrv_all_goto_snapshot(const char *name, BlockDriverState **first_bad_bs,
 467                           Error **errp)
 468{
 469    int ret = 0;
 470    BlockDriverState *bs;
 471    BdrvNextIterator it;
 472
 473    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
 474        AioContext *ctx = bdrv_get_aio_context(bs);
 475
 476        aio_context_acquire(ctx);
 477        if (bdrv_can_snapshot(bs)) {
 478            ret = bdrv_snapshot_goto(bs, name, errp);
 479        }
 480        aio_context_release(ctx);
 481        if (ret < 0) {
 482            bdrv_next_cleanup(&it);
 483            goto fail;
 484        }
 485    }
 486
 487fail:
 488    *first_bad_bs = bs;
 489    return ret;
 490}
 491
 492int bdrv_all_find_snapshot(const char *name, BlockDriverState **first_bad_bs)
 493{
 494    QEMUSnapshotInfo sn;
 495    int err = 0;
 496    BlockDriverState *bs;
 497    BdrvNextIterator it;
 498
 499    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
 500        AioContext *ctx = bdrv_get_aio_context(bs);
 501
 502        aio_context_acquire(ctx);
 503        if (bdrv_can_snapshot(bs)) {
 504            err = bdrv_snapshot_find(bs, &sn, name);
 505        }
 506        aio_context_release(ctx);
 507        if (err < 0) {
 508            bdrv_next_cleanup(&it);
 509            goto fail;
 510        }
 511    }
 512
 513fail:
 514    *first_bad_bs = bs;
 515    return err;
 516}
 517
 518int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
 519                             BlockDriverState *vm_state_bs,
 520                             uint64_t vm_state_size,
 521                             BlockDriverState **first_bad_bs)
 522{
 523    int err = 0;
 524    BlockDriverState *bs;
 525    BdrvNextIterator it;
 526
 527    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
 528        AioContext *ctx = bdrv_get_aio_context(bs);
 529
 530        aio_context_acquire(ctx);
 531        if (bs == vm_state_bs) {
 532            sn->vm_state_size = vm_state_size;
 533            err = bdrv_snapshot_create(bs, sn);
 534        } else if (bdrv_can_snapshot(bs)) {
 535            sn->vm_state_size = 0;
 536            err = bdrv_snapshot_create(bs, sn);
 537        }
 538        aio_context_release(ctx);
 539        if (err < 0) {
 540            bdrv_next_cleanup(&it);
 541            goto fail;
 542        }
 543    }
 544
 545fail:
 546    *first_bad_bs = bs;
 547    return err;
 548}
 549
 550BlockDriverState *bdrv_all_find_vmstate_bs(void)
 551{
 552    BlockDriverState *bs;
 553    BdrvNextIterator it;
 554
 555    for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
 556        AioContext *ctx = bdrv_get_aio_context(bs);
 557        bool found;
 558
 559        aio_context_acquire(ctx);
 560        found = bdrv_can_snapshot(bs);
 561        aio_context_release(ctx);
 562
 563        if (found) {
 564            bdrv_next_cleanup(&it);
 565            break;
 566        }
 567    }
 568    return bs;
 569}
 570