aboutsummaryrefslogtreecommitdiff
path: root/blockdev.c
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2016-01-29 16:36:12 +0100
committerMax Reitz <mreitz@redhat.com>2016-02-02 17:50:46 +0100
commit9c4218e957331e1ba0ba7565730b0b71c49b8d70 (patch)
tree941073a3588534db7b49e49d5ff210a62849020f /blockdev.c
parent2c1d04e002dc91a6f34e8e683ea6b84f61a0b9fd (diff)
blockdev: Keep track of monitor-owned BDS
As a side effect, we can now make x-blockdev-del's check whether a BDS is actually owned by the monitor explicit. Signed-off-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'blockdev.c')
-rw-r--r--blockdev.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/blockdev.c b/blockdev.c
index 09d4621cd2..35e1e5c58f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -50,6 +50,9 @@
#include "trace.h"
#include "sysemu/arch_init.h"
+static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
+ QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states);
+
static const char *const if_name[IF_COUNT] = {
[IF_NONE] = "none",
[IF_IDE] = "ide",
@@ -702,6 +705,19 @@ fail:
return NULL;
}
+void blockdev_close_all_bdrv_states(void)
+{
+ BlockDriverState *bs, *next_bs;
+
+ QTAILQ_FOREACH_SAFE(bs, &monitor_bdrv_states, monitor_list, next_bs) {
+ AioContext *ctx = bdrv_get_aio_context(bs);
+
+ aio_context_acquire(ctx);
+ bdrv_unref(bs);
+ aio_context_release(ctx);
+ }
+}
+
static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to,
Error **errp)
{
@@ -3875,12 +3891,15 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
if (!bs) {
goto fail;
}
+
+ QTAILQ_INSERT_TAIL(&monitor_bdrv_states, bs, monitor_list);
}
if (bs && bdrv_key_required(bs)) {
if (blk) {
blk_unref(blk);
} else {
+ QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
bdrv_unref(bs);
}
error_setg(errp, "blockdev-add doesn't support encrypted devices");
@@ -3940,7 +3959,13 @@ void qmp_x_blockdev_del(bool has_id, const char *id,
goto out;
}
- if (bs->refcnt > 1 || !QLIST_EMPTY(&bs->parents)) {
+ if (!blk && !bs->monitor_list.tqe_prev) {
+ error_setg(errp, "Node %s is not owned by the monitor",
+ bs->node_name);
+ goto out;
+ }
+
+ if (bs->refcnt > 1) {
error_setg(errp, "Block device %s is in use",
bdrv_get_device_or_node_name(bs));
goto out;
@@ -3950,6 +3975,7 @@ void qmp_x_blockdev_del(bool has_id, const char *id,
if (blk) {
blk_unref(blk);
} else {
+ QTAILQ_REMOVE(&monitor_bdrv_states, bs, monitor_list);
bdrv_unref(bs);
}