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:
Kevin Wolf 2015-06-15 13:24:19 +02:00
parent df58179267
commit b4b059f628
3 changed files with 60 additions and 21 deletions

71
block.c
View File

@ -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)

View File

@ -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);

View File

@ -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