From b4b059f628173dd1d722ee8a9c592a80aec1fc2f Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 15 Jun 2015 13:24:19 +0200 Subject: 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 Reviewed-by: Max Reitz --- block.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 19 deletions(-) (limited to 'block.c') diff --git a/block.c b/block.c index 0398bffc03..029feeb7f9 100644 --- a/block.c +++ b/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) -- cgit v1.2.3