qemu/block/export/export.c
<<
>>
Prefs
   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
 115        iothread = iothread_by_id(export->iothread);
 116        if (!iothread) {
 117            error_setg(errp, "iothread \"%s\" not found", export->iothread);
 118            goto fail;
 119        }
 120
 121        new_ctx = iothread_get_aio_context(iothread);
 122
 123        ret = bdrv_try_set_aio_context(bs, new_ctx, errp);
 124        if (ret == 0) {
 125            aio_context_release(ctx);
 126            aio_context_acquire(new_ctx);
 127            ctx = new_ctx;
 128        } else if (fixed_iothread) {
 129            goto fail;
 130        }
 131    }
 132
 133    /*
 134     * Block exports are used for non-shared storage migration. Make sure
 135     * that BDRV_O_INACTIVE is cleared and the image is ready for write
 136     * access since the export could be available before migration handover.
 137     * ctx was acquired in the caller.
 138     */
 139    bdrv_invalidate_cache(bs, NULL);
 140
 141    perm = BLK_PERM_CONSISTENT_READ;
 142    if (export->writable) {
 143        perm |= BLK_PERM_WRITE;
 144    }
 145
 146    blk = blk_new(ctx, perm, BLK_PERM_ALL);
 147
 148    if (!fixed_iothread) {
 149        blk_set_allow_aio_context_change(blk, true);
 150    }
 151
 152    ret = blk_insert_bs(blk, bs, errp);
 153    if (ret < 0) {
 154        goto fail;
 155    }
 156
 157    if (!export->has_writethrough) {
 158        export->writethrough = false;
 159    }
 160    blk_set_enable_write_cache(blk, !export->writethrough);
 161
 162    assert(drv->instance_size >= sizeof(BlockExport));
 163    exp = g_malloc0(drv->instance_size);
 164    *exp = (BlockExport) {
 165        .drv        = drv,
 166        .refcount   = 1,
 167        .user_owned = true,
 168        .id         = g_strdup(export->id),
 169        .ctx        = ctx,
 170        .blk        = blk,
 171    };
 172
 173    ret = drv->create(exp, export, errp);
 174    if (ret < 0) {
 175        goto fail;
 176    }
 177
 178    assert(exp->blk != NULL);
 179
 180    QLIST_INSERT_HEAD(&block_exports, exp, next);
 181
 182    aio_context_release(ctx);
 183    return exp;
 184
 185fail:
 186    blk_unref(blk);
 187    aio_context_release(ctx);
 188    if (exp) {
 189        g_free(exp->id);
 190        g_free(exp);
 191    }
 192    return NULL;
 193}
 194
 195/* Callers must hold exp->ctx lock */
 196void blk_exp_ref(BlockExport *exp)
 197{
 198    assert(exp->refcount > 0);
 199    exp->refcount++;
 200}
 201
 202/* Runs in the main thread */
 203static void blk_exp_delete_bh(void *opaque)
 204{
 205    BlockExport *exp = opaque;
 206    AioContext *aio_context = exp->ctx;
 207
 208    aio_context_acquire(aio_context);
 209
 210    assert(exp->refcount == 0);
 211    QLIST_REMOVE(exp, next);
 212    exp->drv->delete(exp);
 213    blk_unref(exp->blk);
 214    qapi_event_send_block_export_deleted(exp->id);
 215    g_free(exp->id);
 216    g_free(exp);
 217
 218    aio_context_release(aio_context);
 219}
 220
 221/* Callers must hold exp->ctx lock */
 222void blk_exp_unref(BlockExport *exp)
 223{
 224    assert(exp->refcount > 0);
 225    if (--exp->refcount == 0) {
 226        /* Touch the block_exports list only in the main thread */
 227        aio_bh_schedule_oneshot(qemu_get_aio_context(), blk_exp_delete_bh,
 228                                exp);
 229    }
 230}
 231
 232/*
 233 * Drops the user reference to the export and requests that all client
 234 * connections and other internally held references start to shut down. When
 235 * the function returns, there may still be active references while the export
 236 * is in the process of shutting down.
 237 *
 238 * Acquires exp->ctx internally. Callers must *not* hold the lock.
 239 */
 240void blk_exp_request_shutdown(BlockExport *exp)
 241{
 242    AioContext *aio_context = exp->ctx;
 243
 244    aio_context_acquire(aio_context);
 245
 246    /*
 247     * If the user doesn't own the export any more, it is already shutting
 248     * down. We must not call .request_shutdown and decrease the refcount a
 249     * second time.
 250     */
 251    if (!exp->user_owned) {
 252        goto out;
 253    }
 254
 255    exp->drv->request_shutdown(exp);
 256
 257    assert(exp->user_owned);
 258    exp->user_owned = false;
 259    blk_exp_unref(exp);
 260
 261out:
 262    aio_context_release(aio_context);
 263}
 264
 265/*
 266 * Returns whether a block export of the given type exists.
 267 * type == BLOCK_EXPORT_TYPE__MAX checks for an export of any type.
 268 */
 269static bool blk_exp_has_type(BlockExportType type)
 270{
 271    BlockExport *exp;
 272
 273    if (type == BLOCK_EXPORT_TYPE__MAX) {
 274        return !QLIST_EMPTY(&block_exports);
 275    }
 276
 277    QLIST_FOREACH(exp, &block_exports, next) {
 278        if (exp->drv->type == type) {
 279            return true;
 280        }
 281    }
 282
 283    return false;
 284}
 285
 286/* type == BLOCK_EXPORT_TYPE__MAX for all types */
 287void blk_exp_close_all_type(BlockExportType type)
 288{
 289    BlockExport *exp, *next;
 290
 291    assert(in_aio_context_home_thread(qemu_get_aio_context()));
 292
 293    QLIST_FOREACH_SAFE(exp, &block_exports, next, next) {
 294        if (type != BLOCK_EXPORT_TYPE__MAX && exp->drv->type != type) {
 295            continue;
 296        }
 297        blk_exp_request_shutdown(exp);
 298    }
 299
 300    AIO_WAIT_WHILE(NULL, blk_exp_has_type(type));
 301}
 302
 303void blk_exp_close_all(void)
 304{
 305    blk_exp_close_all_type(BLOCK_EXPORT_TYPE__MAX);
 306}
 307
 308void qmp_block_export_add(BlockExportOptions *export, Error **errp)
 309{
 310    blk_exp_add(export, errp);
 311}
 312
 313void qmp_block_export_del(const char *id,
 314                          bool has_mode, BlockExportRemoveMode mode,
 315                          Error **errp)
 316{
 317    ERRP_GUARD();
 318    BlockExport *exp;
 319
 320    exp = blk_exp_find(id);
 321    if (exp == NULL) {
 322        error_setg(errp, "Export '%s' is not found", id);
 323        return;
 324    }
 325    if (!exp->user_owned) {
 326        error_setg(errp, "Export '%s' is already shutting down", id);
 327        return;
 328    }
 329
 330    if (!has_mode) {
 331        mode = BLOCK_EXPORT_REMOVE_MODE_SAFE;
 332    }
 333    if (mode == BLOCK_EXPORT_REMOVE_MODE_SAFE && exp->refcount > 1) {
 334        error_setg(errp, "export '%s' still in use", exp->id);
 335        error_append_hint(errp, "Use mode='hard' to force client "
 336                          "disconnect\n");
 337        return;
 338    }
 339
 340    blk_exp_request_shutdown(exp);
 341}
 342
 343BlockExportInfoList *qmp_query_block_exports(Error **errp)
 344{
 345    BlockExportInfoList *head = NULL, **tail = &head;
 346    BlockExport *exp;
 347
 348    QLIST_FOREACH(exp, &block_exports, next) {
 349        BlockExportInfo *info = g_new(BlockExportInfo, 1);
 350        *info = (BlockExportInfo) {
 351            .id             = g_strdup(exp->id),
 352            .type           = exp->drv->type,
 353            .node_name      = g_strdup(bdrv_get_node_name(blk_bs(exp->blk))),
 354            .shutting_down  = !exp->user_owned,
 355        };
 356
 357        QAPI_LIST_APPEND(tail, info);
 358    }
 359
 360    return head;
 361}
 362