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

bitmap-qmp-cmds.c (9215B)


      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}