* [Qemu-devel] [PATCH 1/9] block: Add blk_name_taken()
2015-02-24 16:23 [Qemu-devel] [PATCH 0/9] blockdev: Further BlockBackend work Max Reitz
@ 2015-02-24 16:23 ` Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 2/9] block: Add blk_next_inserted() Max Reitz
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Max Reitz @ 2015-02-24 16:23 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: Kevin Wolf, Markus Armbruster, Stefan Hajnoczi, Max Reitz
There may be BlockBackends which are not returned by blk_by_name(), but
do exist and have a name. blk_name_taken() allows testing whether a
specific name is in use already, independent of whether the BlockBackend
with that name is accessible through blk_by_name().
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
block.c | 4 ++--
block/block-backend.c | 19 ++++++++++++++++++-
include/sysemu/block-backend.h | 1 +
3 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/block.c b/block.c
index a2637b6..1badb75 100644
--- a/block.c
+++ b/block.c
@@ -930,8 +930,8 @@ static void bdrv_assign_node_name(BlockDriverState *bs,
return;
}
- /* takes care of avoiding namespaces collisions */
- if (blk_by_name(node_name)) {
+ /* takes care of avoiding namespace collisions */
+ if (blk_name_taken(node_name)) {
error_setg(errp, "node-name=%s is conflicting with a device id",
node_name);
return;
diff --git a/block/block-backend.c b/block/block-backend.c
index 2e820fe..e2e70d2 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -85,7 +85,7 @@ BlockBackend *blk_new(const char *name, Error **errp)
error_setg(errp, "Invalid device name");
return NULL;
}
- if (blk_by_name(name)) {
+ if (blk_name_taken(name)) {
error_setg(errp, "Device with id '%s' already exists", name);
return NULL;
}
@@ -263,6 +263,23 @@ BlockBackend *blk_by_name(const char *name)
}
/*
+ * This function should be used to check whether a certain BlockBackend name is
+ * already taken; blk_by_name() will only search in the list of monitor-owned
+ * BlockBackends which is not necessarily complete.
+ */
+bool blk_name_taken(const char *name)
+{
+ BlockBackend *blk;
+
+ QTAILQ_FOREACH(blk, &blk_backends, link) {
+ if (!strcmp(name, blk->name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
* Return the BlockDriverState attached to @blk if any, else null.
*/
BlockDriverState *blk_bs(BlockBackend *blk)
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index ab765a7..b9eae9b 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -70,6 +70,7 @@ void blk_unref(BlockBackend *blk);
void blk_remove_all_bs(void);
const char *blk_name(BlockBackend *blk);
BlockBackend *blk_by_name(const char *name);
+bool blk_name_taken(const char *name);
BlockBackend *blk_next(BlockBackend *blk);
BlockDriverState *blk_bs(BlockBackend *blk);
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 2/9] block: Add blk_next_inserted()
2015-02-24 16:23 [Qemu-devel] [PATCH 0/9] blockdev: Further BlockBackend work Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 1/9] block: Add blk_name_taken() Max Reitz
@ 2015-02-24 16:23 ` Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 3/9] block: Add blk_commit_all() and blk_invalidate_cache_all() Max Reitz
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Max Reitz @ 2015-02-24 16:23 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: Kevin Wolf, Markus Armbruster, Stefan Hajnoczi, Max Reitz
This function skips to the next BlockBackend for which blk_is_inserted()
is true.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
block/block-backend.c | 15 +++++++++++++++
include/sysemu/block-backend.h | 1 +
2 files changed, 16 insertions(+)
diff --git a/block/block-backend.c b/block/block-backend.c
index e2e70d2..ab3affa 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -236,6 +236,21 @@ BlockBackend *blk_next(BlockBackend *blk)
}
/*
+ * Like blk_next(), but skips all non-inserted BlockBackends (that is,
+ * BlockBackends for which blk_is_inserted() returns false)
+ */
+BlockBackend *blk_next_inserted(BlockBackend *blk)
+{
+ while ((blk = blk_next(blk)) != NULL) {
+ if (blk_is_inserted(blk)) {
+ break;
+ }
+ }
+
+ return blk;
+}
+
+/*
* Return @blk's name, a non-null string.
* Wart: the name is empty iff @blk has been hidden with
* blk_hide_on_behalf_of_do_drive_del().
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index b9eae9b..8b4a9ec 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -72,6 +72,7 @@ const char *blk_name(BlockBackend *blk);
BlockBackend *blk_by_name(const char *name);
bool blk_name_taken(const char *name);
BlockBackend *blk_next(BlockBackend *blk);
+BlockBackend *blk_next_inserted(BlockBackend *blk);
BlockDriverState *blk_bs(BlockBackend *blk);
void blk_remove_bs(BlockBackend *blk);
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 3/9] block: Add blk_commit_all() and blk_invalidate_cache_all()
2015-02-24 16:23 [Qemu-devel] [PATCH 0/9] blockdev: Further BlockBackend work Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 1/9] block: Add blk_name_taken() Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 2/9] block: Add blk_next_inserted() Max Reitz
@ 2015-02-24 16:23 ` Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 4/9] block: Use BlockBackend more Max Reitz
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Max Reitz @ 2015-02-24 16:23 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: Kevin Wolf, Markus Armbruster, Stefan Hajnoczi, Max Reitz
These functions will be changed to iterate through the BDS trees as
defined by the BlockBackends instead of the list of root BDS, therefore
prepare moving their code to the BlockBackend level.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
block/block-backend.c | 10 ++++++++++
include/sysemu/block-backend.h | 2 ++
2 files changed, 12 insertions(+)
diff --git a/block/block-backend.c b/block/block-backend.c
index ab3affa..2550ee0 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -1251,3 +1251,13 @@ BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
{
return &blk->root_state;
}
+
+int blk_commit_all(void)
+{
+ return bdrv_commit_all();
+}
+
+void blk_invalidate_cache_all(Error **errp)
+{
+ bdrv_invalidate_cache_all(errp);
+}
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 8b4a9ec..2400a7e 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -126,7 +126,9 @@ int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors);
int blk_co_flush(BlockBackend *blk);
int blk_flush(BlockBackend *blk);
int blk_flush_all(void);
+int blk_commit_all(void);
void blk_drain_all(void);
+void blk_invalidate_cache_all(Error **errp);
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
BlockdevOnError on_write_error);
BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read);
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 4/9] block: Use BlockBackend more
2015-02-24 16:23 [Qemu-devel] [PATCH 0/9] blockdev: Further BlockBackend work Max Reitz
` (2 preceding siblings ...)
2015-02-24 16:23 ` [Qemu-devel] [PATCH 3/9] block: Add blk_commit_all() and blk_invalidate_cache_all() Max Reitz
@ 2015-02-24 16:23 ` Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 5/9] blockdev: Add list of monitor-owned BlockBackends Max Reitz
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Max Reitz @ 2015-02-24 16:23 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: Kevin Wolf, Markus Armbruster, Stefan Hajnoczi, Max Reitz
Replace bdrv_drain_all(), bdrv_commmit_all(), bdrv_flush_all(),
bdrv_invalidate_cache_all(), bdrv_next() and occurrences of bdrv_states
by their BlockBackend equivalents.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block.c | 14 +++++------
block/block-backend.c | 8 +++----
block/qapi.c | 13 ++++++++--
block/snapshot.c | 3 ++-
blockdev.c | 14 ++++++-----
cpus.c | 7 +++---
migration/block.c | 10 +++++---
migration/migration.c | 4 ++--
monitor.c | 13 ++++++----
qemu-char.c | 3 ++-
qemu-io.c | 2 +-
qmp.c | 9 ++++---
savevm.c | 66 ++++++++++++++++++++++++++++++---------------------
xen-mapcache.c | 3 ++-
14 files changed, 101 insertions(+), 68 deletions(-)
diff --git a/block.c b/block.c
index 1badb75..e479042 100644
--- a/block.c
+++ b/block.c
@@ -1721,7 +1721,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp)
assert(bs_queue != NULL);
- bdrv_drain_all();
+ blk_drain_all();
QSIMPLEQ_FOREACH(bs_entry, bs_queue, entry) {
if (bdrv_reopen_prepare(&bs_entry->state, bs_queue, &local_err)) {
@@ -1891,9 +1891,9 @@ static void bdrv_close(BlockDriverState *bs)
if (bs->job) {
block_job_cancel_sync(bs->job);
}
- bdrv_drain_all(); /* complete I/O */
+ blk_drain_all(); /* complete I/O */
bdrv_flush(bs);
- bdrv_drain_all(); /* in case flush left pending I/O */
+ blk_drain_all(); /* in case flush left pending I/O */
if (bs->drv) {
if (bs->backing_hd) {
@@ -5738,7 +5738,7 @@ void bdrv_attach_aio_context(BlockDriverState *bs,
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
{
- bdrv_drain_all(); /* ensure there are no in-flight requests */
+ blk_drain_all(); /* ensure there are no in-flight requests */
bdrv_detach_aio_context(bs);
@@ -5841,14 +5841,14 @@ bool bdrv_recurse_is_first_non_filter(BlockDriverState *bs,
*/
bool bdrv_is_first_non_filter(BlockDriverState *candidate)
{
- BlockDriverState *bs;
+ BlockBackend *blk = NULL;
/* walk down the bs forest recursively */
- QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+ while ((blk = blk_next_inserted(blk)) != NULL) {
bool perm;
/* try to recurse in this top level bs */
- perm = bdrv_recurse_is_first_non_filter(bs, candidate);
+ perm = bdrv_recurse_is_first_non_filter(blk_bs(blk), candidate);
/* candidate is the first non filter */
if (perm) {
diff --git a/block/block-backend.c b/block/block-backend.c
index 2550ee0..5a52af2 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -266,10 +266,10 @@ const char *blk_name(BlockBackend *blk)
*/
BlockBackend *blk_by_name(const char *name)
{
- BlockBackend *blk;
+ BlockBackend *blk = NULL;
assert(name);
- QTAILQ_FOREACH(blk, &blk_backends, link) {
+ while ((blk = blk_next(blk)) != NULL) {
if (!strcmp(name, blk->name)) {
return blk;
}
@@ -327,9 +327,9 @@ DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
*/
BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
{
- BlockBackend *blk;
+ BlockBackend *blk = NULL;
- QTAILQ_FOREACH(blk, &blk_backends, link) {
+ while ((blk = blk_next(blk)) != NULL) {
if (blk->legacy_dinfo == dinfo) {
return blk;
}
diff --git a/block/qapi.c b/block/qapi.c
index 43b0be2..0d97d6f 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -395,15 +395,24 @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
{
BlockStatsList *head = NULL, **p_next = &head;
BlockDriverState *bs = NULL;
+ BlockBackend *blk = NULL;
/* Just to be safe if query_nodes is not always initialized */
query_nodes = has_query_nodes && query_nodes;
- while ((bs = query_nodes ? bdrv_next_node(bs) : bdrv_next(bs))) {
+ while (query_nodes ? (bs = bdrv_next_node(bs)) != NULL
+ : (blk = blk_next_inserted(blk)) != NULL)
+ {
BlockStatsList *info = g_malloc0(sizeof(*info));
- AioContext *ctx = bdrv_get_aio_context(bs);
+ AioContext *ctx = blk ? blk_get_aio_context(blk)
+ : bdrv_get_aio_context(bs);
aio_context_acquire(ctx);
+
+ if (blk) {
+ bs = blk_bs(blk);
+ }
+
info->value = bdrv_query_stats(bs, !query_nodes);
aio_context_release(ctx);
diff --git a/block/snapshot.c b/block/snapshot.c
index 698e1a1..e92e2d4 100644
--- a/block/snapshot.c
+++ b/block/snapshot.c
@@ -24,6 +24,7 @@
#include "block/snapshot.h"
#include "block/block_int.h"
+#include "sysemu/block-backend.h"
QemuOptsList internal_snapshot_opts = {
.name = "snapshot",
@@ -238,7 +239,7 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
}
/* drain all pending i/o before deleting snapshot */
- bdrv_drain_all();
+ blk_drain_all();
if (drv->bdrv_snapshot_delete) {
return drv->bdrv_snapshot_delete(bs, snapshot_id, name, errp);
diff --git a/blockdev.c b/blockdev.c
index 535e83f..58c74c3 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1120,7 +1120,7 @@ void do_commit(Monitor *mon, const QDict *qdict)
int ret;
if (!strcmp(device, "all")) {
- ret = bdrv_commit_all();
+ ret = blk_commit_all();
} else {
bs = bdrv_find(device);
if (!bs) {
@@ -1794,7 +1794,7 @@ void qmp_transaction(TransactionActionList *dev_list, Error **errp)
QSIMPLEQ_INIT(&snap_bdrv_states);
/* drain all i/o before any operations */
- bdrv_drain_all();
+ blk_drain_all();
/* We don't do anything in this loop that commits us to the operations */
while (NULL != dev_entry) {
@@ -2301,7 +2301,7 @@ void qmp_block_resize(bool has_device, const char *device,
}
/* complete all in-flight operations before resizing the device */
- bdrv_drain_all();
+ blk_drain_all();
ret = bdrv_truncate(bs, size);
switch (ret) {
@@ -2468,7 +2468,7 @@ void qmp_block_commit(const char *device,
bs = blk_bs(blk);
/* drain all i/o before commits */
- bdrv_drain_all();
+ blk_drain_all();
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_COMMIT_SOURCE, errp)) {
goto out;
@@ -3204,12 +3204,14 @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
{
BlockJobInfoList *head = NULL, **p_next = &head;
BlockDriverState *bs;
+ BlockBackend *blk = NULL;
- for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
- AioContext *aio_context = bdrv_get_aio_context(bs);
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ AioContext *aio_context = blk_get_aio_context(blk);
aio_context_acquire(aio_context);
+ bs = blk_bs(blk);
if (bs->job) {
BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1);
elem->value = block_job_query(bs->job);
diff --git a/cpus.c b/cpus.c
index 97939e4..9845602 100644
--- a/cpus.c
+++ b/cpus.c
@@ -28,6 +28,7 @@
#include "monitor/monitor.h"
#include "qapi/qmp/qerror.h"
#include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
#include "exec/gdbstub.h"
#include "sysemu/dma.h"
#include "sysemu/kvm.h"
@@ -607,8 +608,8 @@ static int do_vm_stop(RunState state)
qapi_event_send_stop(&error_abort);
}
- bdrv_drain_all();
- ret = bdrv_flush_all();
+ blk_drain_all();
+ ret = blk_flush_all();
return ret;
}
@@ -1306,7 +1307,7 @@ int vm_stop_force_state(RunState state)
runstate_set(state);
/* Make sure to return an error if the flush in a previous vm_stop()
* failed. */
- return bdrv_flush_all();
+ return blk_flush_all();
}
}
diff --git a/migration/block.c b/migration/block.c
index 0c76106..ec435db 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -23,6 +23,7 @@
#include "migration/block.h"
#include "migration/migration.h"
#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
#include <assert.h>
#define BLOCK_SIZE (1 << 20)
@@ -348,6 +349,7 @@ static void unset_dirty_tracking(void)
static void init_blk_migration(QEMUFile *f)
{
BlockDriverState *bs;
+ BlockBackend *blk = NULL;
BlkMigDevState *bmds;
int64_t sectors;
@@ -359,7 +361,9 @@ static void init_blk_migration(QEMUFile *f)
block_mig_state.bulk_completed = 0;
block_mig_state.zero_blocks = migrate_zero_blocks();
- for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ bs = blk_bs(blk);
+
if (bdrv_is_read_only(bs)) {
continue;
}
@@ -456,7 +460,7 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
blk_mig_lock();
if (bmds_aio_inflight(bmds, sector)) {
blk_mig_unlock();
- bdrv_drain_all();
+ blk_drain_all();
} else {
blk_mig_unlock();
}
@@ -596,7 +600,7 @@ static void blk_mig_cleanup(void)
BlkMigDevState *bmds;
BlkMigBlock *blk;
- bdrv_drain_all();
+ blk_drain_all();
unset_dirty_tracking();
diff --git a/migration/migration.c b/migration/migration.c
index 2c805f1..ef31942 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -19,7 +19,7 @@
#include "monitor/monitor.h"
#include "migration/qemu-file.h"
#include "sysemu/sysemu.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
#include "qemu/sockets.h"
#include "migration/block.h"
#include "qemu/thread.h"
@@ -121,7 +121,7 @@ static void process_incoming_migration_co(void *opaque)
qemu_announce_self();
/* Make sure all file formats flush their mutable metadata */
- bdrv_invalidate_cache_all(&local_err);
+ blk_invalidate_cache_all(&local_err);
if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
diff --git a/monitor.c b/monitor.c
index c3cc060..0c9d34c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -40,6 +40,7 @@
#include "ui/console.h"
#include "ui/input.h"
#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
#include "audio/audio.h"
#include "disas/disas.h"
#include "sysemu/balloon.h"
@@ -4617,13 +4618,15 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
static void vm_completion(ReadLineState *rs, const char *str)
{
size_t len;
- BlockDriverState *bs = NULL;
+ BlockDriverState *bs;
+ BlockBackend *blk = NULL;
len = strlen(str);
readline_set_completion_index(rs, len);
- while ((bs = bdrv_next(bs))) {
+ while ((blk = blk_next_inserted(blk)) != NULL) {
SnapshotInfoList *snapshots, *snapshot;
+ bs = blk_bs(blk);
if (!bdrv_can_snapshot(bs)) {
continue;
}
@@ -4670,7 +4673,7 @@ static void monitor_find_completion_by_table(Monitor *mon,
int i;
const char *ptype, *str, *name;
const mon_cmd_t *cmd;
- BlockDriverState *bs;
+ BlockBackend *blk = NULL;
if (nb_args <= 1) {
/* command completion */
@@ -4723,8 +4726,8 @@ static void monitor_find_completion_by_table(Monitor *mon,
case 'B':
/* block device name completion */
readline_set_completion_index(mon->rs, strlen(str));
- for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
- name = bdrv_get_device_name(bs);
+ while ((blk = blk_next(blk)) != NULL) {
+ name = blk_name(blk);
if (str[0] == '\0' ||
!strncmp(name, str, strlen(str))) {
readline_add_completion(mon->rs, name);
diff --git a/qemu-char.c b/qemu-char.c
index 98d4342..4d3fb60 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -24,6 +24,7 @@
#include "qemu-common.h"
#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
#include "qemu/timer.h"
#include "sysemu/char.h"
#include "hw/usb.h"
@@ -523,7 +524,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
break;
}
case 's':
- bdrv_commit_all();
+ blk_commit_all();
break;
case 'b':
qemu_chr_be_event(chr, CHR_EVENT_BREAK);
diff --git a/qemu-io.c b/qemu-io.c
index 4a3e719..04a3fe8 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -472,7 +472,7 @@ int main(int argc, char **argv)
/*
* Make sure all outstanding requests complete before the program exits.
*/
- bdrv_drain_all();
+ blk_drain_all();
blk_unref(qemuio_blk);
g_free(readline_state);
diff --git a/qmp.c b/qmp.c
index 38f0117..e280467 100644
--- a/qmp.c
+++ b/qmp.c
@@ -162,8 +162,7 @@ SpiceInfo *qmp_query_spice(Error **errp)
void qmp_cont(Error **errp)
{
Error *local_err = NULL;
- BlockBackend *blk;
- BlockDriverState *bs;
+ BlockBackend *blk = NULL;
if (runstate_needs_reset()) {
error_setg(errp, "Resetting the Virtual Machine is required");
@@ -172,11 +171,11 @@ void qmp_cont(Error **errp)
return;
}
- for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+ while ((blk = blk_next(blk)) != NULL) {
blk_iostatus_reset(blk);
}
- for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
- bdrv_add_key(bs, NULL, &local_err);
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ bdrv_add_key(blk_bs(blk), NULL, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
diff --git a/savevm.c b/savevm.c
index 1d08165..2037fdf 100644
--- a/savevm.c
+++ b/savevm.c
@@ -30,6 +30,7 @@
#include "net/net.h"
#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
#include "qemu/timer.h"
#include "audio/audio.h"
#include "migration/migration.h"
@@ -1054,10 +1055,10 @@ out:
static BlockDriverState *find_vmstate_bs(void)
{
- BlockDriverState *bs = NULL;
- while ((bs = bdrv_next(bs))) {
- if (bdrv_can_snapshot(bs)) {
- return bs;
+ BlockBackend *blk = NULL;
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ if (bdrv_can_snapshot(blk_bs(blk))) {
+ return blk_bs(blk);
}
}
return NULL;
@@ -1069,11 +1070,13 @@ static BlockDriverState *find_vmstate_bs(void)
static int del_existing_snapshots(Monitor *mon, const char *name)
{
BlockDriverState *bs;
+ BlockBackend *blk = NULL;
QEMUSnapshotInfo sn1, *snapshot = &sn1;
Error *err = NULL;
- bs = NULL;
- while ((bs = bdrv_next(bs))) {
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ bs = blk_bs(blk);
+
if (bdrv_can_snapshot(bs) &&
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
bdrv_snapshot_delete_by_id_or_name(bs, name, &err);
@@ -1095,6 +1098,7 @@ static int del_existing_snapshots(Monitor *mon, const char *name)
void do_savevm(Monitor *mon, const QDict *qdict)
{
BlockDriverState *bs, *bs1;
+ BlockBackend *blk = NULL;
QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
int ret;
QEMUFile *f;
@@ -1106,16 +1110,14 @@ void do_savevm(Monitor *mon, const QDict *qdict)
Error *local_err = NULL;
/* Verify if there is a device that doesn't support snapshots and is writable */
- bs = NULL;
- while ((bs = bdrv_next(bs))) {
-
- if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ if (blk_is_read_only(blk)) {
continue;
}
- if (!bdrv_can_snapshot(bs)) {
+ if (!bdrv_can_snapshot(blk_bs(blk))) {
monitor_printf(mon, "Device '%s' is writable but does not support snapshots.\n",
- bdrv_get_device_name(bs));
+ blk_name(blk));
return;
}
}
@@ -1173,15 +1175,17 @@ void do_savevm(Monitor *mon, const QDict *qdict)
/* create the snapshots */
- bs1 = NULL;
- while ((bs1 = bdrv_next(bs1))) {
+ blk = NULL;
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ bs1 = blk_bs(blk);
+
if (bdrv_can_snapshot(bs1)) {
/* Write VM state size only to the image that contains the state */
sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
ret = bdrv_snapshot_create(bs1, sn);
if (ret < 0) {
monitor_printf(mon, "Error while creating snapshot on '%s'\n",
- bdrv_get_device_name(bs1));
+ blk_name(blk));
}
}
}
@@ -1220,6 +1224,7 @@ void qmp_xen_save_devices_state(const char *filename, Error **errp)
int load_vmstate(const char *name)
{
+ BlockBackend *blk;
BlockDriverState *bs, *bs_vm_state;
QEMUSnapshotInfo sn;
QEMUFile *f;
@@ -1243,12 +1248,12 @@ int load_vmstate(const char *name)
/* Verify if there is any device that doesn't support snapshots and is
writable and check if the requested snapshot is available too. */
- bs = NULL;
- while ((bs = bdrv_next(bs))) {
-
- if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
+ blk = NULL;
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ if (blk_is_read_only(blk)) {
continue;
}
+ bs = blk_bs(blk);
if (!bdrv_can_snapshot(bs)) {
error_report("Device '%s' is writable but does not support snapshots.",
@@ -1265,10 +1270,12 @@ int load_vmstate(const char *name)
}
/* Flush all IO requests so they don't interfere with the new state. */
- bdrv_drain_all();
+ blk_drain_all();
+
+ blk = NULL;
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ bs = blk_bs(blk);
- bs = NULL;
- while ((bs = bdrv_next(bs))) {
if (bdrv_can_snapshot(bs)) {
ret = bdrv_snapshot_goto(bs, name);
if (ret < 0) {
@@ -1301,6 +1308,7 @@ int load_vmstate(const char *name)
void do_delvm(Monitor *mon, const QDict *qdict)
{
BlockDriverState *bs;
+ BlockBackend *blk = NULL;
Error *err;
const char *name = qdict_get_str(qdict, "name");
@@ -1309,8 +1317,9 @@ void do_delvm(Monitor *mon, const QDict *qdict)
return;
}
- bs = NULL;
- while ((bs = bdrv_next(bs))) {
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ bs = blk_bs(blk);
+
if (bdrv_can_snapshot(bs)) {
err = NULL;
bdrv_snapshot_delete_by_id_or_name(bs, name, &err);
@@ -1318,7 +1327,7 @@ void do_delvm(Monitor *mon, const QDict *qdict)
monitor_printf(mon,
"Error while deleting snapshot on device '%s':"
" %s\n",
- bdrv_get_device_name(bs),
+ blk_name(blk),
error_get_pretty(err));
error_free(err);
}
@@ -1329,6 +1338,7 @@ void do_delvm(Monitor *mon, const QDict *qdict)
void do_info_snapshots(Monitor *mon, const QDict *qdict)
{
BlockDriverState *bs, *bs1;
+ BlockBackend *blk;
QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
int nb_sns, i, ret, available;
int total;
@@ -1356,9 +1366,11 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict)
for (i = 0; i < nb_sns; i++) {
sn = &sn_tab[i];
available = 1;
- bs1 = NULL;
+ blk = NULL;
+
+ while ((blk = blk_next_inserted(blk)) != NULL) {
+ bs1 = blk_bs(blk);
- while ((bs1 = bdrv_next(bs1))) {
if (bdrv_can_snapshot(bs1) && bs1 != bs) {
ret = bdrv_snapshot_find(bs1, sn_info, sn->id_str);
if (ret < 0) {
diff --git a/xen-mapcache.c b/xen-mapcache.c
index 8cefd0c..1a98a69 100644
--- a/xen-mapcache.c
+++ b/xen-mapcache.c
@@ -14,6 +14,7 @@
#include "hw/xen/xen_backend.h"
#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
#include "qemu/bitmap.h"
#include <xen/hvm/params.h>
@@ -421,7 +422,7 @@ void xen_invalidate_map_cache(void)
MapCacheRev *reventry;
/* Flush pending AIO before destroying the mapcache */
- bdrv_drain_all();
+ blk_drain_all();
mapcache_lock();
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 5/9] blockdev: Add list of monitor-owned BlockBackends
2015-02-24 16:23 [Qemu-devel] [PATCH 0/9] blockdev: Further BlockBackend work Max Reitz
` (3 preceding siblings ...)
2015-02-24 16:23 ` [Qemu-devel] [PATCH 4/9] block: Use BlockBackend more Max Reitz
@ 2015-02-24 16:23 ` Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 6/9] blockdev: Remove blk_hide_on_behalf_of_do_drive_del() Max Reitz
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Max Reitz @ 2015-02-24 16:23 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: Kevin Wolf, Markus Armbruster, Stefan Hajnoczi, Max Reitz
The monitor does hold references to some BlockBackends so it should have
a list of those BBs; blk_backends is a different list, as it contains
references to all BBs (after a follow-up patch, that is), and that
should not be changed because we do need such a list.
monitor_remove_blk() is idempotent so that we can call it in
blockdev_auto_del() without having to care whether it had been called in
do_drive_del() before. monitor_add_blk() is idempotent for symmetry
reasons (monitor_remove_blk() is, so it would be strange for
monitor_add_blk() not to be).
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/block-backend.c | 34 +++++++++++++++++++++++++++++++++-
blockdev.c | 4 ++++
include/sysemu/block-backend.h | 2 ++
3 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/block/block-backend.c b/block/block-backend.c
index 5a52af2..0eb6216 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -28,6 +28,8 @@ struct BlockBackend {
BlockDriverState *bs;
DriveInfo *legacy_dinfo; /* null unless created by drive_new() */
QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
+ QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
+ bool in_monitor_list;
void *dev; /* attached device model, if any */
/* TODO change to DeviceState when all users are qdevified */
@@ -69,6 +71,11 @@ static void drive_info_del(DriveInfo *dinfo);
static QTAILQ_HEAD(, BlockBackend) blk_backends =
QTAILQ_HEAD_INITIALIZER(blk_backends);
+/* All BlockBackends referenced by the monitor and which are iterated through by
+ * blk_next() */
+static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
+ QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
+
/*
* Create a new BlockBackend with @name, with a reference count of one.
* @name must not be null or empty.
@@ -232,7 +239,8 @@ void blk_remove_all_bs(void)
*/
BlockBackend *blk_next(BlockBackend *blk)
{
- return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
+ return blk ? QTAILQ_NEXT(blk, monitor_link)
+ : QTAILQ_FIRST(&monitor_block_backends);
}
/*
@@ -251,6 +259,30 @@ BlockBackend *blk_next_inserted(BlockBackend *blk)
}
/*
+ * Add a BlockBackend into the list of backends referenced by the monitor.
+ * Strictly for use by blockdev.c.
+ */
+void monitor_add_blk(BlockBackend *blk)
+{
+ if (!blk->in_monitor_list) {
+ QTAILQ_INSERT_TAIL(&monitor_block_backends, blk, monitor_link);
+ blk->in_monitor_list = true;
+ }
+}
+
+/*
+ * Remove a BlockBackend from the list of backends referenced by the monitor.
+ * Strictly for use by blockdev.c.
+ */
+void monitor_remove_blk(BlockBackend *blk)
+{
+ if (blk->in_monitor_list) {
+ QTAILQ_REMOVE(&monitor_block_backends, blk, monitor_link);
+ blk->in_monitor_list = false;
+ }
+}
+
+/*
* Return @blk's name, a non-null string.
* Wart: the name is empty iff @blk has been hidden with
* blk_hide_on_behalf_of_do_drive_del().
diff --git a/blockdev.c b/blockdev.c
index 58c74c3..e9158b6 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -143,6 +143,7 @@ void blockdev_auto_del(BlockBackend *blk)
DriveInfo *dinfo = blk_legacy_dinfo(blk);
if (dinfo && dinfo->auto_del) {
+ monitor_remove_blk(blk);
blk_unref(blk);
}
}
@@ -585,6 +586,8 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
blk_set_on_error(blk, on_read_error, on_write_error);
+ monitor_add_blk(blk);
+
err_no_bs_opts:
qemu_opts_del(opts);
return blk;
@@ -2246,6 +2249,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
/* quiesce block driver; prevent further io */
blk_remove_bs(blk);
+ monitor_remove_blk(blk);
/* if we have a device attached to this BlockDriverState
* then we need to make the drive anonymous until the device
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 2400a7e..397b125 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -73,6 +73,8 @@ BlockBackend *blk_by_name(const char *name);
bool blk_name_taken(const char *name);
BlockBackend *blk_next(BlockBackend *blk);
BlockBackend *blk_next_inserted(BlockBackend *blk);
+void monitor_add_blk(BlockBackend *blk);
+void monitor_remove_blk(BlockBackend *blk);
BlockDriverState *blk_bs(BlockBackend *blk);
void blk_remove_bs(BlockBackend *blk);
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 6/9] blockdev: Remove blk_hide_on_behalf_of_do_drive_del()
2015-02-24 16:23 [Qemu-devel] [PATCH 0/9] blockdev: Further BlockBackend work Max Reitz
` (4 preceding siblings ...)
2015-02-24 16:23 ` [Qemu-devel] [PATCH 5/9] blockdev: Add list of monitor-owned BlockBackends Max Reitz
@ 2015-02-24 16:23 ` Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 7/9] block: Make bdrv_drain_one() public Max Reitz
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Max Reitz @ 2015-02-24 16:23 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: Kevin Wolf, Markus Armbruster, Stefan Hajnoczi, Max Reitz
This function first removed the BlockBackend from the blk_backends list
and cleared its name so it would no longer be found by blk_name(); since
blk_next() now iterates through monitor_block_backends (which the BB is
removed from in do_drive_del()), this is no longer necessary.
Second, bdrv_make_anon() was called on the BDS. This was intended for
cases where the BDS was owned by that BB alone; in which case the BDS
will no longer exist at this point thanks to the blk_remove_bs() in
do_drive_del().
Therefore, this function does nothing useful anymore. Remove it.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block/block-backend.c | 25 ++-----------------------
blockdev.c | 1 -
include/sysemu/block-backend.h | 2 --
3 files changed, 2 insertions(+), 26 deletions(-)
diff --git a/block/block-backend.c b/block/block-backend.c
index 0eb6216..48e0eaa 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -67,7 +67,7 @@ static const AIOCBInfo block_backend_aiocb_info = {
static void drive_info_del(DriveInfo *dinfo);
-/* All the BlockBackends (except for hidden ones) */
+/* All the BlockBackends */
static QTAILQ_HEAD(, BlockBackend) blk_backends =
QTAILQ_HEAD_INITIALIZER(blk_backends);
@@ -171,10 +171,7 @@ static void blk_delete(BlockBackend *blk)
assert(!blk->refcnt);
assert(!blk->dev);
blk_remove_bs(blk);
- /* Avoid double-remove after blk_hide_on_behalf_of_do_drive_del() */
- if (blk->name[0]) {
- QTAILQ_REMOVE(&blk_backends, blk, link);
- }
+ QTAILQ_REMOVE(&blk_backends, blk, link);
g_free(blk->name);
drive_info_del(blk->legacy_dinfo);
g_free(blk);
@@ -370,24 +367,6 @@ BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
}
/*
- * Hide @blk.
- * @blk must not have been hidden already.
- * Make attached BlockDriverState, if any, anonymous.
- * Once hidden, @blk is invisible to all functions that don't receive
- * it as argument. For example, blk_by_name() won't return it.
- * Strictly for use by do_drive_del().
- * TODO get rid of it!
- */
-void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk)
-{
- QTAILQ_REMOVE(&blk_backends, blk, link);
- blk->name[0] = 0;
- if (blk->bs) {
- bdrv_make_anon(blk->bs);
- }
-}
-
-/*
* Disassociates the currently associated BlockDriverState from @blk.
*/
void blk_remove_bs(BlockBackend *blk)
diff --git a/blockdev.c b/blockdev.c
index e9158b6..a72e29f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2257,7 +2257,6 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
* then we can just get rid of the block driver state right here.
*/
if (blk_get_attached_dev(blk)) {
- blk_hide_on_behalf_of_do_drive_del(blk);
/* Further I/O must not pause the guest */
blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT,
BLOCKDEV_ON_ERROR_REPORT);
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 397b125..49ae701 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -80,8 +80,6 @@ BlockDriverState *blk_bs(BlockBackend *blk);
void blk_remove_bs(BlockBackend *blk);
void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs);
-void blk_hide_on_behalf_of_do_drive_del(BlockBackend *blk);
-
void blk_iostatus_enable(BlockBackend *blk);
bool blk_iostatus_is_enabled(const BlockBackend *blk);
BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk);
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 7/9] block: Make bdrv_drain_one() public
2015-02-24 16:23 [Qemu-devel] [PATCH 0/9] blockdev: Further BlockBackend work Max Reitz
` (5 preceding siblings ...)
2015-02-24 16:23 ` [Qemu-devel] [PATCH 6/9] blockdev: Remove blk_hide_on_behalf_of_do_drive_del() Max Reitz
@ 2015-02-24 16:23 ` Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 8/9] block: Move some bdrv_*_all() functions to BB Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 9/9] block: Remove bdrv_states Max Reitz
8 siblings, 0 replies; 10+ messages in thread
From: Max Reitz @ 2015-02-24 16:23 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: Kevin Wolf, Markus Armbruster, Stefan Hajnoczi, Max Reitz
We will need it in block/block-backend.c.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block.c | 2 +-
include/block/block_int.h | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/block.c b/block.c
index e479042..b81f91d 100644
--- a/block.c
+++ b/block.c
@@ -1966,7 +1966,7 @@ static bool bdrv_requests_pending(BlockDriverState *bs)
return false;
}
-static bool bdrv_drain_one(BlockDriverState *bs)
+bool bdrv_drain_one(BlockDriverState *bs)
{
bool bs_busy;
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 1b01f45..d839a8a 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -447,6 +447,8 @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
void bdrv_set_io_limits(BlockDriverState *bs,
ThrottleConfig *cfg);
+bool bdrv_drain_one(BlockDriverState *bs);
+
/**
* bdrv_add_before_write_notifier:
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 8/9] block: Move some bdrv_*_all() functions to BB
2015-02-24 16:23 [Qemu-devel] [PATCH 0/9] blockdev: Further BlockBackend work Max Reitz
` (6 preceding siblings ...)
2015-02-24 16:23 ` [Qemu-devel] [PATCH 7/9] block: Make bdrv_drain_one() public Max Reitz
@ 2015-02-24 16:23 ` Max Reitz
2015-02-24 16:23 ` [Qemu-devel] [PATCH 9/9] block: Remove bdrv_states Max Reitz
8 siblings, 0 replies; 10+ messages in thread
From: Max Reitz @ 2015-02-24 16:23 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: Kevin Wolf, Markus Armbruster, Stefan Hajnoczi, Max Reitz
Move bdrv_drain_all(), bdrv_commit_all(), bdrv_flush_all() and
bdrv_invalidate_cache_all() to BB.
The only operation left is bdrv_close_all(), which cannot be moved to
the BB because it should not only close all BBs, but also all
monitor-owned BDSs.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block.c | 97 --------------------------------------------
block/block-backend.c | 104 ++++++++++++++++++++++++++++++++++++++++++------
include/block/block.h | 4 --
stubs/Makefile.objs | 2 +-
stubs/bdrv-commit-all.c | 7 ----
stubs/blk-commit-all.c | 7 ++++
6 files changed, 100 insertions(+), 121 deletions(-)
delete mode 100644 stubs/bdrv-commit-all.c
create mode 100644 stubs/blk-commit-all.c
diff --git a/block.c b/block.c
index b81f91d..dc24398 100644
--- a/block.c
+++ b/block.c
@@ -1994,37 +1994,6 @@ void bdrv_drain(BlockDriverState *bs)
}
}
-/*
- * Wait for pending requests to complete across all BlockDriverStates
- *
- * This function does not flush data to disk, use bdrv_flush_all() for that
- * after calling this function.
- *
- * Note that completion of an asynchronous I/O operation can trigger any
- * number of other I/O operations on other devices---for example a coroutine
- * can be arbitrarily complex and a constant flow of I/O can come until the
- * coroutine is complete. Because of this, it is not possible to have a
- * function to drain a single device's I/O queue.
- */
-void bdrv_drain_all(void)
-{
- /* Always run first iteration so any pending completion BHs run */
- bool busy = true;
- BlockDriverState *bs;
-
- while (busy) {
- busy = false;
-
- QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
- AioContext *aio_context = bdrv_get_aio_context(bs);
-
- aio_context_acquire(aio_context);
- busy |= bdrv_drain_one(bs);
- aio_context_release(aio_context);
- }
- }
-}
-
/* make a BlockDriverState anonymous by removing from bdrv_state and
* graph_bdrv_state list.
Also, NULL terminate the device_name to prevent double remove */
@@ -2320,26 +2289,6 @@ ro_cleanup:
return ret;
}
-int bdrv_commit_all(void)
-{
- BlockDriverState *bs;
-
- QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
- AioContext *aio_context = bdrv_get_aio_context(bs);
-
- aio_context_acquire(aio_context);
- if (bs->drv && bs->backing_hd) {
- int ret = bdrv_commit(bs);
- if (ret < 0) {
- aio_context_release(aio_context);
- return ret;
- }
- }
- aio_context_release(aio_context);
- }
- return 0;
-}
-
/**
* Remove an active request from the tracked requests list
*
@@ -3814,14 +3763,6 @@ BlockDriverState *bdrv_next_node(BlockDriverState *bs)
return QTAILQ_NEXT(bs, node_list);
}
-BlockDriverState *bdrv_next(BlockDriverState *bs)
-{
- if (!bs) {
- return QTAILQ_FIRST(&bdrv_states);
- }
- return QTAILQ_NEXT(bs, device_list);
-}
-
const char *bdrv_get_node_name(const BlockDriverState *bs)
{
return bs->node_name;
@@ -3838,26 +3779,6 @@ int bdrv_get_flags(BlockDriverState *bs)
return bs->open_flags;
}
-int bdrv_flush_all(void)
-{
- BlockDriverState *bs;
- int result = 0;
-
- QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
- AioContext *aio_context = bdrv_get_aio_context(bs);
- int ret;
-
- aio_context_acquire(aio_context);
- ret = bdrv_flush(bs);
- if (ret < 0 && !result) {
- result = ret;
- }
- aio_context_release(aio_context);
- }
-
- return result;
-}
-
int bdrv_has_zero_init_1(BlockDriverState *bs)
{
return 1;
@@ -5017,24 +4938,6 @@ void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp)
}
}
-void bdrv_invalidate_cache_all(Error **errp)
-{
- BlockDriverState *bs;
- Error *local_err = NULL;
-
- QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
- AioContext *aio_context = bdrv_get_aio_context(bs);
-
- aio_context_acquire(aio_context);
- bdrv_invalidate_cache(bs, &local_err);
- aio_context_release(aio_context);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- }
-}
-
int bdrv_flush(BlockDriverState *bs)
{
Coroutine *co;
diff --git a/block/block-backend.c b/block/block-backend.c
index 48e0eaa..25659b3 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -380,6 +380,9 @@ void blk_remove_bs(BlockBackend *blk)
notifier_list_notify(&blk->remove_bs_notifiers, blk);
blk_update_root_state(blk);
+ /* After this function, the BDS may longer be accessible to blk_*_all()
+ * functions */
+ blk_drain_all();
bdrv_unref(blk->bs);
blk->bs->blk = NULL;
@@ -871,16 +874,6 @@ int blk_flush(BlockBackend *blk)
return bdrv_flush(blk->bs);
}
-int blk_flush_all(void)
-{
- return bdrv_flush_all();
-}
-
-void blk_drain_all(void)
-{
- bdrv_drain_all();
-}
-
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
BlockdevOnError on_write_error)
{
@@ -1263,12 +1256,99 @@ BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
return &blk->root_state;
}
+/*
+ * Wait for pending requests to complete across all BlockBackends
+ *
+ * This function does not flush data to disk, use blk_flush_all() for that
+ * after calling this function.
+ *
+ * Note that completion of an asynchronous I/O operation can trigger any
+ * number of other I/O operations on other devices---for example a coroutine
+ * can be arbitrarily complex and a constant flow of I/O can come until the
+ * coroutine is complete. Because of this, it is not possible to have a
+ * function to drain a single device's I/O queue.
+ */
+void blk_drain_all(void)
+{
+ /* Always run first iteration so any pending completion BHs run */
+ bool busy = true;
+ BlockBackend *blk;
+
+ while (busy) {
+ busy = false;
+
+ QTAILQ_FOREACH(blk, &blk_backends, link) {
+ AioContext *aio_context = blk_get_aio_context(blk);
+
+ if (!blk_is_inserted(blk)) {
+ continue;
+ }
+
+ aio_context_acquire(aio_context);
+ busy |= bdrv_drain_one(blk->bs);
+ aio_context_release(aio_context);
+ }
+ }
+}
+
int blk_commit_all(void)
{
- return bdrv_commit_all();
+ BlockBackend *blk;
+
+ QTAILQ_FOREACH(blk, &blk_backends, link) {
+ AioContext *aio_context = blk_get_aio_context(blk);
+
+ aio_context_acquire(aio_context);
+ if (blk_is_available(blk) && blk->bs->drv && blk->bs->backing_hd) {
+ int ret = bdrv_commit(blk->bs);
+ if (ret < 0) {
+ aio_context_release(aio_context);
+ return ret;
+ }
+ }
+ aio_context_release(aio_context);
+ }
+ return 0;
+}
+
+int blk_flush_all(void)
+{
+ BlockBackend *blk;
+ int result = 0;
+
+ QTAILQ_FOREACH(blk, &blk_backends, link) {
+ AioContext *aio_context = blk_get_aio_context(blk);
+ int ret;
+
+ aio_context_acquire(aio_context);
+ if (blk_is_inserted(blk)) {
+ ret = blk_flush(blk);
+ if (ret < 0 && !result) {
+ result = ret;
+ }
+ }
+ aio_context_release(aio_context);
+ }
+
+ return result;
}
void blk_invalidate_cache_all(Error **errp)
{
- bdrv_invalidate_cache_all(errp);
+ BlockBackend *blk;
+ Error *local_err = NULL;
+
+ QTAILQ_FOREACH(blk, &blk_backends, link) {
+ AioContext *aio_context = blk_get_aio_context(blk);
+
+ aio_context_acquire(aio_context);
+ if (blk_is_inserted(blk)) {
+ blk_invalidate_cache(blk, &local_err);
+ }
+ aio_context_release(aio_context);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
}
diff --git a/include/block/block.h b/include/block/block.h
index eadb25f..95f86f0 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -250,7 +250,6 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
int bdrv_commit(BlockDriverState *bs);
-int bdrv_commit_all(void);
int bdrv_change_backing_file(BlockDriverState *bs,
const char *backing_file, const char *backing_fmt);
void bdrv_register(BlockDriver *bdrv);
@@ -336,15 +335,12 @@ BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
/* Invalidate any cached metadata used by image formats */
void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp);
-void bdrv_invalidate_cache_all(Error **errp);
/* Ensure contents are flushed to disk. */
int bdrv_flush(BlockDriverState *bs);
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
-int bdrv_flush_all(void);
void bdrv_close_all(void);
void bdrv_drain(BlockDriverState *bs);
-void bdrv_drain_all(void);
int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors);
int bdrv_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors);
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 9169a09..04cd798 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -1,5 +1,5 @@
stub-obj-y += arch-query-cpu-def.o
-stub-obj-y += bdrv-commit-all.o
+stub-obj-y += blk-commit-all.o
stub-obj-y += blockdev-close-all-bdrv-states.o
stub-obj-y += chr-baum-init.o
stub-obj-y += chr-msmouse.o
diff --git a/stubs/bdrv-commit-all.c b/stubs/bdrv-commit-all.c
deleted file mode 100644
index a8e0a95..0000000
--- a/stubs/bdrv-commit-all.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "qemu-common.h"
-#include "block/block.h"
-
-int bdrv_commit_all(void)
-{
- return 0;
-}
diff --git a/stubs/blk-commit-all.c b/stubs/blk-commit-all.c
new file mode 100644
index 0000000..90b59e5
--- /dev/null
+++ b/stubs/blk-commit-all.c
@@ -0,0 +1,7 @@
+#include "qemu-common.h"
+#include "sysemu/block-backend.h"
+
+int blk_commit_all(void)
+{
+ return 0;
+}
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 9/9] block: Remove bdrv_states
2015-02-24 16:23 [Qemu-devel] [PATCH 0/9] blockdev: Further BlockBackend work Max Reitz
` (7 preceding siblings ...)
2015-02-24 16:23 ` [Qemu-devel] [PATCH 8/9] block: Move some bdrv_*_all() functions to BB Max Reitz
@ 2015-02-24 16:23 ` Max Reitz
8 siblings, 0 replies; 10+ messages in thread
From: Max Reitz @ 2015-02-24 16:23 UTC (permalink / raw)
To: qemu-block, qemu-devel
Cc: Kevin Wolf, Markus Armbruster, Stefan Hajnoczi, Max Reitz
Every entry in this list should be a root BDS and as such either be
anchored to a BlockBackend or be owned by the monitor.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block.c | 21 +--------------------
include/block/block.h | 1 -
include/block/block_int.h | 2 --
3 files changed, 1 insertion(+), 23 deletions(-)
diff --git a/block.c b/block.c
index dc24398..f0d22fe 100644
--- a/block.c
+++ b/block.c
@@ -88,9 +88,6 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque);
static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags);
-static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
- QTAILQ_HEAD_INITIALIZER(bdrv_states);
-
static QTAILQ_HEAD(, BlockDriverState) graph_bdrv_states =
QTAILQ_HEAD_INITIALIZER(graph_bdrv_states);
@@ -357,10 +354,7 @@ void bdrv_register(BlockDriver *bdrv)
BlockDriverState *bdrv_new_root(void)
{
- BlockDriverState *bs = bdrv_new();
-
- QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
- return bs;
+ return bdrv_new();
}
BlockDriverState *bdrv_new(void)
@@ -1999,17 +1993,6 @@ void bdrv_drain(BlockDriverState *bs)
Also, NULL terminate the device_name to prevent double remove */
void bdrv_make_anon(BlockDriverState *bs)
{
- /*
- * Take care to remove bs from bdrv_states only when it's actually
- * in it. Note that bs->device_list.tqe_prev is initially null,
- * and gets set to non-null by QTAILQ_INSERT_TAIL(). Establish
- * the useful invariant "bs in bdrv_states iff bs->tqe_prev" by
- * resetting it to null on remove.
- */
- if (bs->device_list.tqe_prev) {
- QTAILQ_REMOVE(&bdrv_states, bs, device_list);
- bs->device_list.tqe_prev = NULL;
- }
if (bs->node_name[0] != '\0') {
QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list);
}
@@ -2050,8 +2033,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
/* job */
bs_dest->job = bs_src->job;
- /* keep the same entry in bdrv_states */
- bs_dest->device_list = bs_src->device_list;
/* keep the same entry in the list of monitor-owned BDS */
bs_dest->monitor_list = bs_src->monitor_list;
diff --git a/include/block/block.h b/include/block/block.h
index 95f86f0..698dc02 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -372,7 +372,6 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
Error **errp);
bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base);
BlockDriverState *bdrv_next_node(BlockDriverState *bs);
-BlockDriverState *bdrv_next(BlockDriverState *bs);
int bdrv_is_encrypted(BlockDriverState *bs);
int bdrv_key_required(BlockDriverState *bs);
int bdrv_set_key(BlockDriverState *bs, const char *key);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index d839a8a..8754b35 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -397,8 +397,6 @@ struct BlockDriverState {
char node_name[32];
/* element of the list of named nodes building the graph */
QTAILQ_ENTRY(BlockDriverState) node_list;
- /* element of the list of "drives" the guest sees */
- QTAILQ_ENTRY(BlockDriverState) device_list;
/* element of the list of monitor-owned BDS */
QTAILQ_ENTRY(BlockDriverState) monitor_list;
QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
--
2.1.0
^ permalink raw reply related [flat|nested] 10+ messages in thread