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