cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

backup.c (14789B)


      1/*
      2 * QEMU backup
      3 *
      4 * Copyright (C) 2013 Proxmox Server Solutions
      5 * Copyright (c) 2019 Virtuozzo International GmbH.
      6 *
      7 * Authors:
      8 *  Dietmar Maurer (dietmar@proxmox.com)
      9 *
     10 * This work is licensed under the terms of the GNU GPL, version 2 or later.
     11 * See the COPYING file in the top-level directory.
     12 *
     13 */
     14
     15#include "qemu/osdep.h"
     16
     17#include "trace.h"
     18#include "block/block.h"
     19#include "block/block_int.h"
     20#include "block/blockjob_int.h"
     21#include "block/block_backup.h"
     22#include "block/block-copy.h"
     23#include "qapi/error.h"
     24#include "qapi/qmp/qerror.h"
     25#include "qemu/cutils.h"
     26#include "sysemu/block-backend.h"
     27#include "qemu/bitmap.h"
     28#include "qemu/error-report.h"
     29
     30#include "block/copy-before-write.h"
     31
     32typedef struct BackupBlockJob {
     33    BlockJob common;
     34    BlockDriverState *cbw;
     35    BlockDriverState *source_bs;
     36    BlockDriverState *target_bs;
     37
     38    BdrvDirtyBitmap *sync_bitmap;
     39
     40    MirrorSyncMode sync_mode;
     41    BitmapSyncMode bitmap_mode;
     42    BlockdevOnError on_source_error;
     43    BlockdevOnError on_target_error;
     44    uint64_t len;
     45    int64_t cluster_size;
     46    BackupPerf perf;
     47
     48    BlockCopyState *bcs;
     49
     50    bool wait;
     51    BlockCopyCallState *bg_bcs_call;
     52} BackupBlockJob;
     53
     54static const BlockJobDriver backup_job_driver;
     55
     56static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
     57{
     58    BdrvDirtyBitmap *bm;
     59    bool sync = (((ret == 0) || (job->bitmap_mode == BITMAP_SYNC_MODE_ALWAYS)) \
     60                 && (job->bitmap_mode != BITMAP_SYNC_MODE_NEVER));
     61
     62    if (sync) {
     63        /*
     64         * We succeeded, or we always intended to sync the bitmap.
     65         * Delete this bitmap and install the child.
     66         */
     67        bm = bdrv_dirty_bitmap_abdicate(job->sync_bitmap, NULL);
     68    } else {
     69        /*
     70         * We failed, or we never intended to sync the bitmap anyway.
     71         * Merge the successor back into the parent, keeping all data.
     72         */
     73        bm = bdrv_reclaim_dirty_bitmap(job->sync_bitmap, NULL);
     74    }
     75
     76    assert(bm);
     77
     78    if (ret < 0 && job->bitmap_mode == BITMAP_SYNC_MODE_ALWAYS) {
     79        /* If we failed and synced, merge in the bits we didn't copy: */
     80        bdrv_dirty_bitmap_merge_internal(bm, block_copy_dirty_bitmap(job->bcs),
     81                                         NULL, true);
     82    }
     83}
     84
     85static void backup_commit(Job *job)
     86{
     87    BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
     88    if (s->sync_bitmap) {
     89        backup_cleanup_sync_bitmap(s, 0);
     90    }
     91}
     92
     93static void backup_abort(Job *job)
     94{
     95    BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
     96    if (s->sync_bitmap) {
     97        backup_cleanup_sync_bitmap(s, -1);
     98    }
     99}
    100
    101static void backup_clean(Job *job)
    102{
    103    BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
    104    block_job_remove_all_bdrv(&s->common);
    105    bdrv_cbw_drop(s->cbw);
    106}
    107
    108void backup_do_checkpoint(BlockJob *job, Error **errp)
    109{
    110    BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
    111
    112    assert(block_job_driver(job) == &backup_job_driver);
    113
    114    if (backup_job->sync_mode != MIRROR_SYNC_MODE_NONE) {
    115        error_setg(errp, "The backup job only supports block checkpoint in"
    116                   " sync=none mode");
    117        return;
    118    }
    119
    120    bdrv_set_dirty_bitmap(block_copy_dirty_bitmap(backup_job->bcs), 0,
    121                          backup_job->len);
    122}
    123
    124static BlockErrorAction backup_error_action(BackupBlockJob *job,
    125                                            bool read, int error)
    126{
    127    if (read) {
    128        return block_job_error_action(&job->common, job->on_source_error,
    129                                      true, error);
    130    } else {
    131        return block_job_error_action(&job->common, job->on_target_error,
    132                                      false, error);
    133    }
    134}
    135
    136static void coroutine_fn backup_block_copy_callback(void *opaque)
    137{
    138    BackupBlockJob *s = opaque;
    139
    140    if (s->wait) {
    141        s->wait = false;
    142        aio_co_wake(s->common.job.co);
    143    } else {
    144        job_enter(&s->common.job);
    145    }
    146}
    147
    148static int coroutine_fn backup_loop(BackupBlockJob *job)
    149{
    150    BlockCopyCallState *s = NULL;
    151    int ret = 0;
    152    bool error_is_read;
    153    BlockErrorAction act;
    154
    155    while (true) { /* retry loop */
    156        job->bg_bcs_call = s = block_copy_async(job->bcs, 0,
    157                QEMU_ALIGN_UP(job->len, job->cluster_size),
    158                job->perf.max_workers, job->perf.max_chunk,
    159                backup_block_copy_callback, job);
    160
    161        while (!block_copy_call_finished(s) &&
    162               !job_is_cancelled(&job->common.job))
    163        {
    164            job_yield(&job->common.job);
    165        }
    166
    167        if (!block_copy_call_finished(s)) {
    168            assert(job_is_cancelled(&job->common.job));
    169            /*
    170             * Note that we can't use job_yield() here, as it doesn't work for
    171             * cancelled job.
    172             */
    173            block_copy_call_cancel(s);
    174            job->wait = true;
    175            qemu_coroutine_yield();
    176            assert(block_copy_call_finished(s));
    177            ret = 0;
    178            goto out;
    179        }
    180
    181        if (job_is_cancelled(&job->common.job) ||
    182            block_copy_call_succeeded(s))
    183        {
    184            ret = 0;
    185            goto out;
    186        }
    187
    188        if (block_copy_call_cancelled(s)) {
    189            /*
    190             * Job is not cancelled but only block-copy call. This is possible
    191             * after job pause. Now the pause is finished, start new block-copy
    192             * iteration.
    193             */
    194            block_copy_call_free(s);
    195            continue;
    196        }
    197
    198        /* The only remaining case is failed block-copy call. */
    199        assert(block_copy_call_failed(s));
    200
    201        ret = block_copy_call_status(s, &error_is_read);
    202        act = backup_error_action(job, error_is_read, -ret);
    203        switch (act) {
    204        case BLOCK_ERROR_ACTION_REPORT:
    205            goto out;
    206        case BLOCK_ERROR_ACTION_STOP:
    207            /*
    208             * Go to pause prior to starting new block-copy call on the next
    209             * iteration.
    210             */
    211            job_pause_point(&job->common.job);
    212            break;
    213        case BLOCK_ERROR_ACTION_IGNORE:
    214            /* Proceed to new block-copy call to retry. */
    215            break;
    216        default:
    217            abort();
    218        }
    219
    220        block_copy_call_free(s);
    221    }
    222
    223out:
    224    block_copy_call_free(s);
    225    job->bg_bcs_call = NULL;
    226    return ret;
    227}
    228
    229static void backup_init_bcs_bitmap(BackupBlockJob *job)
    230{
    231    bool ret;
    232    uint64_t estimate;
    233    BdrvDirtyBitmap *bcs_bitmap = block_copy_dirty_bitmap(job->bcs);
    234
    235    if (job->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
    236        bdrv_clear_dirty_bitmap(bcs_bitmap, NULL);
    237        ret = bdrv_dirty_bitmap_merge_internal(bcs_bitmap, job->sync_bitmap,
    238                                               NULL, true);
    239        assert(ret);
    240    } else if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
    241        /*
    242         * We can't hog the coroutine to initialize this thoroughly.
    243         * Set a flag and resume work when we are able to yield safely.
    244         */
    245        block_copy_set_skip_unallocated(job->bcs, true);
    246    }
    247
    248    estimate = bdrv_get_dirty_count(bcs_bitmap);
    249    job_progress_set_remaining(&job->common.job, estimate);
    250}
    251
    252static int coroutine_fn backup_run(Job *job, Error **errp)
    253{
    254    BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
    255    int ret;
    256
    257    backup_init_bcs_bitmap(s);
    258
    259    if (s->sync_mode == MIRROR_SYNC_MODE_TOP) {
    260        int64_t offset = 0;
    261        int64_t count;
    262
    263        for (offset = 0; offset < s->len; ) {
    264            if (job_is_cancelled(job)) {
    265                return -ECANCELED;
    266            }
    267
    268            job_pause_point(job);
    269
    270            if (job_is_cancelled(job)) {
    271                return -ECANCELED;
    272            }
    273
    274            ret = block_copy_reset_unallocated(s->bcs, offset, &count);
    275            if (ret < 0) {
    276                return ret;
    277            }
    278
    279            offset += count;
    280        }
    281        block_copy_set_skip_unallocated(s->bcs, false);
    282    }
    283
    284    if (s->sync_mode == MIRROR_SYNC_MODE_NONE) {
    285        /*
    286         * All bits are set in bcs bitmap to allow any cluster to be copied.
    287         * This does not actually require them to be copied.
    288         */
    289        while (!job_is_cancelled(job)) {
    290            /*
    291             * Yield until the job is cancelled.  We just let our before_write
    292             * notify callback service CoW requests.
    293             */
    294            job_yield(job);
    295        }
    296    } else {
    297        return backup_loop(s);
    298    }
    299
    300    return 0;
    301}
    302
    303static void coroutine_fn backup_pause(Job *job)
    304{
    305    BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
    306
    307    if (s->bg_bcs_call && !block_copy_call_finished(s->bg_bcs_call)) {
    308        block_copy_call_cancel(s->bg_bcs_call);
    309        s->wait = true;
    310        qemu_coroutine_yield();
    311    }
    312}
    313
    314static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
    315{
    316    BackupBlockJob *s = container_of(job, BackupBlockJob, common);
    317
    318    /*
    319     * block_job_set_speed() is called first from block_job_create(), when we
    320     * don't yet have s->bcs.
    321     */
    322    if (s->bcs) {
    323        block_copy_set_speed(s->bcs, speed);
    324        if (s->bg_bcs_call) {
    325            block_copy_kick(s->bg_bcs_call);
    326        }
    327    }
    328}
    329
    330static bool backup_cancel(Job *job, bool force)
    331{
    332    BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
    333
    334    bdrv_cancel_in_flight(s->target_bs);
    335    return true;
    336}
    337
    338static const BlockJobDriver backup_job_driver = {
    339    .job_driver = {
    340        .instance_size          = sizeof(BackupBlockJob),
    341        .job_type               = JOB_TYPE_BACKUP,
    342        .free                   = block_job_free,
    343        .user_resume            = block_job_user_resume,
    344        .run                    = backup_run,
    345        .commit                 = backup_commit,
    346        .abort                  = backup_abort,
    347        .clean                  = backup_clean,
    348        .pause                  = backup_pause,
    349        .cancel                 = backup_cancel,
    350    },
    351    .set_speed = backup_set_speed,
    352};
    353
    354BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
    355                  BlockDriverState *target, int64_t speed,
    356                  MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
    357                  BitmapSyncMode bitmap_mode,
    358                  bool compress,
    359                  const char *filter_node_name,
    360                  BackupPerf *perf,
    361                  BlockdevOnError on_source_error,
    362                  BlockdevOnError on_target_error,
    363                  int creation_flags,
    364                  BlockCompletionFunc *cb, void *opaque,
    365                  JobTxn *txn, Error **errp)
    366{
    367    int64_t len, target_len;
    368    BackupBlockJob *job = NULL;
    369    int64_t cluster_size;
    370    BlockDriverState *cbw = NULL;
    371    BlockCopyState *bcs = NULL;
    372
    373    assert(bs);
    374    assert(target);
    375
    376    /* QMP interface protects us from these cases */
    377    assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
    378    assert(sync_bitmap || sync_mode != MIRROR_SYNC_MODE_BITMAP);
    379
    380    if (bs == target) {
    381        error_setg(errp, "Source and target cannot be the same");
    382        return NULL;
    383    }
    384
    385    if (!bdrv_is_inserted(bs)) {
    386        error_setg(errp, "Device is not inserted: %s",
    387                   bdrv_get_device_name(bs));
    388        return NULL;
    389    }
    390
    391    if (!bdrv_is_inserted(target)) {
    392        error_setg(errp, "Device is not inserted: %s",
    393                   bdrv_get_device_name(target));
    394        return NULL;
    395    }
    396
    397    if (compress && !bdrv_supports_compressed_writes(target)) {
    398        error_setg(errp, "Compression is not supported for this drive %s",
    399                   bdrv_get_device_name(target));
    400        return NULL;
    401    }
    402
    403    if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
    404        return NULL;
    405    }
    406
    407    if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
    408        return NULL;
    409    }
    410
    411    if (perf->max_workers < 1 || perf->max_workers > INT_MAX) {
    412        error_setg(errp, "max-workers must be between 1 and %d", INT_MAX);
    413        return NULL;
    414    }
    415
    416    if (perf->max_chunk < 0) {
    417        error_setg(errp, "max-chunk must be zero (which means no limit) or "
    418                   "positive");
    419        return NULL;
    420    }
    421
    422    if (sync_bitmap) {
    423        /* If we need to write to this bitmap, check that we can: */
    424        if (bitmap_mode != BITMAP_SYNC_MODE_NEVER &&
    425            bdrv_dirty_bitmap_check(sync_bitmap, BDRV_BITMAP_DEFAULT, errp)) {
    426            return NULL;
    427        }
    428
    429        /* Create a new bitmap, and freeze/disable this one. */
    430        if (bdrv_dirty_bitmap_create_successor(sync_bitmap, errp) < 0) {
    431            return NULL;
    432        }
    433    }
    434
    435    len = bdrv_getlength(bs);
    436    if (len < 0) {
    437        error_setg_errno(errp, -len, "Unable to get length for '%s'",
    438                         bdrv_get_device_or_node_name(bs));
    439        goto error;
    440    }
    441
    442    target_len = bdrv_getlength(target);
    443    if (target_len < 0) {
    444        error_setg_errno(errp, -target_len, "Unable to get length for '%s'",
    445                         bdrv_get_device_or_node_name(bs));
    446        goto error;
    447    }
    448
    449    if (target_len != len) {
    450        error_setg(errp, "Source and target image have different sizes");
    451        goto error;
    452    }
    453
    454    cbw = bdrv_cbw_append(bs, target, filter_node_name, &bcs, errp);
    455    if (!cbw) {
    456        goto error;
    457    }
    458
    459    cluster_size = block_copy_cluster_size(bcs);
    460
    461    if (perf->max_chunk && perf->max_chunk < cluster_size) {
    462        error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
    463                   "cluster size (%" PRIi64 ")", perf->max_chunk, cluster_size);
    464        goto error;
    465    }
    466
    467    /* job->len is fixed, so we can't allow resize */
    468    job = block_job_create(job_id, &backup_job_driver, txn, cbw,
    469                           0, BLK_PERM_ALL,
    470                           speed, creation_flags, cb, opaque, errp);
    471    if (!job) {
    472        goto error;
    473    }
    474
    475    job->cbw = cbw;
    476    job->source_bs = bs;
    477    job->target_bs = target;
    478    job->on_source_error = on_source_error;
    479    job->on_target_error = on_target_error;
    480    job->sync_mode = sync_mode;
    481    job->sync_bitmap = sync_bitmap;
    482    job->bitmap_mode = bitmap_mode;
    483    job->bcs = bcs;
    484    job->cluster_size = cluster_size;
    485    job->len = len;
    486    job->perf = *perf;
    487
    488    block_copy_set_copy_opts(bcs, perf->use_copy_range, compress);
    489    block_copy_set_progress_meter(bcs, &job->common.job.progress);
    490    block_copy_set_speed(bcs, speed);
    491
    492    /* Required permissions are taken by copy-before-write filter target */
    493    block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
    494                       &error_abort);
    495
    496    return &job->common;
    497
    498 error:
    499    if (sync_bitmap) {
    500        bdrv_reclaim_dirty_bitmap(sync_bitmap, NULL);
    501    }
    502    if (cbw) {
    503        bdrv_cbw_drop(cbw);
    504    }
    505
    506    return NULL;
    507}