block/export: add iothread and fixed-iothread options

Make it possible to specify the iothread where the export will run. By
default the block node can be moved to other AioContexts later and the
export will follow. The fixed-iothread option forces strict behavior
that prevents changing AioContext while the export is active. See the
QAPI docs for details.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20200929125516.186715-5-stefanha@redhat.com
[Fix stray '#' character in block-export.json and add missing "(since:
5.2)" as suggested by Eric Blake.
--Stefan]
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2020-09-29 13:55:16 +01:00
parent cbc20bfb8f
commit f51d23c80a
4 changed files with 45 additions and 4 deletions

View File

@ -15,6 +15,7 @@
#include "block/block.h"
#include "sysemu/block-backend.h"
#include "sysemu/iothread.h"
#include "block/export.h"
#include "block/nbd.h"
#include "qapi/error.h"
@ -63,10 +64,11 @@ static const BlockExportDriver *blk_exp_find_driver(BlockExportType type)
BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
{
bool fixed_iothread = export->has_fixed_iothread && export->fixed_iothread;
const BlockExportDriver *drv;
BlockExport *exp = NULL;
BlockDriverState *bs;
BlockBackend *blk;
BlockBackend *blk = NULL;
AioContext *ctx;
uint64_t perm;
int ret;
@ -102,6 +104,28 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
ctx = bdrv_get_aio_context(bs);
aio_context_acquire(ctx);
if (export->has_iothread) {
IOThread *iothread;
AioContext *new_ctx;
iothread = iothread_by_id(export->iothread);
if (!iothread) {
error_setg(errp, "iothread \"%s\" not found", export->iothread);
goto fail;
}
new_ctx = iothread_get_aio_context(iothread);
ret = bdrv_try_set_aio_context(bs, new_ctx, errp);
if (ret == 0) {
aio_context_release(ctx);
aio_context_acquire(new_ctx);
ctx = new_ctx;
} else if (fixed_iothread) {
goto fail;
}
}
/*
* Block exports are used for non-shared storage migration. Make sure
* that BDRV_O_INACTIVE is cleared and the image is ready for write
@ -116,6 +140,11 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
}
blk = blk_new(ctx, perm, BLK_PERM_ALL);
if (!fixed_iothread) {
blk_set_allow_aio_context_change(blk, true);
}
ret = blk_insert_bs(blk, bs, errp);
if (ret < 0) {
goto fail;

View File

@ -323,13 +323,17 @@ static const VuDevIface vu_blk_iface = {
static void blk_aio_attached(AioContext *ctx, void *opaque)
{
VuBlkExport *vexp = opaque;
vexp->export.ctx = ctx;
vhost_user_server_attach_aio_context(&vexp->vu_server, ctx);
}
static void blk_aio_detach(void *opaque)
{
VuBlkExport *vexp = opaque;
vhost_user_server_detach_aio_context(&vexp->vu_server);
vexp->export.ctx = NULL;
}
static void
@ -384,7 +388,6 @@ static int vu_blk_exp_create(BlockExport *exp, BlockExportOptions *opts,
vu_blk_initialize_config(blk_bs(exp->blk), &vexp->blkcfg,
logical_block_size);
blk_set_allow_aio_context_change(exp->blk, true);
blk_add_aio_context_notifier(exp->blk, blk_aio_attached, blk_aio_detach,
vexp);

View File

@ -1517,8 +1517,6 @@ static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp_args,
return ret;
}
blk_set_allow_aio_context_change(blk, true);
QTAILQ_INIT(&exp->clients);
exp->name = g_strdup(arg->name);
exp->description = g_strdup(arg->description);

View File

@ -219,11 +219,22 @@
# export before completion is signalled. (since: 5.2;
# default: false)
#
# @iothread: The name of the iothread object where the export will run. The
# default is to use the thread currently associated with the
# block node. (since: 5.2)
#
# @fixed-iothread: True prevents the block node from being moved to another
# thread while the export is active. If true and @iothread is
# given, export creation fails if the block node cannot be
# moved to the iothread. The default is false. (since: 5.2)
#
# Since: 4.2
##
{ 'union': 'BlockExportOptions',
'base': { 'type': 'BlockExportType',
'id': 'str',
'*fixed-iothread': 'bool',
'*iothread': 'str',
'node-name': 'str',
'*writable': 'bool',
'*writethrough': 'bool' },