mirror of https://github.com/xemu-project/xemu.git
block/export: Allocate BlockExport in blk_exp_add()
Instead of letting the driver allocate and return the BlockExport object, allocate it already in blk_exp_add() and pass it. This allows us to initialise the generic part before calling into the driver so that the driver can just use these values instead of having to parse the options a second time. For symmetry, move freeing the BlockExport to blk_exp_unref(). Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Message-Id: <20200924152717.287415-17-kwolf@redhat.com> Acked-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
b6076afcab
commit
a6ff798966
|
@ -39,6 +39,8 @@ static const BlockExportDriver *blk_exp_find_driver(BlockExportType type)
|
||||||
BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
|
BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
|
||||||
{
|
{
|
||||||
const BlockExportDriver *drv;
|
const BlockExportDriver *drv;
|
||||||
|
BlockExport *exp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
drv = blk_exp_find_driver(export->type);
|
drv = blk_exp_find_driver(export->type);
|
||||||
if (!drv) {
|
if (!drv) {
|
||||||
|
@ -46,7 +48,20 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return drv->create(export, errp);
|
assert(drv->instance_size >= sizeof(BlockExport));
|
||||||
|
exp = g_malloc0(drv->instance_size);
|
||||||
|
*exp = (BlockExport) {
|
||||||
|
.drv = drv,
|
||||||
|
.refcount = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = drv->create(exp, export, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
g_free(exp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callers must hold exp->ctx lock */
|
/* Callers must hold exp->ctx lock */
|
||||||
|
@ -62,6 +77,7 @@ void blk_exp_unref(BlockExport *exp)
|
||||||
assert(exp->refcount > 0);
|
assert(exp->refcount > 0);
|
||||||
if (--exp->refcount == 0) {
|
if (--exp->refcount == 0) {
|
||||||
exp->drv->delete(exp);
|
exp->drv->delete(exp);
|
||||||
|
g_free(exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,18 +173,19 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr,
|
||||||
qapi_free_SocketAddress(addr_flat);
|
qapi_free_SocketAddress(addr_flat);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockExport *nbd_export_create(BlockExportOptions *exp_args, Error **errp)
|
int nbd_export_create(BlockExport *exp, BlockExportOptions *exp_args,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
BlockExportOptionsNbd *arg = &exp_args->u.nbd;
|
BlockExportOptionsNbd *arg = &exp_args->u.nbd;
|
||||||
BlockDriverState *bs = NULL;
|
BlockDriverState *bs = NULL;
|
||||||
NBDExport *exp = NULL;
|
|
||||||
AioContext *aio_context;
|
AioContext *aio_context;
|
||||||
|
int ret;
|
||||||
|
|
||||||
assert(exp_args->type == BLOCK_EXPORT_TYPE_NBD);
|
assert(exp_args->type == BLOCK_EXPORT_TYPE_NBD);
|
||||||
|
|
||||||
if (!nbd_server && !is_qemu_nbd) {
|
if (!nbd_server && !is_qemu_nbd) {
|
||||||
error_setg(errp, "NBD server not running");
|
error_setg(errp, "NBD server not running");
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!arg->has_name) {
|
if (!arg->has_name) {
|
||||||
|
@ -193,22 +194,22 @@ BlockExport *nbd_export_create(BlockExportOptions *exp_args, Error **errp)
|
||||||
|
|
||||||
if (strlen(arg->name) > NBD_MAX_STRING_SIZE) {
|
if (strlen(arg->name) > NBD_MAX_STRING_SIZE) {
|
||||||
error_setg(errp, "export name '%s' too long", arg->name);
|
error_setg(errp, "export name '%s' too long", arg->name);
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg->description && strlen(arg->description) > NBD_MAX_STRING_SIZE) {
|
if (arg->description && strlen(arg->description) > NBD_MAX_STRING_SIZE) {
|
||||||
error_setg(errp, "description '%s' too long", arg->description);
|
error_setg(errp, "description '%s' too long", arg->description);
|
||||||
return NULL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbd_export_find(arg->name)) {
|
if (nbd_export_find(arg->name)) {
|
||||||
error_setg(errp, "NBD server already has export named '%s'", arg->name);
|
error_setg(errp, "NBD server already has export named '%s'", arg->name);
|
||||||
return NULL;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = bdrv_lookup_bs(NULL, exp_args->node_name, errp);
|
bs = bdrv_lookup_bs(NULL, exp_args->node_name, errp);
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
return NULL;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_context = bdrv_get_aio_context(bs);
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
|
@ -218,6 +219,7 @@ BlockExport *nbd_export_create(BlockExportOptions *exp_args, Error **errp)
|
||||||
arg->writable = false;
|
arg->writable = false;
|
||||||
}
|
}
|
||||||
if (bdrv_is_read_only(bs) && arg->writable) {
|
if (bdrv_is_read_only(bs) && arg->writable) {
|
||||||
|
ret = -EINVAL;
|
||||||
error_setg(errp, "Cannot export read-only node as writable");
|
error_setg(errp, "Cannot export read-only node as writable");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -226,22 +228,22 @@ BlockExport *nbd_export_create(BlockExportOptions *exp_args, Error **errp)
|
||||||
exp_args->writethrough = false;
|
exp_args->writethrough = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
exp = nbd_export_new(bs, arg->name, arg->description, arg->bitmap,
|
ret = nbd_export_new(exp, bs, arg->name, arg->description, arg->bitmap,
|
||||||
!arg->writable, !arg->writable,
|
!arg->writable, !arg->writable,
|
||||||
exp_args->writethrough, errp);
|
exp_args->writethrough, errp);
|
||||||
if (!exp) {
|
if (ret < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The list of named exports has a strong reference to this export now and
|
/* The list of named exports has a strong reference to this export now and
|
||||||
* our only way of accessing it is through nbd_export_find(), so we can drop
|
* our only way of accessing it is through nbd_export_find(), so we can drop
|
||||||
* the strong reference that is @exp. */
|
* the strong reference that is @exp. */
|
||||||
blk_exp_unref((BlockExport*) exp);
|
blk_exp_unref(exp);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
/* TODO Remove the cast: nbd_export_new() will return a BlockExport. */
|
return ret;
|
||||||
return (BlockExport*) exp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_nbd_server_add(NbdServerAddOptions *arg, Error **errp)
|
void qmp_nbd_server_add(NbdServerAddOptions *arg, Error **errp)
|
||||||
|
|
|
@ -22,8 +22,14 @@ typedef struct BlockExportDriver {
|
||||||
/* The export type that this driver services */
|
/* The export type that this driver services */
|
||||||
BlockExportType type;
|
BlockExportType type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The size of the driver-specific state that contains BlockExport as its
|
||||||
|
* first field.
|
||||||
|
*/
|
||||||
|
size_t instance_size;
|
||||||
|
|
||||||
/* Creates and starts a new block export */
|
/* Creates and starts a new block export */
|
||||||
BlockExport *(*create)(BlockExportOptions *, Error **);
|
int (*create)(BlockExport *, BlockExportOptions *, Error **);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Frees a removed block export. This function is only called after all
|
* Frees a removed block export. This function is only called after all
|
||||||
|
|
|
@ -330,11 +330,12 @@ int nbd_errno_to_system_errno(int err);
|
||||||
typedef struct NBDExport NBDExport;
|
typedef struct NBDExport NBDExport;
|
||||||
typedef struct NBDClient NBDClient;
|
typedef struct NBDClient NBDClient;
|
||||||
|
|
||||||
BlockExport *nbd_export_create(BlockExportOptions *exp_args, Error **errp);
|
int nbd_export_create(BlockExport *exp, BlockExportOptions *exp_args,
|
||||||
NBDExport *nbd_export_new(BlockDriverState *bs,
|
Error **errp);
|
||||||
const char *name, const char *desc,
|
int nbd_export_new(BlockExport *blk_exp, BlockDriverState *bs,
|
||||||
const char *bitmap, bool readonly, bool shared,
|
const char *name, const char *desc,
|
||||||
bool writethrough, Error **errp);
|
const char *bitmap, bool readonly, bool shared,
|
||||||
|
bool writethrough, Error **errp);
|
||||||
void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk);
|
void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk);
|
||||||
void nbd_export_close(NBDExport *exp);
|
void nbd_export_close(NBDExport *exp);
|
||||||
void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp);
|
void nbd_export_remove(NBDExport *exp, NbdServerRemoveMode mode, Error **errp);
|
||||||
|
|
30
nbd/server.c
30
nbd/server.c
|
@ -1514,14 +1514,14 @@ void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk)
|
||||||
blk_add_remove_bs_notifier(blk, &nbd_exp->eject_notifier);
|
blk_add_remove_bs_notifier(blk, &nbd_exp->eject_notifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
NBDExport *nbd_export_new(BlockDriverState *bs,
|
int nbd_export_new(BlockExport *blk_exp, BlockDriverState *bs,
|
||||||
const char *name, const char *desc,
|
const char *name, const char *desc,
|
||||||
const char *bitmap, bool readonly, bool shared,
|
const char *bitmap, bool readonly, bool shared,
|
||||||
bool writethrough, Error **errp)
|
bool writethrough, Error **errp)
|
||||||
{
|
{
|
||||||
|
NBDExport *exp = container_of(blk_exp, NBDExport, common);
|
||||||
AioContext *ctx;
|
AioContext *ctx;
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
NBDExport *exp;
|
|
||||||
int64_t size;
|
int64_t size;
|
||||||
uint64_t perm;
|
uint64_t perm;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1530,17 +1530,11 @@ NBDExport *nbd_export_new(BlockDriverState *bs,
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
error_setg_errno(errp, -size,
|
error_setg_errno(errp, -size,
|
||||||
"Failed to determine the NBD export's length");
|
"Failed to determine the NBD export's length");
|
||||||
return NULL;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = bdrv_get_aio_context(bs);
|
ctx = bdrv_get_aio_context(bs);
|
||||||
|
blk_exp->ctx = ctx;
|
||||||
exp = g_new0(NBDExport, 1);
|
|
||||||
exp->common = (BlockExport) {
|
|
||||||
.drv = &blk_exp_nbd,
|
|
||||||
.refcount = 1,
|
|
||||||
.ctx = ctx,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NBD exports are used for non-shared storage migration. Make sure
|
* NBD exports are used for non-shared storage migration. Make sure
|
||||||
|
@ -1599,16 +1593,19 @@ NBDExport *nbd_export_new(BlockDriverState *bs,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bm == NULL) {
|
if (bm == NULL) {
|
||||||
|
ret = -ENOENT;
|
||||||
error_setg(errp, "Bitmap '%s' is not found", bitmap);
|
error_setg(errp, "Bitmap '%s' is not found", bitmap);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdrv_dirty_bitmap_check(bm, BDRV_BITMAP_ALLOW_RO, errp)) {
|
if (bdrv_dirty_bitmap_check(bm, BDRV_BITMAP_ALLOW_RO, errp)) {
|
||||||
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readonly && bdrv_is_writable(bs) &&
|
if (readonly && bdrv_is_writable(bs) &&
|
||||||
bdrv_dirty_bitmap_enabled(bm)) {
|
bdrv_dirty_bitmap_enabled(bm)) {
|
||||||
|
ret = -EINVAL;
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Enabled bitmap '%s' incompatible with readonly export",
|
"Enabled bitmap '%s' incompatible with readonly export",
|
||||||
bitmap);
|
bitmap);
|
||||||
|
@ -1628,14 +1625,13 @@ NBDExport *nbd_export_new(BlockDriverState *bs,
|
||||||
blk_exp_ref(&exp->common);
|
blk_exp_ref(&exp->common);
|
||||||
QTAILQ_INSERT_TAIL(&exports, exp, next);
|
QTAILQ_INSERT_TAIL(&exports, exp, next);
|
||||||
|
|
||||||
return exp;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
blk_unref(blk);
|
blk_unref(blk);
|
||||||
g_free(exp->name);
|
g_free(exp->name);
|
||||||
g_free(exp->description);
|
g_free(exp->description);
|
||||||
g_free(exp);
|
return ret;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NBDExport *nbd_export_find(const char *name)
|
NBDExport *nbd_export_find(const char *name)
|
||||||
|
@ -1722,12 +1718,12 @@ static void nbd_export_delete(BlockExport *blk_exp)
|
||||||
}
|
}
|
||||||
|
|
||||||
QTAILQ_REMOVE(&closed_exports, exp, next);
|
QTAILQ_REMOVE(&closed_exports, exp, next);
|
||||||
g_free(exp);
|
|
||||||
aio_wait_kick();
|
aio_wait_kick();
|
||||||
}
|
}
|
||||||
|
|
||||||
const BlockExportDriver blk_exp_nbd = {
|
const BlockExportDriver blk_exp_nbd = {
|
||||||
.type = BLOCK_EXPORT_TYPE_NBD,
|
.type = BLOCK_EXPORT_TYPE_NBD,
|
||||||
|
.instance_size = sizeof(NBDExport),
|
||||||
.create = nbd_export_create,
|
.create = nbd_export_create,
|
||||||
.delete = nbd_export_delete,
|
.delete = nbd_export_delete,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue