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

export.c (9131B)


      1/*
      2 * Common block export infrastructure
      3 *
      4 * Copyright (c) 2012, 2020 Red Hat, Inc.
      5 *
      6 * Authors:
      7 * Paolo Bonzini <pbonzini@redhat.com>
      8 * Kevin Wolf <kwolf@redhat.com>
      9 *
     10 * This work is licensed under the terms of the GNU GPL, version 2 or
     11 * later.  See the COPYING file in the top-level directory.
     12 */
     13
     14#include "qemu/osdep.h"
     15
     16#include "block/block.h"
     17#include "sysemu/block-backend.h"
     18#include "sysemu/iothread.h"
     19#include "block/export.h"
     20#include "block/fuse.h"
     21#include "block/nbd.h"
     22#include "qapi/error.h"
     23#include "qapi/qapi-commands-block-export.h"
     24#include "qapi/qapi-events-block-export.h"
     25#include "qemu/id.h"
     26#ifdef CONFIG_VHOST_USER_BLK_SERVER
     27#include "vhost-user-blk-server.h"
     28#endif
     29
     30static const BlockExportDriver *blk_exp_drivers[] = {
     31    &blk_exp_nbd,
     32#ifdef CONFIG_VHOST_USER_BLK_SERVER
     33    &blk_exp_vhost_user_blk,
     34#endif
     35#ifdef CONFIG_FUSE
     36    &blk_exp_fuse,
     37#endif
     38};
     39
     40/* Only accessed from the main thread */
     41static QLIST_HEAD(, BlockExport) block_exports =
     42    QLIST_HEAD_INITIALIZER(block_exports);
     43
     44BlockExport *blk_exp_find(const char *id)
     45{
     46    BlockExport *exp;
     47
     48    QLIST_FOREACH(exp, &block_exports, next) {
     49        if (strcmp(id, exp->id) == 0) {
     50            return exp;
     51        }
     52    }
     53
     54    return NULL;
     55}
     56
     57static const BlockExportDriver *blk_exp_find_driver(BlockExportType type)
     58{
     59    int i;
     60
     61    for (i = 0; i < ARRAY_SIZE(blk_exp_drivers); i++) {
     62        if (blk_exp_drivers[i]->type == type) {
     63            return blk_exp_drivers[i];
     64        }
     65    }
     66    return NULL;
     67}
     68
     69BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
     70{
     71    bool fixed_iothread = export->has_fixed_iothread && export->fixed_iothread;
     72    const BlockExportDriver *drv;
     73    BlockExport *exp = NULL;
     74    BlockDriverState *bs;
     75    BlockBackend *blk = NULL;
     76    AioContext *ctx;
     77    uint64_t perm;
     78    int ret;
     79
     80    if (!id_wellformed(export->id)) {
     81        error_setg(errp, "Invalid block export id");
     82        return NULL;
     83    }
     84    if (blk_exp_find(export->id)) {
     85        error_setg(errp, "Block export id '%s' is already in use", export->id);
     86        return NULL;
     87    }
     88
     89    drv = blk_exp_find_driver(export->type);
     90    if (!drv) {
     91        error_setg(errp, "No driver found for the requested export type");
     92        return NULL;
     93    }
     94
     95    bs = bdrv_lookup_bs(NULL, export->node_name, errp);
     96    if (!bs) {
     97        return NULL;
     98    }
     99
    100    if (!export->has_writable) {
    101        export->writable = false;
    102    }
    103    if (bdrv_is_read_only(bs) && export->writable) {
    104        error_setg(errp, "Cannot export read-only node as writable");
    105        return NULL;
    106    }
    107
    108    ctx = bdrv_get_aio_context(bs);
    109    aio_context_acquire(ctx);
    110
    111    if (export->has_iothread) {
    112        IOThread *iothread;
    113        AioContext *new_ctx;
    114        Error **set_context_errp;
    115
    116        iothread = iothread_by_id(export->iothread);
    117        if (!iothread) {
    118            error_setg(errp, "iothread \"%s\" not found", export->iothread);
    119            goto fail;
    120        }
    121
    122        new_ctx = iothread_get_aio_context(iothread);
    123
    124        /* Ignore errors with fixed-iothread=false */
    125        set_context_errp = fixed_iothread ? errp : NULL;
    126        ret = bdrv_try_set_aio_context(bs, new_ctx, set_context_errp);
    127        if (ret == 0) {
    128            aio_context_release(ctx);
    129            aio_context_acquire(new_ctx);
    130            ctx = new_ctx;
    131        } else if (fixed_iothread) {
    132            goto fail;
    133        }
    134    }
    135
    136    /*
    137     * Block exports are used for non-shared storage migration. Make sure
    138     * that BDRV_O_INACTIVE is cleared and the image is ready for write
    139     * access since the export could be available before migration handover.
    140     * ctx was acquired in the caller.
    141     */
    142    bdrv_invalidate_cache(bs, NULL);
    143
    144    perm = BLK_PERM_CONSISTENT_READ;
    145    if (export->writable) {
    146        perm |= BLK_PERM_WRITE;
    147    }
    148
    149    blk = blk_new(ctx, perm, BLK_PERM_ALL);
    150
    151    if (!fixed_iothread) {
    152        blk_set_allow_aio_context_change(blk, true);
    153    }
    154
    155    ret = blk_insert_bs(blk, bs, errp);
    156    if (ret < 0) {
    157        goto fail;
    158    }
    159
    160    if (!export->has_writethrough) {
    161        export->writethrough = false;
    162    }
    163    blk_set_enable_write_cache(blk, !export->writethrough);
    164
    165    assert(drv->instance_size >= sizeof(BlockExport));
    166    exp = g_malloc0(drv->instance_size);
    167    *exp = (BlockExport) {
    168        .drv        = drv,
    169        .refcount   = 1,
    170        .user_owned = true,
    171        .id         = g_strdup(export->id),
    172        .ctx        = ctx,
    173        .blk        = blk,
    174    };
    175
    176    ret = drv->create(exp, export, errp);
    177    if (ret < 0) {
    178        goto fail;
    179    }
    180
    181    assert(exp->blk != NULL);
    182
    183    QLIST_INSERT_HEAD(&block_exports, exp, next);
    184
    185    aio_context_release(ctx);
    186    return exp;
    187
    188fail:
    189    blk_unref(blk);
    190    aio_context_release(ctx);
    191    if (exp) {
    192        g_free(exp->id);
    193        g_free(exp);
    194    }
    195    return NULL;
    196}
    197
    198/* Callers must hold exp->ctx lock */
    199void blk_exp_ref(BlockExport *exp)
    200{
    201    assert(exp->refcount > 0);
    202    exp->refcount++;
    203}
    204
    205/* Runs in the main thread */
    206static void blk_exp_delete_bh(void *opaque)
    207{
    208    BlockExport *exp = opaque;
    209    AioContext *aio_context = exp->ctx;
    210
    211    aio_context_acquire(aio_context);
    212
    213    assert(exp->refcount == 0);
    214    QLIST_REMOVE(exp, next);
    215    exp->drv->delete(exp);
    216    blk_unref(exp->blk);
    217    qapi_event_send_block_export_deleted(exp->id);
    218    g_free(exp->id);
    219    g_free(exp);
    220
    221    aio_context_release(aio_context);
    222}
    223
    224/* Callers must hold exp->ctx lock */
    225void blk_exp_unref(BlockExport *exp)
    226{
    227    assert(exp->refcount > 0);
    228    if (--exp->refcount == 0) {
    229        /* Touch the block_exports list only in the main thread */
    230        aio_bh_schedule_oneshot(qemu_get_aio_context(), blk_exp_delete_bh,
    231                                exp);
    232    }
    233}
    234
    235/*
    236 * Drops the user reference to the export and requests that all client
    237 * connections and other internally held references start to shut down. When
    238 * the function returns, there may still be active references while the export
    239 * is in the process of shutting down.
    240 *
    241 * Acquires exp->ctx internally. Callers must *not* hold the lock.
    242 */
    243void blk_exp_request_shutdown(BlockExport *exp)
    244{
    245    AioContext *aio_context = exp->ctx;
    246
    247    aio_context_acquire(aio_context);
    248
    249    /*
    250     * If the user doesn't own the export any more, it is already shutting
    251     * down. We must not call .request_shutdown and decrease the refcount a
    252     * second time.
    253     */
    254    if (!exp->user_owned) {
    255        goto out;
    256    }
    257
    258    exp->drv->request_shutdown(exp);
    259
    260    assert(exp->user_owned);
    261    exp->user_owned = false;
    262    blk_exp_unref(exp);
    263
    264out:
    265    aio_context_release(aio_context);
    266}
    267
    268/*
    269 * Returns whether a block export of the given type exists.
    270 * type == BLOCK_EXPORT_TYPE__MAX checks for an export of any type.
    271 */
    272static bool blk_exp_has_type(BlockExportType type)
    273{
    274    BlockExport *exp;
    275
    276    if (type == BLOCK_EXPORT_TYPE__MAX) {
    277        return !QLIST_EMPTY(&block_exports);
    278    }
    279
    280    QLIST_FOREACH(exp, &block_exports, next) {
    281        if (exp->drv->type == type) {
    282            return true;
    283        }
    284    }
    285
    286    return false;
    287}
    288
    289/* type == BLOCK_EXPORT_TYPE__MAX for all types */
    290void blk_exp_close_all_type(BlockExportType type)
    291{
    292    BlockExport *exp, *next;
    293
    294    assert(in_aio_context_home_thread(qemu_get_aio_context()));
    295
    296    QLIST_FOREACH_SAFE(exp, &block_exports, next, next) {
    297        if (type != BLOCK_EXPORT_TYPE__MAX && exp->drv->type != type) {
    298            continue;
    299        }
    300        blk_exp_request_shutdown(exp);
    301    }
    302
    303    AIO_WAIT_WHILE(NULL, blk_exp_has_type(type));
    304}
    305
    306void blk_exp_close_all(void)
    307{
    308    blk_exp_close_all_type(BLOCK_EXPORT_TYPE__MAX);
    309}
    310
    311void qmp_block_export_add(BlockExportOptions *export, Error **errp)
    312{
    313    blk_exp_add(export, errp);
    314}
    315
    316void qmp_block_export_del(const char *id,
    317                          bool has_mode, BlockExportRemoveMode mode,
    318                          Error **errp)
    319{
    320    ERRP_GUARD();
    321    BlockExport *exp;
    322
    323    exp = blk_exp_find(id);
    324    if (exp == NULL) {
    325        error_setg(errp, "Export '%s' is not found", id);
    326        return;
    327    }
    328    if (!exp->user_owned) {
    329        error_setg(errp, "Export '%s' is already shutting down", id);
    330        return;
    331    }
    332
    333    if (!has_mode) {
    334        mode = BLOCK_EXPORT_REMOVE_MODE_SAFE;
    335    }
    336    if (mode == BLOCK_EXPORT_REMOVE_MODE_SAFE && exp->refcount > 1) {
    337        error_setg(errp, "export '%s' still in use", exp->id);
    338        error_append_hint(errp, "Use mode='hard' to force client "
    339                          "disconnect\n");
    340        return;
    341    }
    342
    343    blk_exp_request_shutdown(exp);
    344}
    345
    346BlockExportInfoList *qmp_query_block_exports(Error **errp)
    347{
    348    BlockExportInfoList *head = NULL, **tail = &head;
    349    BlockExport *exp;
    350
    351    QLIST_FOREACH(exp, &block_exports, next) {
    352        BlockExportInfo *info = g_new(BlockExportInfo, 1);
    353        *info = (BlockExportInfo) {
    354            .id             = g_strdup(exp->id),
    355            .type           = exp->drv->type,
    356            .node_name      = g_strdup(bdrv_get_node_name(blk_bs(exp->blk))),
    357            .shutting_down  = !exp->user_owned,
    358        };
    359
    360        QAPI_LIST_APPEND(tail, info);
    361    }
    362
    363    return head;
    364}