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