aboutsummaryrefslogtreecommitdiff
path: root/block.c
diff options
context:
space:
mode:
Diffstat (limited to 'block.c')
-rw-r--r--block.c71
1 files changed, 52 insertions, 19 deletions
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)