block: Add Error parameter to bdrv_set_backing_hd()
Not all callers of bdrv_set_backing_hd() know for sure that attaching
the backing file will be allowed by the permission system. Return the
error from the function rather than aborting.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Acked-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
diff --git a/block.c b/block.c
index 74ac7dc..6440b61 100644
--- a/block.c
+++ b/block.c
@@ -1883,7 +1883,8 @@
* Sets the backing file link of a BDS. A new reference is created; callers
* which don't need their own reference any more must call bdrv_unref().
*/
-void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
+void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
+ Error **errp)
{
if (backing_hd) {
bdrv_ref(backing_hd);
@@ -1897,9 +1898,12 @@
bs->backing = NULL;
goto out;
}
- /* FIXME Error handling */
+
bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
- &error_abort);
+ errp);
+ if (!bs->backing) {
+ bdrv_unref(backing_hd);
+ }
out:
bdrv_refresh_limits(bs, NULL);
@@ -1983,8 +1987,12 @@
/* Hook up the backing file link; drop our reference, bs owns the
* backing_hd reference now */
- bdrv_set_backing_hd(bs, backing_hd);
+ bdrv_set_backing_hd(bs, backing_hd, &local_err);
bdrv_unref(backing_hd);
+ if (local_err) {
+ ret = -EINVAL;
+ goto free_exit;
+ }
qdict_del(parent_options, bdref_key);
@@ -2818,7 +2826,7 @@
bs->drv->bdrv_close(bs);
bs->drv = NULL;
- bdrv_set_backing_hd(bs, NULL);
+ bdrv_set_backing_hd(bs, NULL, &error_abort);
if (bs->file != NULL) {
bdrv_unref_child(bs, bs->file);
@@ -2927,7 +2935,8 @@
bdrv_ref(bs_top);
change_parent_backing_link(bs_top, bs_new);
- bdrv_set_backing_hd(bs_new, bs_top);
+ /* FIXME Error handling */
+ bdrv_set_backing_hd(bs_new, bs_top, &error_abort);
bdrv_unref(bs_top);
/* bs_new is now referenced by its new parents, we don't need the
@@ -3075,6 +3084,7 @@
BlockDriverState *base, const char *backing_file_str)
{
BlockDriverState *new_top_bs = NULL;
+ Error *local_err = NULL;
int ret = -EIO;
if (!top->drv || !base->drv) {
@@ -3107,7 +3117,13 @@
if (ret) {
goto exit;
}
- bdrv_set_backing_hd(new_top_bs, base);
+
+ bdrv_set_backing_hd(new_top_bs, base, &local_err);
+ if (local_err) {
+ ret = -EPERM;
+ error_report_err(local_err);
+ goto exit;
+ }
ret = 0;
exit: