mirror of
https://github.com/qemu/qemu.git
synced 2025-01-22 21:44:07 +08:00
block: Introduce bdrv_open_child()
It is the same as bdrv_open_image(), except that it doesn't only return success or failure, but the newly created BdrvChild object for the new child node. As the BdrvChild object already contains a BlockDriverState pointer (and this is supposed to become the only pointer so that bdrv_append() and friends can just change a single pointer in BdrvChild), the pbs parameter is removed for bdrv_open_child(). Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
df58179267
commit
b4b059f628
71
block.c
71
block.c
@ -1102,9 +1102,9 @@ static int bdrv_fill_options(QDict **options, const char **pfilename,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bdrv_attach_child(BlockDriverState *parent_bs,
|
||||
BlockDriverState *child_bs,
|
||||
const BdrvChildRole *child_role)
|
||||
static BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
||||
BlockDriverState *child_bs,
|
||||
const BdrvChildRole *child_role)
|
||||
{
|
||||
BdrvChild *child = g_new(BdrvChild, 1);
|
||||
*child = (BdrvChild) {
|
||||
@ -1113,6 +1113,8 @@ static void bdrv_attach_child(BlockDriverState *parent_bs,
|
||||
};
|
||||
|
||||
QLIST_INSERT_HEAD(&parent_bs->children, child, next);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
|
||||
@ -1229,7 +1231,7 @@ free_exit:
|
||||
* device's options.
|
||||
*
|
||||
* If allow_none is true, no image will be opened if filename is false and no
|
||||
* BlockdevRef is given. *pbs will remain unchanged and 0 will be returned.
|
||||
* BlockdevRef is given. NULL will be returned, but errp remains unset.
|
||||
*
|
||||
* bdrev_key specifies the key for the image's BlockdevRef in the options QDict.
|
||||
* That QDict has to be flattened; therefore, if the BlockdevRef is a QDict
|
||||
@ -1237,21 +1239,20 @@ free_exit:
|
||||
* BlockdevRef.
|
||||
*
|
||||
* The BlockdevRef will be removed from the options QDict.
|
||||
*
|
||||
* To conform with the behavior of bdrv_open(), *pbs has to be NULL.
|
||||
*/
|
||||
int bdrv_open_image(BlockDriverState **pbs, const char *filename,
|
||||
QDict *options, const char *bdref_key,
|
||||
BlockDriverState* parent, const BdrvChildRole *child_role,
|
||||
bool allow_none, Error **errp)
|
||||
BdrvChild *bdrv_open_child(const char *filename,
|
||||
QDict *options, const char *bdref_key,
|
||||
BlockDriverState* parent,
|
||||
const BdrvChildRole *child_role,
|
||||
bool allow_none, Error **errp)
|
||||
{
|
||||
BdrvChild *c = NULL;
|
||||
BlockDriverState *bs;
|
||||
QDict *image_options;
|
||||
int ret;
|
||||
char *bdref_key_dot;
|
||||
const char *reference;
|
||||
|
||||
assert(pbs);
|
||||
assert(*pbs == NULL);
|
||||
assert(child_role != NULL);
|
||||
|
||||
bdref_key_dot = g_strdup_printf("%s.", bdref_key);
|
||||
@ -1260,28 +1261,60 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
|
||||
|
||||
reference = qdict_get_try_str(options, bdref_key);
|
||||
if (!filename && !reference && !qdict_size(image_options)) {
|
||||
if (allow_none) {
|
||||
ret = 0;
|
||||
} else {
|
||||
if (!allow_none) {
|
||||
error_setg(errp, "A block device must be specified for \"%s\"",
|
||||
bdref_key);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
QDECREF(image_options);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = bdrv_open_inherit(pbs, filename, reference, image_options, 0,
|
||||
bs = NULL;
|
||||
ret = bdrv_open_inherit(&bs, filename, reference, image_options, 0,
|
||||
parent, child_role, NULL, errp);
|
||||
if (ret < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
bdrv_attach_child(parent, *pbs, child_role);
|
||||
c = bdrv_attach_child(parent, bs, child_role);
|
||||
|
||||
done:
|
||||
qdict_del(options, bdref_key);
|
||||
return ret;
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a version of bdrv_open_child() that returns 0/-EINVAL instead of
|
||||
* a BdrvChild object.
|
||||
*
|
||||
* If allow_none is true, no image will be opened if filename is false and no
|
||||
* BlockdevRef is given. *pbs will remain unchanged and 0 will be returned.
|
||||
*
|
||||
* To conform with the behavior of bdrv_open(), *pbs has to be NULL.
|
||||
*/
|
||||
int bdrv_open_image(BlockDriverState **pbs, const char *filename,
|
||||
QDict *options, const char *bdref_key,
|
||||
BlockDriverState* parent, const BdrvChildRole *child_role,
|
||||
bool allow_none, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BdrvChild *c;
|
||||
|
||||
assert(pbs);
|
||||
assert(*pbs == NULL);
|
||||
|
||||
c = bdrv_open_child(filename, options, bdref_key, parent, child_role,
|
||||
allow_none, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (c != NULL) {
|
||||
*pbs = c->bs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
|
||||
|
@ -12,6 +12,7 @@
|
||||
/* block.c */
|
||||
typedef struct BlockDriver BlockDriver;
|
||||
typedef struct BlockJob BlockJob;
|
||||
typedef struct BdrvChild BdrvChild;
|
||||
typedef struct BdrvChildRole BdrvChildRole;
|
||||
|
||||
typedef struct BlockDriverInfo {
|
||||
@ -208,6 +209,11 @@ int bdrv_open_image(BlockDriverState **pbs, const char *filename,
|
||||
QDict *options, const char *bdref_key,
|
||||
BlockDriverState* parent, const BdrvChildRole *child_role,
|
||||
bool allow_none, Error **errp);
|
||||
BdrvChild *bdrv_open_child(const char *filename,
|
||||
QDict *options, const char *bdref_key,
|
||||
BlockDriverState* parent,
|
||||
const BdrvChildRole *child_role,
|
||||
bool allow_none, Error **errp);
|
||||
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd);
|
||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp);
|
||||
int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp);
|
||||
|
@ -335,11 +335,11 @@ struct BdrvChildRole {
|
||||
extern const BdrvChildRole child_file;
|
||||
extern const BdrvChildRole child_format;
|
||||
|
||||
typedef struct BdrvChild {
|
||||
struct BdrvChild {
|
||||
BlockDriverState *bs;
|
||||
const BdrvChildRole *role;
|
||||
QLIST_ENTRY(BdrvChild) next;
|
||||
} BdrvChild;
|
||||
};
|
||||
|
||||
/*
|
||||
* Note: the function bdrv_append() copies and swaps contents of
|
||||
|
Loading…
Reference in New Issue
Block a user