mirror of https://github.com/xemu-project/xemu.git
block: Add error parameter to blk_insert_bs()
Now that blk_insert_bs() requests the BlockBackend permissions for the node it attaches to, it can fail. Instead of aborting, pass the errors to the callers. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Max Reitz <mreitz@redhat.com> Acked-by: Fam Zheng <famz@redhat.com>
This commit is contained in:
parent
6d0eb64d5c
commit
d7086422b1
5
block.c
5
block.c
|
@ -2194,8 +2194,11 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||||
}
|
}
|
||||||
if (file_bs != NULL) {
|
if (file_bs != NULL) {
|
||||||
file = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
|
file = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
|
||||||
blk_insert_bs(file, file_bs);
|
blk_insert_bs(file, file_bs, &local_err);
|
||||||
bdrv_unref(file_bs);
|
bdrv_unref(file_bs);
|
||||||
|
if (local_err) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
qdict_put(options, "file",
|
qdict_put(options, "file",
|
||||||
qstring_from_str(bdrv_get_node_name(file_bs)));
|
qstring_from_str(bdrv_get_node_name(file_bs)));
|
||||||
|
|
|
@ -626,7 +626,10 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
|
||||||
|
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
job->target = blk_new(0, BLK_PERM_ALL);
|
job->target = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(job->target, target);
|
ret = blk_insert_bs(job->target, target, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
job->on_source_error = on_source_error;
|
job->on_source_error = on_source_error;
|
||||||
job->on_target_error = on_target_error;
|
job->on_target_error = on_target_error;
|
||||||
|
|
|
@ -508,19 +508,22 @@ void blk_remove_bs(BlockBackend *blk)
|
||||||
/*
|
/*
|
||||||
* Associates a new BlockDriverState with @blk.
|
* Associates a new BlockDriverState with @blk.
|
||||||
*/
|
*/
|
||||||
void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
|
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
|
||||||
{
|
{
|
||||||
bdrv_ref(bs);
|
|
||||||
/* FIXME Error handling */
|
|
||||||
blk->root = bdrv_root_attach_child(bs, "root", &child_root,
|
blk->root = bdrv_root_attach_child(bs, "root", &child_root,
|
||||||
blk->perm, blk->shared_perm, blk,
|
blk->perm, blk->shared_perm, blk, errp);
|
||||||
&error_abort);
|
if (blk->root == NULL) {
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
bdrv_ref(bs);
|
||||||
|
|
||||||
notifier_list_notify(&blk->insert_bs_notifiers, blk);
|
notifier_list_notify(&blk->insert_bs_notifiers, blk);
|
||||||
if (blk->public.throttle_state) {
|
if (blk->public.throttle_state) {
|
||||||
throttle_timers_attach_aio_context(
|
throttle_timers_attach_aio_context(
|
||||||
&blk->public.throttle_timers, bdrv_get_aio_context(bs));
|
&blk->public.throttle_timers, bdrv_get_aio_context(bs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -220,6 +220,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||||
BlockDriverState *iter;
|
BlockDriverState *iter;
|
||||||
BlockDriverState *overlay_bs;
|
BlockDriverState *overlay_bs;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
assert(top != bs);
|
assert(top != bs);
|
||||||
if (top == base) {
|
if (top == base) {
|
||||||
|
@ -256,8 +257,7 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||||
bdrv_reopen_multiple(bdrv_get_aio_context(bs), reopen_queue, &local_err);
|
bdrv_reopen_multiple(bdrv_get_aio_context(bs), reopen_queue, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
block_job_unref(&s->common);
|
goto fail;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,11 +277,17 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||||
|
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
s->base = blk_new(0, BLK_PERM_ALL);
|
s->base = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(s->base, base);
|
ret = blk_insert_bs(s->base, base, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
s->top = blk_new(0, BLK_PERM_ALL);
|
s->top = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(s->top, top);
|
ret = blk_insert_bs(s->top, top, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
s->active = bs;
|
s->active = bs;
|
||||||
|
|
||||||
|
@ -294,6 +300,16 @@ void commit_start(const char *job_id, BlockDriverState *bs,
|
||||||
|
|
||||||
trace_commit_start(bs, base, top, s);
|
trace_commit_start(bs, base, top, s);
|
||||||
block_job_start(&s->common);
|
block_job_start(&s->common);
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (s->base) {
|
||||||
|
blk_unref(s->base);
|
||||||
|
}
|
||||||
|
if (s->top) {
|
||||||
|
blk_unref(s->top);
|
||||||
|
}
|
||||||
|
block_job_unref(&s->common);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -332,11 +348,17 @@ int bdrv_commit(BlockDriverState *bs)
|
||||||
|
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
src = blk_new(0, BLK_PERM_ALL);
|
src = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(src, bs);
|
|
||||||
|
|
||||||
/* FIXME Use real permissions */
|
|
||||||
backing = blk_new(0, BLK_PERM_ALL);
|
backing = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(backing, bs->backing->bs);
|
|
||||||
|
ret = blk_insert_bs(src, bs, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto ro_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = blk_insert_bs(backing, bs->backing->bs, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto ro_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
length = blk_getlength(src);
|
length = blk_getlength(src);
|
||||||
if (length < 0) {
|
if (length < 0) {
|
||||||
|
|
|
@ -525,9 +525,12 @@ static void mirror_exit(BlockJob *job, void *opaque)
|
||||||
bdrv_replace_in_backing_chain(to_replace, target_bs);
|
bdrv_replace_in_backing_chain(to_replace, target_bs);
|
||||||
bdrv_drained_end(target_bs);
|
bdrv_drained_end(target_bs);
|
||||||
|
|
||||||
/* We just changed the BDS the job BB refers to */
|
/* We just changed the BDS the job BB refers to, so switch the BB back
|
||||||
|
* so the cleanup does the right thing. We don't need any permissions
|
||||||
|
* any more now. */
|
||||||
blk_remove_bs(job->blk);
|
blk_remove_bs(job->blk);
|
||||||
blk_insert_bs(job->blk, src);
|
blk_set_perm(job->blk, 0, BLK_PERM_ALL, &error_abort);
|
||||||
|
blk_insert_bs(job->blk, src, &error_abort);
|
||||||
}
|
}
|
||||||
if (s->to_replace) {
|
if (s->to_replace) {
|
||||||
bdrv_op_unblock_all(s->to_replace, s->replace_blocker);
|
bdrv_op_unblock_all(s->to_replace, s->replace_blocker);
|
||||||
|
@ -995,6 +998,7 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
|
||||||
bool auto_complete)
|
bool auto_complete)
|
||||||
{
|
{
|
||||||
MirrorBlockJob *s;
|
MirrorBlockJob *s;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (granularity == 0) {
|
if (granularity == 0) {
|
||||||
granularity = bdrv_get_default_bitmap_granularity(target);
|
granularity = bdrv_get_default_bitmap_granularity(target);
|
||||||
|
@ -1019,7 +1023,12 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
|
||||||
|
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
s->target = blk_new(0, BLK_PERM_ALL);
|
s->target = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(s->target, target);
|
ret = blk_insert_bs(s->target, target, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
blk_unref(s->target);
|
||||||
|
block_job_unref(&s->common);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
s->replaces = g_strdup(replaces);
|
s->replaces = g_strdup(replaces);
|
||||||
s->on_source_error = on_source_error;
|
s->on_source_error = on_source_error;
|
||||||
|
|
|
@ -3113,6 +3113,7 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||||
uint64_t cluster_size = s->cluster_size;
|
uint64_t cluster_size = s->cluster_size;
|
||||||
bool encrypt;
|
bool encrypt;
|
||||||
int refcount_bits = s->refcount_bits;
|
int refcount_bits = s->refcount_bits;
|
||||||
|
Error *local_err = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
QemuOptDesc *desc = opts->list->desc;
|
QemuOptDesc *desc = opts->list->desc;
|
||||||
Qcow2AmendHelperCBInfo helper_cb_info;
|
Qcow2AmendHelperCBInfo helper_cb_info;
|
||||||
|
@ -3263,10 +3264,15 @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
|
||||||
|
|
||||||
if (new_size) {
|
if (new_size) {
|
||||||
BlockBackend *blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL);
|
BlockBackend *blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL);
|
||||||
blk_insert_bs(blk, bs);
|
ret = blk_insert_bs(blk, bs, &local_err);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report_err(local_err);
|
||||||
|
blk_unref(blk);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ret = blk_truncate(blk, new_size);
|
ret = blk_truncate(blk, new_size);
|
||||||
blk_unref(blk);
|
blk_unref(blk);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
11
blockdev.c
11
blockdev.c
|
@ -2436,6 +2436,7 @@ static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
|
||||||
BlockDriverState *bs, Error **errp)
|
BlockDriverState *bs, Error **errp)
|
||||||
{
|
{
|
||||||
bool has_device;
|
bool has_device;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* For BBs without a device, we can exchange the BDS tree at will */
|
/* For BBs without a device, we can exchange the BDS tree at will */
|
||||||
has_device = blk_get_attached_dev(blk);
|
has_device = blk_get_attached_dev(blk);
|
||||||
|
@ -2455,7 +2456,10 @@ static void qmp_blockdev_insert_anon_medium(BlockBackend *blk,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk_insert_bs(blk, bs);
|
ret = blk_insert_bs(blk, bs, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!blk_dev_has_tray(blk)) {
|
if (!blk_dev_has_tray(blk)) {
|
||||||
/* For tray-less devices, blockdev-close-tray is a no-op (or may not be
|
/* For tray-less devices, blockdev-close-tray is a no-op (or may not be
|
||||||
|
@ -2891,7 +2895,10 @@ void qmp_block_resize(bool has_device, const char *device,
|
||||||
}
|
}
|
||||||
|
|
||||||
blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL);
|
blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL);
|
||||||
blk_insert_bs(blk, bs);
|
ret = blk_insert_bs(blk, bs, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* complete all in-flight operations before resizing the device */
|
/* complete all in-flight operations before resizing the device */
|
||||||
bdrv_drain_all();
|
bdrv_drain_all();
|
||||||
|
|
|
@ -128,6 +128,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
BlockJob *job;
|
BlockJob *job;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (bs->job) {
|
if (bs->job) {
|
||||||
error_setg(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
|
error_setg(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
|
||||||
|
@ -161,7 +162,11 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
|
||||||
|
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
blk = blk_new(0, BLK_PERM_ALL);
|
blk = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(blk, bs);
|
ret = blk_insert_bs(blk, bs, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
blk_unref(blk);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
job = g_malloc0(driver->instance_size);
|
job = g_malloc0(driver->instance_size);
|
||||||
error_setg(&job->blocker, "block device is in use by block job: %s",
|
error_setg(&job->blocker, "block device is in use by block job: %s",
|
||||||
|
|
6
hmp.c
6
hmp.c
|
@ -2045,6 +2045,7 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
|
||||||
const char* device = qdict_get_str(qdict, "device");
|
const char* device = qdict_get_str(qdict, "device");
|
||||||
const char* command = qdict_get_str(qdict, "command");
|
const char* command = qdict_get_str(qdict, "command");
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
blk = blk_by_name(device);
|
blk = blk_by_name(device);
|
||||||
if (!blk) {
|
if (!blk) {
|
||||||
|
@ -2052,7 +2053,10 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
|
||||||
if (bs) {
|
if (bs) {
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
blk = local_blk = blk_new(0, BLK_PERM_ALL);
|
blk = local_blk = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(blk, bs);
|
ret = blk_insert_bs(blk, bs, &err);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr,
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
bool blk_created = false;
|
bool blk_created = false;
|
||||||
|
int ret;
|
||||||
|
|
||||||
blk = blk_by_name(str);
|
blk = blk_by_name(str);
|
||||||
if (!blk) {
|
if (!blk) {
|
||||||
|
@ -80,8 +81,12 @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr,
|
||||||
if (bs) {
|
if (bs) {
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
blk = blk_new(0, BLK_PERM_ALL);
|
blk = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(blk, bs);
|
|
||||||
blk_created = true;
|
blk_created = true;
|
||||||
|
|
||||||
|
ret = blk_insert_bs(blk, bs, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!blk) {
|
if (!blk) {
|
||||||
|
|
|
@ -102,7 +102,7 @@ BlockBackend *blk_by_public(BlockBackendPublic *public);
|
||||||
|
|
||||||
BlockDriverState *blk_bs(BlockBackend *blk);
|
BlockDriverState *blk_bs(BlockBackend *blk);
|
||||||
void blk_remove_bs(BlockBackend *blk);
|
void blk_remove_bs(BlockBackend *blk);
|
||||||
void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs);
|
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp);
|
||||||
bool bdrv_has_blk(BlockDriverState *bs);
|
bool bdrv_has_blk(BlockDriverState *bs);
|
||||||
bool bdrv_is_root_node(BlockDriverState *bs);
|
bool bdrv_is_root_node(BlockDriverState *bs);
|
||||||
int blk_set_perm(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
|
int blk_set_perm(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
|
||||||
|
|
|
@ -446,7 +446,7 @@ static void init_blk_migration(QEMUFile *f)
|
||||||
BlockDriverState *bs = bmds_bs[i].bs;
|
BlockDriverState *bs = bmds_bs[i].bs;
|
||||||
|
|
||||||
if (bmds) {
|
if (bmds) {
|
||||||
blk_insert_bs(bmds->blk, bs);
|
blk_insert_bs(bmds->blk, bs, &error_abort);
|
||||||
|
|
||||||
alloc_aio_bitmap(bmds);
|
alloc_aio_bitmap(bmds);
|
||||||
error_setg(&bmds->blocker, "block device is in use by migration");
|
error_setg(&bmds->blocker, "block device is in use by migration");
|
||||||
|
|
|
@ -891,10 +891,14 @@ NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size,
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
NBDExport *exp = g_malloc0(sizeof(NBDExport));
|
NBDExport *exp = g_malloc0(sizeof(NBDExport));
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* FIXME Use real permissions */
|
/* FIXME Use real permissions */
|
||||||
blk = blk_new(0, BLK_PERM_ALL);
|
blk = blk_new(0, BLK_PERM_ALL);
|
||||||
blk_insert_bs(blk, bs);
|
ret = blk_insert_bs(blk, bs, errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
blk_set_enable_write_cache(blk, !writethrough);
|
blk_set_enable_write_cache(blk, !writethrough);
|
||||||
|
|
||||||
exp->refcount = 1;
|
exp->refcount = 1;
|
||||||
|
|
|
@ -60,7 +60,7 @@ static BlockBackend *create_blk(const char *name)
|
||||||
bs = bdrv_open("null-co://", NULL, NULL, 0, &error_abort);
|
bs = bdrv_open("null-co://", NULL, NULL, 0, &error_abort);
|
||||||
g_assert_nonnull(bs);
|
g_assert_nonnull(bs);
|
||||||
|
|
||||||
blk_insert_bs(blk, bs);
|
blk_insert_bs(blk, bs, &error_abort);
|
||||||
bdrv_unref(bs);
|
bdrv_unref(bs);
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
|
|
Loading…
Reference in New Issue