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