All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe
@ 2014-09-10  8:13 Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new() Markus Armbruster
                   ` (23 more replies)
  0 siblings, 24 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

My last attempt got bogged down because I tried to do a reasonably
complete job, and the complexity proved more than I could handle with
the limited amount of uninterrupted time available.  This time, I'm
cutting BlockBackend off with an axe, leaving most of the work for
later.

Done in this series already:

* Introduce a BlockBackend type, and lift up BlockDriverState's
  device_name, device_list, dev, dev_ops, dev_opaque.  Much more
  remains to be lifted.

* Make BlockBackend own the DriveInfo.

* Wean hw/ off BlockDriverState, with two small exceptions.

* Fix blockdev-add not to create a bogus IDE drive (0,0).

* Take a few baby steps towards use of BlockBackend in monitor command
  code where appropriate.

Coming soon, hopefully:

* QMP command blockdev-del

* blockdev-add accepts node-name without id at top level

* Lift up more stuff

* More monitor command code BlockBackend use

Depends on my [PATCH 0/4] Block-related miscellaneous cleanups.

I know the diffstat looks intimidating.  I tried very hard to split
the patches so that the bigger ones do just one simple thing, and
mostly mechanically.

Markus Armbruster (23):
  block: Split bdrv_new_named() off bdrv_new()
  block: New BlockBackend
  block: Connect BlockBackend to BlockDriverState
  block: Connect BlockBackend and DriveInfo
  block: Make BlockBackend own its BlockDriverState
  block: Eliminate bdrv_states, use block_next() instead
  block: Eliminate bdrv_iterate(), use bdrv_next()
  block: Eliminate BlockDriverState member device_name[]
  block: Merge BlockBackend and BlockDriverState name spaces
  block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
  block: Rename BlockDriverAIOCB* to BlockAIOCB*
  virtio-blk: Drop redundant VirtIOBlock member conf
  virtio-blk: Rename VirtIOBlkConf variables to conf
  hw: Convert from BlockDriverState to BlockBackend, mostly
  ide: Complete conversion from BlockDriverState to BlockBackend
  pc87312: Drop unused members of PC87312State
  blockdev: Drop superfluous DriveInfo member id
  blockdev: Fix blockdev-add not to create IDE drive (0,0)
  blockdev: Drop DriveInfo member enable_auto_del
  block/qapi: Convert qmp_query_block() to BlockBackend
  blockdev: Convert qmp_eject(), qmp_change_blockdev() to BlockBackend
  block: Lift device model API into BlockBackend
  block: Make device model's references to BlockBackend strong

 block-migration.c                        |  44 +--
 block.c                                  | 389 +++++++-------------
 block/Makefile.objs                      |   2 +-
 block/archipelago.c                      |  30 +-
 block/backup.c                           |   2 +-
 block/blkdebug.c                         |  22 +-
 block/blkverify.c                        |  20 +-
 block/block-backend.c                    | 588 +++++++++++++++++++++++++++++++
 block/commit.c                           |   2 +-
 block/cow.c                              |   2 +-
 block/curl.c                             |   8 +-
 block/iscsi.c                            |  10 +-
 block/linux-aio.c                        |   8 +-
 block/mirror.c                           |   9 +-
 block/qapi.c                             |  27 +-
 block/qcow.c                             |   4 +-
 block/qcow2.c                            |   4 +-
 block/qed-gencb.c                        |   4 +-
 block/qed-table.c                        |  10 +-
 block/qed.c                              |  48 +--
 block/qed.h                              |  12 +-
 block/quorum.c                           |  42 +--
 block/raw-aio.h                          |   8 +-
 block/raw-posix.c                        |  32 +-
 block/raw-win32.c                        |  16 +-
 block/raw_bsd.c                          |   8 +-
 block/rbd.c                              |  58 +--
 block/sheepdog.c                         |   4 +-
 block/stream.c                           |   2 +-
 block/vdi.c                              |   2 +-
 block/vhdx.c                             |   2 +-
 block/vmdk.c                             |   4 +-
 block/vpc.c                              |   2 +-
 block/vvfat.c                            |   4 +-
 block/win32-aio.c                        |   8 +-
 blockdev.c                               | 204 +++++------
 blockjob.c                               |   7 +-
 dma-helpers.c                            |  69 ++--
 hw/arm/collie.c                          |  10 +-
 hw/arm/gumstix.c                         |   6 +-
 hw/arm/highbank.c                        |   2 +-
 hw/arm/mainstone.c                       |   8 +-
 hw/arm/musicpal.c                        |  13 +-
 hw/arm/nseries.c                         |   7 +-
 hw/arm/omap1.c                           |   4 +-
 hw/arm/omap2.c                           |   4 +-
 hw/arm/omap_sx1.c                        |  10 +-
 hw/arm/pxa2xx.c                          |   7 +-
 hw/arm/realview.c                        |   2 +-
 hw/arm/spitz.c                           |   6 +-
 hw/arm/tosa.c                            |   3 +-
 hw/arm/versatilepb.c                     |   5 +-
 hw/arm/vexpress.c                        |   5 +-
 hw/arm/xilinx_zynq.c                     |   5 +-
 hw/arm/z2.c                              |   8 +-
 hw/block/block.c                         |  23 +-
 hw/block/dataplane/virtio-blk.c          |  35 +-
 hw/block/dataplane/virtio-blk.h          |   2 +-
 hw/block/fdc.c                           |  74 ++--
 hw/block/hd-geometry.c                   |  24 +-
 hw/block/m25p80.c                        |  31 +-
 hw/block/nand.c                          |  50 +--
 hw/block/nvme.c                          |  17 +-
 hw/block/nvme.h                          |   2 +-
 hw/block/onenand.c                       |  67 ++--
 hw/block/pflash_cfi01.c                  |  24 +-
 hw/block/pflash_cfi02.c                  |  24 +-
 hw/block/virtio-blk.c                    | 149 ++++----
 hw/block/xen_disk.c                      |  86 +++--
 hw/core/qdev-properties-system.c         |  26 +-
 hw/core/qdev-properties.c                |   2 +-
 hw/cris/axis_dev88.c                     |   4 +-
 hw/display/tc6393xb.c                    |   4 +-
 hw/i386/pc.c                             |   2 +-
 hw/i386/pc_piix.c                        |   2 +-
 hw/i386/pc_sysfw.c                       |  10 +-
 hw/i386/xen/xen_platform.c               |   5 +-
 hw/ide/ahci.c                            |  33 +-
 hw/ide/ahci.h                            |   2 +-
 hw/ide/atapi.c                           |  33 +-
 hw/ide/cmd646.c                          |   2 +-
 hw/ide/core.c                            | 206 ++++++-----
 hw/ide/ich.c                             |   2 +-
 hw/ide/internal.h                        |  16 +-
 hw/ide/isa.c                             |   2 +-
 hw/ide/macio.c                           |  54 +--
 hw/ide/microdrive.c                      |   4 +-
 hw/ide/mmio.c                            |   2 +-
 hw/ide/pci.c                             |   6 +-
 hw/ide/pci.h                             |   2 +-
 hw/ide/piix.c                            |   9 +-
 hw/ide/qdev.c                            |  13 +-
 hw/ide/via.c                             |   2 +-
 hw/isa/pc87312.c                         |   7 +-
 hw/lm32/lm32_boards.c                    |  14 +-
 hw/lm32/milkymist.c                      |   8 +-
 hw/microblaze/petalogix_ml605_mmu.c      |   6 +-
 hw/microblaze/petalogix_s3adsp1800_mmu.c |   6 +-
 hw/mips/mips_fulong2e.c                  |   2 +-
 hw/mips/mips_jazz.c                      |   2 +-
 hw/mips/mips_malta.c                     |   8 +-
 hw/mips/mips_r4k.c                       |   6 +-
 hw/nvram/spapr_nvram.c                   |  17 +-
 hw/pci/pci-hotplug-old.c                 |  10 +-
 hw/ppc/mac.h                             |   2 +-
 hw/ppc/mac_newworld.c                    |   2 +-
 hw/ppc/mac_oldworld.c                    |   2 +-
 hw/ppc/ppc405_boards.c                   |  27 +-
 hw/ppc/prep.c                            |   2 +-
 hw/ppc/spapr.c                           |   4 +-
 hw/ppc/virtex_ml507.c                    |   6 +-
 hw/s390x/s390-virtio-bus.c               |   2 +-
 hw/s390x/s390-virtio.c                   |   2 +-
 hw/s390x/virtio-ccw.c                    |   2 +-
 hw/scsi/megasas.c                        |  15 +-
 hw/scsi/scsi-bus.c                       |  11 +-
 hw/scsi/scsi-disk.c                      | 194 +++++-----
 hw/scsi/scsi-generic.c                   |  41 ++-
 hw/sd/milkymist-memcard.c                |   7 +-
 hw/sd/omap_mmc.c                         |   8 +-
 hw/sd/pl181.c                            |   3 +-
 hw/sd/pxa2xx_mmci.c                      |   4 +-
 hw/sd/sd.c                               |  60 ++--
 hw/sd/sdhci.c                            |   3 +-
 hw/sd/ssi-sd.c                           |   3 +-
 hw/sh4/r2d.c                             |   6 +-
 hw/sparc/sun4m.c                         |   2 +-
 hw/sparc64/sun4u.c                       |   2 +-
 hw/tpm/tpm_tis.c                         |   2 +-
 hw/tricore/tricore_testboard.c           |   2 +-
 hw/usb/dev-storage.c                     |  19 +-
 hw/virtio/virtio-pci.c                   |   2 +-
 hw/xen/xen_devconfig.c                   |   1 +
 hw/xenpv/xen_machine_pv.c                |   2 +-
 hw/xtensa/xtfpga.c                       |   5 +-
 include/block/aio.h                      |  12 +-
 include/block/block.h                    |  87 ++---
 include/block/block_int.h                |  46 +--
 include/block/blockjob.h                 |   4 +-
 include/block/qapi.h                     |   3 -
 include/block/thread-pool.h              |   4 +-
 include/hw/arm/omap.h                    |   4 +-
 include/hw/arm/pxa.h                     |   2 +-
 include/hw/block/block.h                 |   6 +-
 include/hw/block/flash.h                 |   6 +-
 include/hw/isa/pc87312.h                 |   3 -
 include/hw/qdev-properties.h             |   8 +-
 include/hw/scsi/scsi.h                   |   6 +-
 include/hw/sd.h                          |   2 +-
 include/hw/virtio/virtio-blk.h           |   9 +-
 include/monitor/monitor.h                |   4 +-
 include/qemu/typedefs.h                  |   2 +
 include/sysemu/block-backend.h           | 144 ++++++++
 include/sysemu/blockdev.h                |  12 +-
 include/sysemu/dma.h                     |  26 +-
 monitor.c                                |  39 +-
 qemu-img.c                               | 150 ++++----
 qemu-io.c                                |  15 +-
 qemu-nbd.c                               |   4 +-
 tests/test-thread-pool.c                 |   2 +-
 thread-pool.c                            |   8 +-
 trace-events                             |   8 +-
 162 files changed, 2317 insertions(+), 1701 deletions(-)
 create mode 100644 block/block-backend.c
 create mode 100644 include/sysemu/block-backend.h

-- 
1.9.3

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new()
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10 11:03   ` Benoît Canet
                     ` (4 more replies)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 02/23] block: New BlockBackend Markus Armbruster
                   ` (22 subsequent siblings)
  23 siblings, 5 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Creating an anonymous BDS can't fail.  Make that obvious.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block.c               | 26 +++++++++++++++++++-------
 block/iscsi.c         |  2 +-
 block/vvfat.c         |  2 +-
 blockdev.c            |  2 +-
 hw/block/xen_disk.c   |  2 +-
 include/block/block.h |  3 ++-
 qemu-img.c            |  6 +++---
 qemu-io.c             |  2 +-
 qemu-nbd.c            |  2 +-
 9 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/block.c b/block.c
index d06dd51..4b3bcd4 100644
--- a/block.c
+++ b/block.c
@@ -335,10 +335,11 @@ void bdrv_register(BlockDriver *bdrv)
 }
 
 /* create a new block device (by default it is empty) */
-BlockDriverState *bdrv_new(const char *device_name, Error **errp)
+BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
 {
     BlockDriverState *bs;
-    int i;
+
+    assert(*device_name);
 
     if (bdrv_find(device_name)) {
         error_setg(errp, "Device with id '%s' already exists",
@@ -351,12 +352,23 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
         return NULL;
     }
 
-    bs = g_new0(BlockDriverState, 1);
-    QLIST_INIT(&bs->dirty_bitmaps);
+    bs = bdrv_new();
+
     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
     if (device_name[0] != '\0') {
         QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
     }
+
+    return bs;
+}
+
+BlockDriverState *bdrv_new(void)
+{
+    BlockDriverState *bs;
+    int i;
+
+    bs = g_new0(BlockDriverState, 1);
+    QLIST_INIT(&bs->dirty_bitmaps);
     for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
         QLIST_INIT(&bs->op_blockers[i]);
     }
@@ -1217,7 +1229,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
         goto free_exit;
     }
 
-    backing_hd = bdrv_new("", errp);
+    backing_hd = bdrv_new();
 
     if (bs->backing_format[0] != '\0') {
         back_drv = bdrv_find_format(bs->backing_format);
@@ -1346,7 +1358,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
     qdict_put(snapshot_options, "file.filename",
               qstring_from_str(tmp_filename));
 
-    bs_snapshot = bdrv_new("", &error_abort);
+    bs_snapshot = bdrv_new();
 
     ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
                     flags, bdrv_qcow2, &local_err);
@@ -1417,7 +1429,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
     if (*pbs) {
         bs = *pbs;
     } else {
-        bs = bdrv_new("", &error_abort);
+        bs = bdrv_new();
     }
 
     /* NULL means an empty set of options */
diff --git a/block/iscsi.c b/block/iscsi.c
index 3e19202..af3d0f6 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1528,7 +1528,7 @@ static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
     IscsiLun *iscsilun = NULL;
     QDict *bs_options;
 
-    bs = bdrv_new("", &error_abort);
+    bs = bdrv_new();
 
     /* Read out options */
     total_size =
diff --git a/block/vvfat.c b/block/vvfat.c
index 731e591..6c9fde0 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2939,7 +2939,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
     unlink(s->qcow_filename);
 #endif
 
-    bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort));
+    bdrv_set_backing_hd(s->bs, bdrv_new());
     s->bs->backing_hd->drv = &vvfat_write_target;
     s->bs->backing_hd->opaque = g_new(void *, 1);
     *(void**)s->bs->backing_hd->opaque = s;
diff --git a/blockdev.c b/blockdev.c
index e919566..9fbd888 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -458,7 +458,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     /* init */
     dinfo = g_malloc0(sizeof(*dinfo));
     dinfo->id = g_strdup(qemu_opts_id(opts));
-    dinfo->bdrv = bdrv_new(dinfo->id, &error);
+    dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
     if (error) {
         error_propagate(errp, error);
         goto bdrv_new_err;
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 2dcef07..8bac7ff 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -856,7 +856,7 @@ static int blk_connect(struct XenDevice *xendev)
 
         /* setup via xenbus -> create new block driver instance */
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
-        blkdev->bs = bdrv_new(blkdev->dev, NULL);
+        blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
         if (!blkdev->bs) {
             return -1;
         }
diff --git a/include/block/block.h b/include/block/block.h
index 8f4ad16..95139c0 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -203,7 +203,8 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
 int bdrv_create(BlockDriver *drv, const char* filename,
                 QemuOpts *opts, Error **errp);
 int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
-BlockDriverState *bdrv_new(const char *device_name, Error **errp);
+BlockDriverState *bdrv_new_named(const char *device_name, Error **errp);
+BlockDriverState *bdrv_new(void);
 void bdrv_make_anon(BlockDriverState *bs);
 void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
 void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
diff --git a/qemu-img.c b/qemu-img.c
index 91d1ac3..4490a22 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -296,7 +296,7 @@ static BlockDriverState *bdrv_new_open(const char *id,
     Error *local_err = NULL;
     int ret;
 
-    bs = bdrv_new(id, &error_abort);
+    bs = bdrv_new_named(id, &error_abort);
 
     if (fmt) {
         drv = bdrv_find_format(fmt);
@@ -2425,7 +2425,7 @@ static int img_rebase(int argc, char **argv)
     if (!unsafe) {
         char backing_name[1024];
 
-        bs_old_backing = bdrv_new("old_backing", &error_abort);
+        bs_old_backing = bdrv_new_named("old_backing", &error_abort);
         bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
         ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
                         old_backing_drv, &local_err);
@@ -2436,7 +2436,7 @@ static int img_rebase(int argc, char **argv)
             goto out;
         }
         if (out_baseimg[0]) {
-            bs_new_backing = bdrv_new("new_backing", &error_abort);
+            bs_new_backing = bdrv_new_named("new_backing", &error_abort);
             ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
                             new_backing_drv, &local_err);
             if (ret) {
diff --git a/qemu-io.c b/qemu-io.c
index d2ab694..44c2e1c 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -58,7 +58,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
         return 1;
     }
 
-    qemuio_bs = bdrv_new("hda", &error_abort);
+    qemuio_bs = bdrv_new_named("hda", &error_abort);
 
     if (growable) {
         flags |= BDRV_O_PROTOCOL;
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 9bc152e..a56ebfc 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -687,7 +687,7 @@ int main(int argc, char **argv)
         drv = NULL;
     }
 
-    bs = bdrv_new("hda", &error_abort);
+    bs = bdrv_new_named("hda", &error_abort);
 
     srcpath = argv[optind];
     ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new() Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  9:56   ` Kevin Wolf
                     ` (2 more replies)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState Markus Armbruster
                   ` (21 subsequent siblings)
  23 siblings, 3 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

A block device consists of a frontend device model and a backend.

A block backend has a tree of block drivers doing the actual work.
The tree is managed by the block layer.

We currently use a single abstraction BlockDriverState both for tree
nodes and the backend as a whole.  Drawbacks:

* Its API includes both stuff that makes sense only at the block
  backend level (root of the tree) and stuff that's only for use
  within the block layer.  This makes the API bigger and more complex
  than necessary.  Moreover, it's not obvious which interfaces are
  meant for device models, and which really aren't.

* Since device models keep a reference to their backend, the backend
  object can't just be destroyed.  But for media change, we need to
  replace the tree.  Our solution is to make the BlockDriverState
  generic, with actual driver state in a separate object, pointed to
  by member opaque.  That lets us replace the tree by deinitializing
  and reinitializing its root.  This special need of the root makes
  the data structure awkward everywhere in the tree.

The general plan is to separate the APIs into "block backend", for use
by device models, monitor and whatever other code dealing with block
backends, and "block driver", for use by the block layer and whatever
other code (if any) dealing with trees and tree nodes.

Code dealing with block backends, device models in particular, should
become completely oblivious of BlockDriverState.  This should let us
clean up both APIs, and the tree data structures.

This commit is a first step.  It creates a minimal "block backend"
API: type BlockBackend and functions to create, destroy and find them.
BlockBackend objects are created and destroyed, but not yet used for
anything; that'll come shortly.

BlockBackend is reference-counted.  Its reference count never exceeds
one so far, but that's going to change.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block/Makefile.objs            |   2 +-
 block/block-backend.c          | 110 +++++++++++++++++++++++++++++++++++++++++
 blockdev.c                     |  10 +++-
 hw/block/xen_disk.c            |  11 +++++
 include/qemu/typedefs.h        |   1 +
 include/sysemu/block-backend.h |  26 ++++++++++
 qemu-img.c                     |  46 +++++++++++++++++
 qemu-io.c                      |   8 +++
 qemu-nbd.c                     |   3 +-
 9 files changed, 214 insertions(+), 3 deletions(-)
 create mode 100644 block/block-backend.c
 create mode 100644 include/sysemu/block-backend.h

diff --git a/block/Makefile.objs b/block/Makefile.objs
index f45f939..a70140b 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -5,7 +5,7 @@ block-obj-y += qed-check.o
 block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
 block-obj-$(CONFIG_QUORUM) += quorum.o
 block-obj-y += parallels.o blkdebug.o blkverify.o
-block-obj-y += snapshot.o qapi.o
+block-obj-y += block-backend.o snapshot.o qapi.o
 block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
 block-obj-$(CONFIG_POSIX) += raw-posix.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
diff --git a/block/block-backend.c b/block/block-backend.c
new file mode 100644
index 0000000..833f7d9
--- /dev/null
+++ b/block/block-backend.c
@@ -0,0 +1,110 @@
+/*
+ * QEMU Block backends
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * Authors:
+ *  Markus Armbruster <armbru@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "sysemu/block-backend.h"
+#include "block/block_int.h"
+
+struct BlockBackend {
+    char *name;
+    int refcnt;
+    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
+};
+
+static QTAILQ_HEAD(, BlockBackend) blk_backends =
+    QTAILQ_HEAD_INITIALIZER(blk_backends);
+
+/**
+ * blk_new:
+ * @name: name, must not be %NULL or empty
+ * @errp: return location for an error to be set on failure, or %NULL
+ *
+ * Create a new BlockBackend, with a reference count of one.  Fail if
+ * @name already exists.
+ *
+ * Returns: the BlockBackend on success, %NULL on failure
+ */
+BlockBackend *blk_new(const char *name, Error **errp)
+{
+    BlockBackend *blk = g_new0(BlockBackend, 1);
+
+    assert(name && name[0]);
+    if (blk_by_name(name)) {
+        error_setg(errp, "Device with id '%s' already exists", name);
+        return NULL;
+    }
+    blk->name = g_strdup(name);
+    blk->refcnt = 1;
+    QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
+    return blk;
+}
+
+static void blk_delete(BlockBackend *blk)
+{
+    assert(!blk->refcnt);
+    QTAILQ_REMOVE(&blk_backends, blk, link);
+    g_free(blk->name);
+    g_free(blk);
+}
+
+/**
+ * blk_ref:
+ *
+ * Increment @blk's reference count.
+ */
+void blk_ref(BlockBackend *blk)
+{
+    blk->refcnt++;
+}
+
+/**
+ * blk_unref:
+ *
+ * Decrement @blk's reference count.  If this drops it to zero,
+ * destroy @blk.
+ */
+void blk_unref(BlockBackend *blk)
+{
+    if (blk) {
+        g_assert(blk->refcnt > 0);
+        if (!--blk->refcnt) {
+            blk_delete(blk);
+        }
+    }
+}
+
+const char *blk_name(BlockBackend *blk)
+{
+    return blk->name;
+}
+
+BlockBackend *blk_by_name(const char *name)
+{
+    BlockBackend *blk;
+
+    QTAILQ_FOREACH(blk, &blk_backends, link) {
+        if (!strcmp(name, blk->name)) {
+            return blk;
+        }
+    }
+    return NULL;
+}
+
+/**
+ * blk_next:
+ *
+ * Returns: the first BlockBackend if @blk is null, else @blk's next
+ * sibling, which is %NULL for the last BlockBackend
+ */
+BlockBackend *blk_next(BlockBackend *blk)
+{
+    return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
+}
diff --git a/blockdev.c b/blockdev.c
index 9fbd888..86596bc 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -30,6 +30,7 @@
  * THE SOFTWARE.
  */
 
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/block/block.h"
 #include "block/blockjob.h"
@@ -221,6 +222,7 @@ void drive_del(DriveInfo *dinfo)
     }
 
     bdrv_unref(dinfo->bdrv);
+    blk_unref(blk_by_name(dinfo->id));
     g_free(dinfo->id);
     QTAILQ_REMOVE(&drives, dinfo, next);
     g_free(dinfo->serial);
@@ -301,6 +303,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     int ro = 0;
     int bdrv_flags = 0;
     int on_read_error, on_write_error;
+    BlockBackend *blk;
     DriveInfo *dinfo;
     ThrottleConfig cfg;
     int snapshot = 0;
@@ -456,6 +459,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     }
 
     /* init */
+    blk = blk_new(qemu_opts_id(opts), errp);
+    if (!blk) {
+        goto early_err;
+    }
     dinfo = g_malloc0(sizeof(*dinfo));
     dinfo->id = g_strdup(qemu_opts_id(opts));
     dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
@@ -525,6 +532,7 @@ err:
 bdrv_new_err:
     g_free(dinfo->id);
     g_free(dinfo);
+    blk_unref(blk);
 early_err:
     qemu_opts_del(opts);
 err_no_opts:
@@ -1770,7 +1778,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
      */
     if (bdrv_get_attached_dev(bs)) {
         bdrv_make_anon(bs);
-
+        blk_unref(blk_by_name(id));
         /* Further I/O must not pause the guest */
         bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
                           BLOCKDEV_ON_ERROR_REPORT);
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 8bac7ff..730a021 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -39,6 +39,7 @@
 #include "hw/xen/xen_backend.h"
 #include "xen_blkif.h"
 #include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 
 /* ------------------------------------------------------------- */
 
@@ -852,12 +853,18 @@ static int blk_connect(struct XenDevice *xendev)
     blkdev->dinfo = drive_get(IF_XEN, 0, index);
     if (!blkdev->dinfo) {
         Error *local_err = NULL;
+        BlockBackend *blk;
         BlockDriver *drv;
 
         /* setup via xenbus -> create new block driver instance */
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
+        blk = blk_new(blkdev->dev, NULL);
+        if (!blk) {
+            return -1;
+        }
         blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
         if (!blkdev->bs) {
+            blk_unref(blk);
             return -1;
         }
 
@@ -868,6 +875,7 @@ static int blk_connect(struct XenDevice *xendev)
                           error_get_pretty(local_err));
             error_free(local_err);
             bdrv_unref(blkdev->bs);
+            blk_unref(blk);
             blkdev->bs = NULL;
             return -1;
         }
@@ -983,6 +991,9 @@ static void blk_disconnect(struct XenDevice *xendev)
     if (blkdev->bs) {
         bdrv_detach_dev(blkdev->bs, blkdev);
         bdrv_unref(blkdev->bs);
+        if (!blkdev->dinfo) {
+            blk_unref(blk_by_name(blkdev->dev));
+        }
         blkdev->bs = NULL;
     }
     xen_be_unbind_evtchn(&blkdev->xendev);
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 5f20b0e..198da2e 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -35,6 +35,7 @@ typedef struct MachineClass MachineClass;
 typedef struct NICInfo NICInfo;
 typedef struct HCIInfo HCIInfo;
 typedef struct AudioState AudioState;
+typedef struct BlockBackend BlockBackend;
 typedef struct BlockDriverState BlockDriverState;
 typedef struct DriveInfo DriveInfo;
 typedef struct DisplayState DisplayState;
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
new file mode 100644
index 0000000..3f8371c
--- /dev/null
+++ b/include/sysemu/block-backend.h
@@ -0,0 +1,26 @@
+/*
+ * QEMU Block backends
+ *
+ * Copyright (C) 2014 Red Hat, Inc.
+ *
+ * Authors:
+ *  Markus Armbruster <armbru@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#ifndef BLOCK_BACKEND_H
+#define BLOCK_BACKEND_H
+
+#include "qemu/typedefs.h"
+#include "qapi/error.h"
+
+BlockBackend *blk_new(const char *name, Error **errp);
+void blk_ref(BlockBackend *blk);
+void blk_unref(BlockBackend *blk);
+const char *blk_name(BlockBackend *blk);
+BlockBackend *blk_by_name(const char *name);
+BlockBackend *blk_next(BlockBackend *blk);
+
+#endif
diff --git a/qemu-img.c b/qemu-img.c
index 4490a22..bad3f64 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -29,6 +29,7 @@
 #include "qemu/error-report.h"
 #include "qemu/osdep.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
 #include "block/block_int.h"
 #include "block/qapi.h"
 #include <getopt.h>
@@ -575,6 +576,7 @@ static int img_check(int argc, char **argv)
     int c, ret;
     OutputFormat output_format = OFORMAT_HUMAN;
     const char *filename, *fmt, *output, *cache;
+    BlockBackend *blk;
     BlockDriverState *bs;
     int fix = 0;
     int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
@@ -649,6 +651,7 @@ static int img_check(int argc, char **argv)
         return 1;
     }
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
         return 1;
@@ -710,6 +713,7 @@ static int img_check(int argc, char **argv)
 fail:
     qapi_free_ImageCheck(check);
     bdrv_unref(bs);
+    blk_unref(blk);
 
     return ret;
 }
@@ -718,6 +722,7 @@ static int img_commit(int argc, char **argv)
 {
     int c, ret, flags;
     const char *filename, *fmt, *cache;
+    BlockBackend *blk;
     BlockDriverState *bs;
     bool quiet = false;
 
@@ -756,6 +761,7 @@ static int img_commit(int argc, char **argv)
         return 1;
     }
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
         return 1;
@@ -780,6 +786,7 @@ static int img_commit(int argc, char **argv)
     }
 
     bdrv_unref(bs);
+    blk_unref(blk);
     if (ret) {
         return 1;
     }
@@ -942,6 +949,7 @@ static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
 static int img_compare(int argc, char **argv)
 {
     const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
+    BlockBackend *blk1, *blk2;
     BlockDriverState *bs1, *bs2;
     int64_t total_sectors1, total_sectors2;
     uint8_t *buf1 = NULL, *buf2 = NULL;
@@ -1011,6 +1019,7 @@ static int img_compare(int argc, char **argv)
         goto out3;
     }
 
+    blk1 = blk_new("image 1", &error_abort);
     bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
     if (!bs1) {
         error_report("Can't open file %s", filename1);
@@ -1018,6 +1027,7 @@ static int img_compare(int argc, char **argv)
         goto out3;
     }
 
+    blk2 = blk_new("image 2", &error_abort);
     bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
     if (!bs2) {
         error_report("Can't open file %s", filename2);
@@ -1184,10 +1194,12 @@ static int img_compare(int argc, char **argv)
 
 out:
     bdrv_unref(bs2);
+    blk_unref(blk2);
     qemu_vfree(buf1);
     qemu_vfree(buf2);
 out2:
     bdrv_unref(bs1);
+    blk_unref(blk1);
 out3:
     qemu_progress_end();
     return ret;
@@ -1200,6 +1212,7 @@ static int img_convert(int argc, char **argv)
     int progress = 0, flags, src_flags;
     const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
     BlockDriver *drv, *proto_drv;
+    BlockBackend **blk = NULL, *out_blk = NULL;
     BlockDriverState **bs = NULL, *out_bs = NULL;
     int64_t total_sectors, nb_sectors, sector_num, bs_offset;
     int64_t *bs_sectors = NULL;
@@ -1354,6 +1367,7 @@ static int img_convert(int argc, char **argv)
 
     qemu_progress_print(0, 100);
 
+    blk = g_new0(BlockBackend *, bs_n);
     bs = g_new0(BlockDriverState *, bs_n);
     bs_sectors = g_new(int64_t, bs_n);
 
@@ -1361,6 +1375,7 @@ static int img_convert(int argc, char **argv)
     for (bs_i = 0; bs_i < bs_n; bs_i++) {
         char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
                             : g_strdup("source");
+        blk[bs_i] = blk_new(id, &error_abort);
         bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
                                  true, quiet);
         g_free(id);
@@ -1486,6 +1501,7 @@ static int img_convert(int argc, char **argv)
         goto out;
     }
 
+    out_blk = blk_new("target", &error_abort);
     out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
     if (!out_bs) {
         ret = -1;
@@ -1742,6 +1758,7 @@ out:
     if (out_bs) {
         bdrv_unref(out_bs);
     }
+    blk_unref(out_blk);
     if (bs) {
         for (bs_i = 0; bs_i < bs_n; bs_i++) {
             if (bs[bs_i]) {
@@ -1750,6 +1767,12 @@ out:
         }
         g_free(bs);
     }
+    if (blk) {
+        for (bs_i = 0; bs_i < bs_n; bs_i++) {
+            blk_unref(blk[bs_i]);
+        }
+        g_free(blk);
+    }
     g_free(bs_sectors);
 fail_getopt:
     g_free(options);
@@ -1858,6 +1881,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
     filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
 
     while (filename) {
+        BlockBackend *blk;
         BlockDriverState *bs;
         ImageInfo *info;
         ImageInfoList *elem;
@@ -1869,6 +1893,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         }
         g_hash_table_insert(filenames, (gpointer)filename, NULL);
 
+        blk = blk_new("image", &error_abort);
         bs = bdrv_new_open("image", filename, fmt,
                            BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
         if (!bs) {
@@ -1880,6 +1905,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
             error_report("%s", error_get_pretty(err));
             error_free(err);
             bdrv_unref(bs);
+            blk_unref(blk);
             goto err;
         }
 
@@ -1889,6 +1915,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         last = &elem->next;
 
         bdrv_unref(bs);
+        blk_unref(blk);
 
         filename = fmt = NULL;
         if (chain) {
@@ -2082,6 +2109,7 @@ static int img_map(int argc, char **argv)
 {
     int c;
     OutputFormat output_format = OFORMAT_HUMAN;
+    BlockBackend *blk;
     BlockDriverState *bs;
     const char *filename, *fmt, *output;
     int64_t length;
@@ -2130,6 +2158,7 @@ static int img_map(int argc, char **argv)
         return 1;
     }
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
     if (!bs) {
         return 1;
@@ -2175,6 +2204,7 @@ static int img_map(int argc, char **argv)
 
 out:
     bdrv_unref(bs);
+    blk_unref(blk);
     return ret < 0;
 }
 
@@ -2185,6 +2215,7 @@ out:
 
 static int img_snapshot(int argc, char **argv)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     QEMUSnapshotInfo sn;
     char *filename, *snapshot_name = NULL;
@@ -2250,6 +2281,7 @@ static int img_snapshot(int argc, char **argv)
     filename = argv[optind++];
 
     /* Open the image */
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
     if (!bs) {
         return 1;
@@ -2297,6 +2329,7 @@ static int img_snapshot(int argc, char **argv)
 
     /* Cleanup */
     bdrv_unref(bs);
+    blk_unref(blk);
     if (ret) {
         return 1;
     }
@@ -2305,6 +2338,7 @@ static int img_snapshot(int argc, char **argv)
 
 static int img_rebase(int argc, char **argv)
 {
+    BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL;
     BlockDriverState *bs = NULL, *bs_old_backing = NULL, *bs_new_backing = NULL;
     BlockDriver *old_backing_drv, *new_backing_drv;
     char *filename;
@@ -2393,6 +2427,7 @@ static int img_rebase(int argc, char **argv)
      * Ignore the old backing file for unsafe rebase in case we want to correct
      * the reference to a renamed or moved backing file.
      */
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
         ret = -1;
@@ -2425,6 +2460,7 @@ static int img_rebase(int argc, char **argv)
     if (!unsafe) {
         char backing_name[1024];
 
+        blk_old_backing = blk_new("old_backing", &error_abort);
         bs_old_backing = bdrv_new_named("old_backing", &error_abort);
         bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
         ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
@@ -2436,6 +2472,7 @@ static int img_rebase(int argc, char **argv)
             goto out;
         }
         if (out_baseimg[0]) {
+            blk_new_backing = blk_new("new_backing", &error_abort);
             bs_new_backing = bdrv_new_named("new_backing", &error_abort);
             ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
                             new_backing_drv, &local_err);
@@ -2614,12 +2651,15 @@ out:
         if (bs_old_backing != NULL) {
             bdrv_unref(bs_old_backing);
         }
+        blk_unref(blk_old_backing);
         if (bs_new_backing != NULL) {
             bdrv_unref(bs_new_backing);
         }
+        blk_unref(blk_new_backing);
     }
 
     bdrv_unref(bs);
+    blk_unref(blk);
     if (ret) {
         return 1;
     }
@@ -2632,6 +2672,7 @@ static int img_resize(int argc, char **argv)
     const char *filename, *fmt, *size;
     int64_t n, total_size;
     bool quiet = false;
+    BlockBackend *blk = NULL;
     BlockDriverState *bs = NULL;
     QemuOpts *param;
     static QemuOptsList resize_options = {
@@ -2708,6 +2749,7 @@ static int img_resize(int argc, char **argv)
     n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
     qemu_opts_del(param);
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
                        true, quiet);
     if (!bs) {
@@ -2745,6 +2787,7 @@ out:
     if (bs) {
         bdrv_unref(bs);
     }
+    blk_unref(blk);
     if (ret) {
         return 1;
     }
@@ -2760,6 +2803,7 @@ static int img_amend(int argc, char **argv)
     const char *fmt = NULL, *filename, *cache;
     int flags;
     bool quiet = false;
+    BlockBackend *blk = NULL;
     BlockDriverState *bs = NULL;
 
     cache = BDRV_DEFAULT_CACHE;
@@ -2823,6 +2867,7 @@ static int img_amend(int argc, char **argv)
         goto out;
     }
 
+    blk = blk_new("image", &error_abort);
     bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
     if (!bs) {
         error_report("Could not open image '%s'", filename);
@@ -2856,6 +2901,7 @@ out:
     if (bs) {
         bdrv_unref(bs);
     }
+    blk_unref(blk);
     qemu_opts_del(opts);
     qemu_opts_free(create_opts);
     g_free(options);
diff --git a/qemu-io.c b/qemu-io.c
index 44c2e1c..45e5494 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -19,6 +19,7 @@
 #include "qemu/option.h"
 #include "qemu/config-file.h"
 #include "qemu/readline.h"
+#include "sysemu/block-backend.h"
 #include "block/block_int.h"
 #include "trace/control.h"
 
@@ -26,6 +27,7 @@
 
 static char *progname;
 
+static BlockBackend *qemuio_blk;
 static BlockDriverState *qemuio_bs;
 
 /* qemu-io commands passed using -c */
@@ -37,7 +39,9 @@ static ReadLineState *readline_state;
 static int close_f(BlockDriverState *bs, int argc, char **argv)
 {
     bdrv_unref(bs);
+    blk_unref(qemuio_blk);
     qemuio_bs = NULL;
+    qemuio_blk = NULL;
     return 0;
 }
 
@@ -58,6 +62,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
         return 1;
     }
 
+    qemuio_blk = blk_new("hda", &error_abort);
     qemuio_bs = bdrv_new_named("hda", &error_abort);
 
     if (growable) {
@@ -70,7 +75,9 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
                 error_get_pretty(local_err));
         error_free(local_err);
         bdrv_unref(qemuio_bs);
+        blk_unref(qemuio_blk);
         qemuio_bs = NULL;
+        qemuio_blk = NULL;
         return 1;
     }
 
@@ -479,6 +486,7 @@ int main(int argc, char **argv)
     if (qemuio_bs) {
         bdrv_unref(qemuio_bs);
     }
+    blk_unref(qemuio_blk);
     g_free(readline_state);
     return 0;
 }
diff --git a/qemu-nbd.c b/qemu-nbd.c
index a56ebfc..94b9b49 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -17,7 +17,7 @@
  */
 
 #include "qemu-common.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "block/block_int.h"
 #include "block/nbd.h"
 #include "qemu/main-loop.h"
@@ -687,6 +687,7 @@ int main(int argc, char **argv)
         drv = NULL;
     }
 
+    blk_new("hda", &error_abort);
     bs = bdrv_new_named("hda", &error_abort);
 
     srcpath = argv[optind];
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new() Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 02/23] block: New BlockBackend Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10 11:55   ` Benoît Canet
  2014-09-10 12:24   ` Kevin Wolf
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo Markus Armbruster
                   ` (20 subsequent siblings)
  23 siblings, 2 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

The pointer from BlockBackend to BlockDriverState is a strong
reference, managed with bdrv_ref() / bdrv_unref(), the back-pointer is
a weak one.

Convenience function blk_new_with_bs() creates a BlockBackend with its
BlockDriverState.  Callers have to unref both.  The commit after next
will relieve them of the need to unref the BlockDriverState.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block.c                        |  10 ++--
 block/block-backend.c          |  79 +++++++++++++++++++++++++++++++
 blockdev.c                     |  49 +++++++++++---------
 hw/block/xen_disk.c            |   8 +---
 include/block/block_int.h      |   2 +
 include/sysemu/block-backend.h |   5 ++
 qemu-img.c                     | 103 +++++++++++++++++++++--------------------
 qemu-io.c                      |   4 +-
 qemu-nbd.c                     |   3 +-
 9 files changed, 175 insertions(+), 88 deletions(-)

diff --git a/block.c b/block.c
index 4b3bcd4..a6c03da 100644
--- a/block.c
+++ b/block.c
@@ -2032,7 +2032,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
  * This will modify the BlockDriverState fields, and swap contents
  * between bs_new and bs_old. Both bs_new and bs_old are modified.
  *
- * bs_new is required to be anonymous.
+ * bs_new must be nameless and not attached to a BlockBackend.
  *
  * This function does not create any image files.
  */
@@ -2051,8 +2051,9 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
         QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list);
     }
 
-    /* bs_new must be anonymous and shouldn't have anything fancy enabled */
+    /* bs_new must be nameless and shouldn't have anything fancy enabled */
     assert(bs_new->device_name[0] == '\0');
+    assert(!bs_new->blk);
     assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
     assert(bs_new->job == NULL);
     assert(bs_new->dev == NULL);
@@ -2068,8 +2069,9 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
     bdrv_move_feature_fields(bs_old, bs_new);
     bdrv_move_feature_fields(bs_new, &tmp);
 
-    /* bs_new shouldn't be in bdrv_states even after the swap!  */
+    /* bs_new must remain nameless and unattached */
     assert(bs_new->device_name[0] == '\0');
+    assert(!bs_new->blk);
 
     /* Check a few fields that should remain attached to the device */
     assert(bs_new->dev == NULL);
@@ -2096,7 +2098,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
  * This will modify the BlockDriverState fields, and swap contents
  * between bs_new and bs_top. Both bs_new and bs_top are modified.
  *
- * bs_new is required to be anonymous.
+ * bs_new must be nameless and not attached to a BlockBackend.
  *
  * This function does not create any image files.
  */
diff --git a/block/block-backend.c b/block/block-backend.c
index 833f7d9..deccb54 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -16,6 +16,7 @@
 struct BlockBackend {
     char *name;
     int refcnt;
+    BlockDriverState *bs;
     QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
 };
 
@@ -47,9 +48,43 @@ BlockBackend *blk_new(const char *name, Error **errp)
     return blk;
 }
 
+/**
+ * blk_new_with_bs:
+ * @name: name, must not be %NULL or empty
+ * @errp: return location for an error to be set on failure, or %NULL
+ *
+ * Create a new BlockBackend, with a reference count of one, and
+ * attach a new BlockDriverState to it, also with a reference count of
+ * one.  Caller owns *both* references.
+ * TODO Let caller own only the BlockBackend reference
+ * Fail if @name already exists.
+ *
+ * Returns: the BlockBackend on success, %NULL on error
+ */
+BlockBackend *blk_new_with_bs(const char *name, Error **errp)
+{
+    BlockBackend *blk;
+    BlockDriverState *bs;
+
+    blk = blk_new(name, errp);
+    if (!blk) {
+        return NULL;
+    }
+
+    bs = bdrv_new_named(name, errp);
+    if (!bs) {
+        blk_unref(blk);
+        return NULL;
+    }
+
+    blk_attach_bs(blk, bs);
+    return blk;
+}
+
 static void blk_delete(BlockBackend *blk)
 {
     assert(!blk->refcnt);
+    blk_detach_bs(blk);
     QTAILQ_REMOVE(&blk_backends, blk, link);
     g_free(blk->name);
     g_free(blk);
@@ -70,6 +105,9 @@ void blk_ref(BlockBackend *blk)
  *
  * Decrement @blk's reference count.  If this drops it to zero,
  * destroy @blk.
+ *
+ * Does *not* touch the attached BlockDriverState's reference count.
+ * TODO Decrement it!
  */
 void blk_unref(BlockBackend *blk)
 {
@@ -108,3 +146,44 @@ BlockBackend *blk_next(BlockBackend *blk)
 {
     return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
 }
+
+/**
+ * blk_attach_bs:
+ *
+ * Attach @bs to @blk, taking over the caller's reference to @bs.
+ */
+void blk_attach_bs(BlockBackend *blk, BlockDriverState *bs)
+{
+    assert(!blk->bs && !bs->blk);
+    blk->bs = bs;
+    bs->blk = blk;
+}
+
+/**
+ * blk_bs:
+ *
+ * Returns: the BlockDriverState attached to @blk, or %NULL
+ */
+BlockDriverState *blk_bs(BlockBackend *blk)
+{
+    return blk->bs;
+}
+
+/**
+ * blk_detach_bs:
+ *
+ * Detach @blk's BlockDriverState, giving up its reference to the
+ * caller.
+ *
+ * Returns: the detached BlockDriverState
+ */
+BlockDriverState *blk_detach_bs(BlockBackend *blk)
+{
+    BlockDriverState *bs = blk->bs;
+
+    if (bs) {
+        bs->blk = NULL;
+        blk->bs = NULL;
+    }
+    return bs;
+}
diff --git a/blockdev.c b/blockdev.c
index 86596bc..0a0b95e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -304,6 +304,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     int bdrv_flags = 0;
     int on_read_error, on_write_error;
     BlockBackend *blk;
+    BlockDriverState *bs;
     DriveInfo *dinfo;
     ThrottleConfig cfg;
     int snapshot = 0;
@@ -459,30 +460,28 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     }
 
     /* init */
-    blk = blk_new(qemu_opts_id(opts), errp);
+    blk = blk_new_with_bs(qemu_opts_id(opts), errp);
     if (!blk) {
         goto early_err;
     }
+    bs = blk_bs(blk);
+    bs->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
+    bs->read_only = ro;
+    bs->detect_zeroes = detect_zeroes;
+
+    bdrv_set_on_error(bs, on_read_error, on_write_error);
+
+    /* disk I/O throttling */
+    if (throttle_enabled(&cfg)) {
+        bdrv_io_limits_enable(bs);
+        bdrv_set_io_limits(bs, &cfg);
+    }
+
     dinfo = g_malloc0(sizeof(*dinfo));
     dinfo->id = g_strdup(qemu_opts_id(opts));
-    dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
-    if (error) {
-        error_propagate(errp, error);
-        goto bdrv_new_err;
-    }
-    dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
-    dinfo->bdrv->read_only = ro;
-    dinfo->bdrv->detect_zeroes = detect_zeroes;
+    dinfo->bdrv = bs;
     QTAILQ_INSERT_TAIL(&drives, dinfo, next);
 
-    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
-
-    /* disk I/O throttling */
-    if (throttle_enabled(&cfg)) {
-        bdrv_io_limits_enable(dinfo->bdrv);
-        bdrv_set_io_limits(dinfo->bdrv, &cfg);
-    }
-
     if (!file || !*file) {
         if (has_driver_specific_opts) {
             file = NULL;
@@ -509,7 +508,8 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
 
     QINCREF(bs_opts);
-    ret = bdrv_open(&dinfo->bdrv, file, NULL, bs_opts, bdrv_flags, drv, &error);
+    ret = bdrv_open(&bs, file, NULL, bs_opts, bdrv_flags, drv, &error);
+    assert(bs == blk_bs(blk));
 
     if (ret < 0) {
         error_setg(errp, "could not open disk image %s: %s",
@@ -518,8 +518,9 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
         goto err;
     }
 
-    if (bdrv_key_required(dinfo->bdrv))
+    if (bdrv_key_required(bs)) {
         autostart = 0;
+    }
 
     QDECREF(bs_opts);
     qemu_opts_del(opts);
@@ -529,7 +530,6 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
 err:
     bdrv_unref(dinfo->bdrv);
     QTAILQ_REMOVE(&drives, dinfo, next);
-bdrv_new_err:
     g_free(dinfo->id);
     g_free(dinfo);
     blk_unref(blk);
@@ -1746,15 +1746,17 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
 int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
     const char *id = qdict_get_str(qdict, "id");
+    BlockBackend *blk;
     BlockDriverState *bs;
     AioContext *aio_context;
     Error *local_err = NULL;
 
-    bs = bdrv_find(id);
-    if (!bs) {
+    blk = blk_by_name(id);
+    if (!blk) {
         error_report("Device '%s' not found", id);
         return -1;
     }
+    bs = blk_bs(blk);
 
     aio_context = bdrv_get_aio_context(bs);
     aio_context_acquire(aio_context);
@@ -1777,8 +1779,9 @@ 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 (bdrv_get_attached_dev(bs)) {
+        blk_detach_bs(blk);
+        blk_unref(blk);
         bdrv_make_anon(bs);
-        blk_unref(blk_by_name(id));
         /* Further I/O must not pause the guest */
         bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
                           BLOCKDEV_ON_ERROR_REPORT);
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 730a021..51f4f3a 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -858,15 +858,11 @@ static int blk_connect(struct XenDevice *xendev)
 
         /* setup via xenbus -> create new block driver instance */
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
-        blk = blk_new(blkdev->dev, NULL);
+        blk = blk_new_with_bs(blkdev->dev, NULL);
         if (!blk) {
             return -1;
         }
-        blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
-        if (!blkdev->bs) {
-            blk_unref(blk);
-            return -1;
-        }
+        blkdev->bs = blk_bs(blk);
 
         drv = bdrv_find_whitelisted_format(blkdev->fileproto, readonly);
         if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 8a61215..a04c852 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -323,6 +323,8 @@ struct BlockDriverState {
     BlockDriver *drv; /* NULL means no media */
     void *opaque;
 
+    BlockBackend *blk;          /* owning backend, if any */
+
     void *dev;                  /* attached device model, if any */
     /* TODO change to DeviceState when all users are qdevified */
     const BlockDevOps *dev_ops;
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 3f8371c..539b96f 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -17,10 +17,15 @@
 #include "qapi/error.h"
 
 BlockBackend *blk_new(const char *name, Error **errp);
+BlockBackend *blk_new_with_bs(const char *name, Error **errp);
 void blk_ref(BlockBackend *blk);
 void blk_unref(BlockBackend *blk);
 const char *blk_name(BlockBackend *blk);
 BlockBackend *blk_by_name(const char *name);
 BlockBackend *blk_next(BlockBackend *blk);
 
+void blk_attach_bs(BlockBackend *blk, BlockDriverState *bs);
+BlockDriverState *blk_detach_bs(BlockBackend *blk);
+BlockDriverState *blk_bs(BlockBackend *blk);
+
 #endif
diff --git a/qemu-img.c b/qemu-img.c
index bad3f64..9fba5a1 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -284,20 +284,19 @@ static int print_block_option_help(const char *filename, const char *fmt)
     return 0;
 }
 
-static BlockDriverState *bdrv_new_open(const char *id,
-                                       const char *filename,
-                                       const char *fmt,
-                                       int flags,
-                                       bool require_io,
-                                       bool quiet)
+static BlockBackend *img_open(const char *id, const char *filename,
+                              const char *fmt, int flags,
+                              bool require_io, bool quiet)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriver *drv;
     char password[256];
     Error *local_err = NULL;
     int ret;
 
-    bs = bdrv_new_named(id, &error_abort);
+    blk = blk_new_with_bs(id, &error_abort);
+    bs = blk_bs(blk);
 
     if (fmt) {
         drv = bdrv_find_format(fmt);
@@ -328,9 +327,10 @@ static BlockDriverState *bdrv_new_open(const char *id,
             goto fail;
         }
     }
-    return bs;
+    return blk;
 fail:
     bdrv_unref(bs);
+    blk_unref(blk);
     return NULL;
 }
 
@@ -651,11 +651,11 @@ static int img_check(int argc, char **argv)
         return 1;
     }
 
-    blk = blk_new("image", &error_abort);
-    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
-    if (!bs) {
+    blk = img_open("image", filename, fmt, flags, true, quiet);
+    if (!blk) {
         return 1;
     }
+    bs = blk_bs(blk);
 
     check = g_new0(ImageCheck, 1);
     ret = collect_image_check(bs, check, filename, fmt, fix);
@@ -761,11 +761,12 @@ static int img_commit(int argc, char **argv)
         return 1;
     }
 
-    blk = blk_new("image", &error_abort);
-    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
-    if (!bs) {
+    blk = img_open("image", filename, fmt, flags, true, quiet);
+    if (!blk) {
         return 1;
     }
+    bs = blk_bs(blk);
+
     ret = bdrv_commit(bs);
     switch(ret) {
     case 0:
@@ -1019,21 +1020,21 @@ static int img_compare(int argc, char **argv)
         goto out3;
     }
 
-    blk1 = blk_new("image 1", &error_abort);
-    bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
-    if (!bs1) {
+    blk1 = img_open("image 1", filename1, fmt1, flags, true, quiet);
+    if (!blk1) {
         error_report("Can't open file %s", filename1);
         ret = 2;
         goto out3;
     }
+    bs1 = blk_bs(blk1);
 
-    blk2 = blk_new("image 2", &error_abort);
-    bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
-    if (!bs2) {
+    blk2 = img_open("image 2", filename2, fmt2, flags, true, quiet);
+    if (!blk2) {
         error_report("Can't open file %s", filename2);
         ret = 2;
         goto out2;
     }
+    bs2 = blk_bs(blk2);
 
     buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
     buf2 = qemu_blockalign(bs2, IO_BUF_SIZE);
@@ -1375,15 +1376,15 @@ static int img_convert(int argc, char **argv)
     for (bs_i = 0; bs_i < bs_n; bs_i++) {
         char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
                             : g_strdup("source");
-        blk[bs_i] = blk_new(id, &error_abort);
-        bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
-                                 true, quiet);
+        blk[bs_i] = img_open(id, argv[optind + bs_i], fmt, src_flags,
+                             true, quiet);
         g_free(id);
-        if (!bs[bs_i]) {
+        if (!blk[bs_i]) {
             error_report("Could not open '%s'", argv[optind + bs_i]);
             ret = -1;
             goto out;
         }
+        bs[bs_i] = blk_bs(blk[bs_i]);
         bs_sectors[bs_i] = bdrv_nb_sectors(bs[bs_i]);
         if (bs_sectors[bs_i] < 0) {
             error_report("Could not get size of %s: %s",
@@ -1501,12 +1502,12 @@ static int img_convert(int argc, char **argv)
         goto out;
     }
 
-    out_blk = blk_new("target", &error_abort);
-    out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
-    if (!out_bs) {
+    out_blk = img_open("target", out_filename, out_fmt, flags, true, quiet);
+    if (!out_blk) {
         ret = -1;
         goto out;
     }
+    out_bs = blk_bs(out_blk);
 
     bs_i = 0;
     bs_offset = 0;
@@ -1893,12 +1894,12 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         }
         g_hash_table_insert(filenames, (gpointer)filename, NULL);
 
-        blk = blk_new("image", &error_abort);
-        bs = bdrv_new_open("image", filename, fmt,
-                           BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
-        if (!bs) {
+        blk = img_open("image", filename, fmt,
+                       BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
+        if (!blk) {
             goto err;
         }
+        bs = blk_bs(blk);
 
         bdrv_query_image_info(bs, &info, &err);
         if (err) {
@@ -2158,11 +2159,11 @@ static int img_map(int argc, char **argv)
         return 1;
     }
 
-    blk = blk_new("image", &error_abort);
-    bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
-    if (!bs) {
+    blk = img_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
+    if (!blk) {
         return 1;
     }
+    bs = blk_bs(blk);
 
     if (output_format == OFORMAT_HUMAN) {
         printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File");
@@ -2281,11 +2282,11 @@ static int img_snapshot(int argc, char **argv)
     filename = argv[optind++];
 
     /* Open the image */
-    blk = blk_new("image", &error_abort);
-    bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
-    if (!bs) {
+    blk = img_open("image", filename, NULL, bdrv_oflags, true, quiet);
+    if (!blk) {
         return 1;
     }
+    bs = blk_bs(blk);
 
     /* Perform the requested action */
     switch(action) {
@@ -2427,12 +2428,12 @@ static int img_rebase(int argc, char **argv)
      * Ignore the old backing file for unsafe rebase in case we want to correct
      * the reference to a renamed or moved backing file.
      */
-    blk = blk_new("image", &error_abort);
-    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
-    if (!bs) {
+    blk = img_open("image", filename, fmt, flags, true, quiet);
+    if (!blk) {
         ret = -1;
         goto out;
     }
+    bs = blk_bs(blk);
 
     /* Find the right drivers for the backing files */
     old_backing_drv = NULL;
@@ -2460,8 +2461,8 @@ static int img_rebase(int argc, char **argv)
     if (!unsafe) {
         char backing_name[1024];
 
-        blk_old_backing = blk_new("old_backing", &error_abort);
-        bs_old_backing = bdrv_new_named("old_backing", &error_abort);
+        blk_old_backing = blk_new_with_bs("old_backing", &error_abort);
+        bs_old_backing = blk_bs(blk_old_backing);
         bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
         ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
                         old_backing_drv, &local_err);
@@ -2472,8 +2473,8 @@ static int img_rebase(int argc, char **argv)
             goto out;
         }
         if (out_baseimg[0]) {
-            blk_new_backing = blk_new("new_backing", &error_abort);
-            bs_new_backing = bdrv_new_named("new_backing", &error_abort);
+            blk_new_backing = blk_new_with_bs("new_backing", &error_abort);
+            bs_new_backing = blk_bs(blk_new_backing);
             ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
                             new_backing_drv, &local_err);
             if (ret) {
@@ -2749,13 +2750,13 @@ static int img_resize(int argc, char **argv)
     n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
     qemu_opts_del(param);
 
-    blk = blk_new("image", &error_abort);
-    bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
-                       true, quiet);
-    if (!bs) {
+    blk = img_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
+                   true, quiet);
+    if (!blk) {
         ret = -1;
         goto out;
     }
+    bs = blk_bs(blk);
 
     if (relative) {
         total_size = bdrv_getlength(bs) + n * relative;
@@ -2867,13 +2868,13 @@ static int img_amend(int argc, char **argv)
         goto out;
     }
 
-    blk = blk_new("image", &error_abort);
-    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
-    if (!bs) {
+    blk = img_open("image", filename, fmt, flags, true, quiet);
+    if (!blk) {
         error_report("Could not open image '%s'", filename);
         ret = -1;
         goto out;
     }
+    bs = blk_bs(blk);
 
     fmt = bs->drv->format_name;
 
diff --git a/qemu-io.c b/qemu-io.c
index 45e5494..ef1d3ea 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -62,8 +62,8 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
         return 1;
     }
 
-    qemuio_blk = blk_new("hda", &error_abort);
-    qemuio_bs = bdrv_new_named("hda", &error_abort);
+    qemuio_blk = blk_new_with_bs("hda", &error_abort);
+    qemuio_bs = blk_bs(qemuio_blk);
 
     if (growable) {
         flags |= BDRV_O_PROTOCOL;
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 94b9b49..8eff588 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -687,8 +687,7 @@ int main(int argc, char **argv)
         drv = NULL;
     }
 
-    blk_new("hda", &error_abort);
-    bs = bdrv_new_named("hda", &error_abort);
+    bs = blk_bs(blk_new_with_bs("hda", &error_abort));
 
     srcpath = argv[optind];
     ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (2 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10 13:08   ` Benoît Canet
  2014-09-10 13:30   ` Kevin Wolf
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 05/23] block: Make BlockBackend own its BlockDriverState Markus Armbruster
                   ` (19 subsequent siblings)
  23 siblings, 2 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Make the BlockBackend own the DriveInfo.  Change blockdev_init() to
return the BlockBackend instead of the DriveInfo.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block/block-backend.c     | 38 +++++++++++++++++++++++
 blockdev.c                | 79 +++++++++++++++++++++--------------------------
 include/sysemu/blockdev.h |  4 +++
 3 files changed, 78 insertions(+), 43 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index deccb54..2a22660 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -12,14 +12,18 @@
 
 #include "sysemu/block-backend.h"
 #include "block/block_int.h"
+#include "sysemu/blockdev.h"
 
 struct BlockBackend {
     char *name;
     int refcnt;
     BlockDriverState *bs;
+    DriveInfo *legacy_dinfo;
     QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
 };
 
+static void drive_info_del(DriveInfo *dinfo);
+
 static QTAILQ_HEAD(, BlockBackend) blk_backends =
     QTAILQ_HEAD_INITIALIZER(blk_backends);
 
@@ -87,6 +91,7 @@ static void blk_delete(BlockBackend *blk)
     blk_detach_bs(blk);
     QTAILQ_REMOVE(&blk_backends, blk, link);
     g_free(blk->name);
+    drive_info_del(blk->legacy_dinfo);
     g_free(blk);
 }
 
@@ -119,6 +124,16 @@ void blk_unref(BlockBackend *blk)
     }
 }
 
+static void drive_info_del(DriveInfo *dinfo)
+{
+    if (dinfo) {
+        qemu_opts_del(dinfo->opts);
+        g_free(dinfo->id);
+        g_free(dinfo->serial);
+        g_free(dinfo);
+    }
+}
+
 const char *blk_name(BlockBackend *blk)
 {
     return blk->name;
@@ -187,3 +202,26 @@ BlockDriverState *blk_detach_bs(BlockBackend *blk)
     }
     return bs;
 }
+
+DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
+{
+    return blk->legacy_dinfo;
+}
+
+DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
+{
+    assert(!blk->legacy_dinfo);
+    return blk->legacy_dinfo = dinfo;
+}
+
+BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
+{
+    BlockBackend *blk;
+
+    QTAILQ_FOREACH(blk, &blk_backends, link) {
+        if (blk->legacy_dinfo == dinfo) {
+            return blk;
+        }
+    }
+    assert(0);
+}
diff --git a/blockdev.c b/blockdev.c
index 0a0b95e..73e2da9 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -47,8 +47,6 @@
 #include "trace.h"
 #include "sysemu/arch_init.h"
 
-static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
-
 static const char *const if_name[IF_COUNT] = {
     [IF_NONE] = "none",
     [IF_IDE] = "ide",
@@ -89,7 +87,8 @@ static const int if_max_devs[IF_COUNT] = {
  */
 void blockdev_mark_auto_del(BlockDriverState *bs)
 {
-    DriveInfo *dinfo = drive_get_by_blockdev(bs);
+    BlockBackend *blk = bs->blk;
+    DriveInfo *dinfo = blk_legacy_dinfo(blk);
 
     if (dinfo && !dinfo->enable_auto_del) {
         return;
@@ -105,7 +104,8 @@ void blockdev_mark_auto_del(BlockDriverState *bs)
 
 void blockdev_auto_del(BlockDriverState *bs)
 {
-    DriveInfo *dinfo = drive_get_by_blockdev(bs);
+    BlockBackend *blk = bs->blk;
+    DriveInfo *dinfo = blk_legacy_dinfo(blk);
 
     if (dinfo && dinfo->auto_del) {
         drive_del(dinfo);
@@ -153,15 +153,15 @@ QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
 
 DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
 {
+    BlockBackend *blk;
     DriveInfo *dinfo;
 
-    /* seek interface, bus and unit */
-
-    QTAILQ_FOREACH(dinfo, &drives, next) {
-        if (dinfo->type == type &&
-	    dinfo->bus == bus &&
-	    dinfo->unit == unit)
+    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+        dinfo = blk_legacy_dinfo(blk);
+        if (dinfo && dinfo->type == type
+            && dinfo->bus == bus && dinfo->unit == unit) {
             return dinfo;
+        }
     }
 
     return NULL;
@@ -177,13 +177,15 @@ DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
 int drive_get_max_bus(BlockInterfaceType type)
 {
     int max_bus;
+    BlockBackend *blk;
     DriveInfo *dinfo;
 
     max_bus = -1;
-    QTAILQ_FOREACH(dinfo, &drives, next) {
-        if(dinfo->type == type &&
-           dinfo->bus > max_bus)
+    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+        dinfo = blk_legacy_dinfo(blk);
+        if (dinfo && dinfo->type == type && dinfo->bus > max_bus) {
             max_bus = dinfo->bus;
+        }
     }
     return max_bus;
 }
@@ -200,11 +202,11 @@ DriveInfo *drive_get_next(BlockInterfaceType type)
 
 DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
 {
-    DriveInfo *dinfo;
+    BlockBackend *blk;
 
-    QTAILQ_FOREACH(dinfo, &drives, next) {
-        if (dinfo->bdrv == bs) {
-            return dinfo;
+    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+        if (blk_bs(blk) == bs) {
+            return blk_legacy_dinfo(blk);
         }
     }
     return NULL;
@@ -217,16 +219,10 @@ static void bdrv_format_print(void *opaque, const char *name)
 
 void drive_del(DriveInfo *dinfo)
 {
-    if (dinfo->opts) {
-        qemu_opts_del(dinfo->opts);
-    }
+    BlockBackend *blk = dinfo->bdrv->blk;
 
     bdrv_unref(dinfo->bdrv);
-    blk_unref(blk_by_name(dinfo->id));
-    g_free(dinfo->id);
-    QTAILQ_REMOVE(&drives, dinfo, next);
-    g_free(dinfo->serial);
-    g_free(dinfo);
+    blk_unref(blk);
 }
 
 typedef struct {
@@ -296,8 +292,8 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
 typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
 
 /* Takes the ownership of bs_opts */
-static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
-                                Error **errp)
+static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
+                                   Error **errp)
 {
     const char *buf;
     int ro = 0;
@@ -480,7 +476,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     dinfo = g_malloc0(sizeof(*dinfo));
     dinfo->id = g_strdup(qemu_opts_id(opts));
     dinfo->bdrv = bs;
-    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
+    blk_set_legacy_dinfo(blk, dinfo);
 
     if (!file || !*file) {
         if (has_driver_specific_opts) {
@@ -488,7 +484,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
         } else {
             QDECREF(bs_opts);
             qemu_opts_del(opts);
-            return dinfo;
+            return blk;
         }
     }
     if (snapshot) {
@@ -525,13 +521,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
     QDECREF(bs_opts);
     qemu_opts_del(opts);
 
-    return dinfo;
+    return blk;
 
 err:
     bdrv_unref(dinfo->bdrv);
-    QTAILQ_REMOVE(&drives, dinfo, next);
-    g_free(dinfo->id);
-    g_free(dinfo);
     blk_unref(blk);
 early_err:
     qemu_opts_del(opts);
@@ -635,6 +628,7 @@ QemuOptsList qemu_legacy_drive_opts = {
 DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 {
     const char *value;
+    BlockBackend *blk;
     DriveInfo *dinfo = NULL;
     QDict *bs_opts;
     QemuOpts *legacy_opts;
@@ -917,19 +911,17 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     }
 
     /* Actual block device init: Functionality shared with blockdev-add */
-    dinfo = blockdev_init(filename, bs_opts, &local_err);
+    blk = blockdev_init(filename, bs_opts, &local_err);
     bs_opts = NULL;
-    if (dinfo == NULL) {
-        if (local_err) {
-            error_report("%s", error_get_pretty(local_err));
-            error_free(local_err);
-        }
+    if (!blk) {
+        error_report("%s", error_get_pretty(local_err));
         goto fail;
     } else {
         assert(!local_err);
     }
 
     /* Set legacy DriveInfo fields */
+    dinfo = blk_legacy_dinfo(blk);
     dinfo->enable_auto_del = true;
     dinfo->opts = all_opts;
 
@@ -2478,7 +2470,7 @@ void qmp_change_backing_file(const char *device,
 void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 {
     QmpOutputVisitor *ov = qmp_output_visitor_new();
-    DriveInfo *dinfo;
+    BlockBackend *blk;
     QObject *obj;
     QDict *qdict;
     Error *local_err = NULL;
@@ -2516,14 +2508,15 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
 
     qdict_flatten(qdict);
 
-    dinfo = blockdev_init(NULL, qdict, &local_err);
+    blk = blockdev_init(NULL, qdict, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         goto fail;
     }
 
-    if (bdrv_key_required(dinfo->bdrv)) {
-        drive_del(dinfo);
+    if (bdrv_key_required(blk_bs(blk))) {
+        bdrv_unref(blk_bs(blk));
+        blk_unref(blk);
         error_setg(errp, "blockdev-add doesn't support encrypted devices");
         goto fail;
     }
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 23a5d10..2ed297b 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -45,6 +45,10 @@ struct DriveInfo {
     QTAILQ_ENTRY(DriveInfo) next;
 };
 
+DriveInfo *blk_legacy_dinfo(BlockBackend *blk);
+DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo);
+BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo);
+
 DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
 DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
 int drive_get_max_bus(BlockInterfaceType type);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 05/23] block: Make BlockBackend own its BlockDriverState
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (3 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10 10:14   ` Kevin Wolf
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 06/23] block: Eliminate bdrv_states, use block_next() instead Markus Armbruster
                   ` (18 subsequent siblings)
  23 siblings, 1 reply; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

On BlockBackend destruction, unref its BlockDriverState.  Replaces the
callers' unrefs.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block/block-backend.c |  9 ++-------
 blockdev.c            | 11 +++--------
 hw/block/xen_disk.c   |  6 +++---
 qemu-img.c            | 35 +----------------------------------
 qemu-io.c             |  5 -----
 5 files changed, 9 insertions(+), 57 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 2a22660..ae51f7f 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -58,10 +58,7 @@ BlockBackend *blk_new(const char *name, Error **errp)
  * @errp: return location for an error to be set on failure, or %NULL
  *
  * Create a new BlockBackend, with a reference count of one, and
- * attach a new BlockDriverState to it, also with a reference count of
- * one.  Caller owns *both* references.
- * TODO Let caller own only the BlockBackend reference
- * Fail if @name already exists.
+ * a new BlockDriverState attached.  Fail if @name already exists.
  *
  * Returns: the BlockBackend on success, %NULL on error
  */
@@ -88,6 +85,7 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp)
 static void blk_delete(BlockBackend *blk)
 {
     assert(!blk->refcnt);
+    bdrv_unref(blk->bs);
     blk_detach_bs(blk);
     QTAILQ_REMOVE(&blk_backends, blk, link);
     g_free(blk->name);
@@ -110,9 +108,6 @@ void blk_ref(BlockBackend *blk)
  *
  * Decrement @blk's reference count.  If this drops it to zero,
  * destroy @blk.
- *
- * Does *not* touch the attached BlockDriverState's reference count.
- * TODO Decrement it!
  */
 void blk_unref(BlockBackend *blk)
 {
diff --git a/blockdev.c b/blockdev.c
index 73e2da9..791f6d9 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -108,7 +108,7 @@ void blockdev_auto_del(BlockDriverState *bs)
     DriveInfo *dinfo = blk_legacy_dinfo(blk);
 
     if (dinfo && dinfo->auto_del) {
-        drive_del(dinfo);
+        blk_unref(blk);
     }
 }
 
@@ -219,10 +219,7 @@ static void bdrv_format_print(void *opaque, const char *name)
 
 void drive_del(DriveInfo *dinfo)
 {
-    BlockBackend *blk = dinfo->bdrv->blk;
-
-    bdrv_unref(dinfo->bdrv);
-    blk_unref(blk);
+    blk_unref(dinfo->bdrv->blk);
 }
 
 typedef struct {
@@ -524,7 +521,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
     return blk;
 
 err:
-    bdrv_unref(dinfo->bdrv);
     blk_unref(blk);
 early_err:
     qemu_opts_del(opts);
@@ -1778,7 +1774,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
         bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
                           BLOCKDEV_ON_ERROR_REPORT);
     } else {
-        drive_del(drive_get_by_blockdev(bs));
+        blk_unref(blk);
     }
 
     aio_context_release(aio_context);
@@ -2515,7 +2511,6 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
     }
 
     if (bdrv_key_required(blk_bs(blk))) {
-        bdrv_unref(blk_bs(blk));
         blk_unref(blk);
         error_setg(errp, "blockdev-add doesn't support encrypted devices");
         goto fail;
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 51f4f3a..6d474b9 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -870,7 +870,6 @@ static int blk_connect(struct XenDevice *xendev)
             xen_be_printf(&blkdev->xendev, 0, "error: %s\n",
                           error_get_pretty(local_err));
             error_free(local_err);
-            bdrv_unref(blkdev->bs);
             blk_unref(blk);
             blkdev->bs = NULL;
             return -1;
@@ -886,7 +885,9 @@ static int blk_connect(struct XenDevice *xendev)
         }
         /* blkdev->bs is not create by us, we get a reference
          * so we can bdrv_unref() unconditionally */
-        bdrv_ref(blkdev->bs);
+        /* Except we don't bdrv_unref() anymore, we blk_unref().
+         * Conditionally, because we can't easily blk_ref() here.
+         * TODO Clean this up! */
     }
     bdrv_attach_dev_nofail(blkdev->bs, blkdev);
     blkdev->file_size = bdrv_getlength(blkdev->bs);
@@ -986,7 +987,6 @@ static void blk_disconnect(struct XenDevice *xendev)
 
     if (blkdev->bs) {
         bdrv_detach_dev(blkdev->bs, blkdev);
-        bdrv_unref(blkdev->bs);
         if (!blkdev->dinfo) {
             blk_unref(blk_by_name(blkdev->dev));
         }
diff --git a/qemu-img.c b/qemu-img.c
index 9fba5a1..083a8eb 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -329,7 +329,6 @@ static BlockBackend *img_open(const char *id, const char *filename,
     }
     return blk;
 fail:
-    bdrv_unref(bs);
     blk_unref(blk);
     return NULL;
 }
@@ -712,9 +711,7 @@ static int img_check(int argc, char **argv)
 
 fail:
     qapi_free_ImageCheck(check);
-    bdrv_unref(bs);
     blk_unref(blk);
-
     return ret;
 }
 
@@ -786,7 +783,6 @@ static int img_commit(int argc, char **argv)
         break;
     }
 
-    bdrv_unref(bs);
     blk_unref(blk);
     if (ret) {
         return 1;
@@ -1194,12 +1190,10 @@ static int img_compare(int argc, char **argv)
     ret = 0;
 
 out:
-    bdrv_unref(bs2);
     blk_unref(blk2);
     qemu_vfree(buf1);
     qemu_vfree(buf2);
 out2:
-    bdrv_unref(bs1);
     blk_unref(blk1);
 out3:
     qemu_progress_end();
@@ -1756,18 +1750,8 @@ out:
     if (sn_opts) {
         qemu_opts_del(sn_opts);
     }
-    if (out_bs) {
-        bdrv_unref(out_bs);
-    }
     blk_unref(out_blk);
-    if (bs) {
-        for (bs_i = 0; bs_i < bs_n; bs_i++) {
-            if (bs[bs_i]) {
-                bdrv_unref(bs[bs_i]);
-            }
-        }
-        g_free(bs);
-    }
+    g_free(bs);
     if (blk) {
         for (bs_i = 0; bs_i < bs_n; bs_i++) {
             blk_unref(blk[bs_i]);
@@ -1905,7 +1889,6 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         if (err) {
             error_report("%s", error_get_pretty(err));
             error_free(err);
-            bdrv_unref(bs);
             blk_unref(blk);
             goto err;
         }
@@ -1915,7 +1898,6 @@ static ImageInfoList *collect_image_info_list(const char *filename,
         *last = elem;
         last = &elem->next;
 
-        bdrv_unref(bs);
         blk_unref(blk);
 
         filename = fmt = NULL;
@@ -2204,7 +2186,6 @@ static int img_map(int argc, char **argv)
     dump_map_entry(output_format, &curr, NULL);
 
 out:
-    bdrv_unref(bs);
     blk_unref(blk);
     return ret < 0;
 }
@@ -2329,7 +2310,6 @@ static int img_snapshot(int argc, char **argv)
     }
 
     /* Cleanup */
-    bdrv_unref(bs);
     blk_unref(blk);
     if (ret) {
         return 1;
@@ -2649,17 +2629,10 @@ out:
     qemu_progress_end();
     /* Cleanup */
     if (!unsafe) {
-        if (bs_old_backing != NULL) {
-            bdrv_unref(bs_old_backing);
-        }
         blk_unref(blk_old_backing);
-        if (bs_new_backing != NULL) {
-            bdrv_unref(bs_new_backing);
-        }
         blk_unref(blk_new_backing);
     }
 
-    bdrv_unref(bs);
     blk_unref(blk);
     if (ret) {
         return 1;
@@ -2785,9 +2758,6 @@ static int img_resize(int argc, char **argv)
         break;
     }
 out:
-    if (bs) {
-        bdrv_unref(bs);
-    }
     blk_unref(blk);
     if (ret) {
         return 1;
@@ -2899,9 +2869,6 @@ static int img_amend(int argc, char **argv)
     }
 
 out:
-    if (bs) {
-        bdrv_unref(bs);
-    }
     blk_unref(blk);
     qemu_opts_del(opts);
     qemu_opts_free(create_opts);
diff --git a/qemu-io.c b/qemu-io.c
index ef1d3ea..45e8167 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -38,7 +38,6 @@ static ReadLineState *readline_state;
 
 static int close_f(BlockDriverState *bs, int argc, char **argv)
 {
-    bdrv_unref(bs);
     blk_unref(qemuio_blk);
     qemuio_bs = NULL;
     qemuio_blk = NULL;
@@ -74,7 +73,6 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
                 name ? " device " : "", name ?: "",
                 error_get_pretty(local_err));
         error_free(local_err);
-        bdrv_unref(qemuio_bs);
         blk_unref(qemuio_blk);
         qemuio_bs = NULL;
         qemuio_blk = NULL;
@@ -483,9 +481,6 @@ int main(int argc, char **argv)
      */
     bdrv_drain_all();
 
-    if (qemuio_bs) {
-        bdrv_unref(qemuio_bs);
-    }
     blk_unref(qemuio_blk);
     g_free(readline_state);
     return 0;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 06/23] block: Eliminate bdrv_states, use block_next() instead
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (4 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 05/23] block: Make BlockBackend own its BlockDriverState Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-11 10:25   ` Benoît Canet
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 07/23] block: Eliminate bdrv_iterate(), use bdrv_next() Markus Armbruster
                   ` (17 subsequent siblings)
  23 siblings, 1 reply; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block.c                   | 43 +++++++++++++++++++------------------------
 block/block-backend.c     |  4 ++++
 include/block/block_int.h |  2 --
 3 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/block.c b/block.c
index a6c03da..89f9cf0 100644
--- a/block.c
+++ b/block.c
@@ -24,6 +24,7 @@
 #include "config-host.h"
 #include "qemu-common.h"
 #include "trace.h"
+#include "sysemu/block-backend.h"
 #include "block/block_int.h"
 #include "block/blockjob.h"
 #include "qemu/module.h"
@@ -90,9 +91,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);
 
@@ -355,9 +353,6 @@ BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
     bs = bdrv_new();
 
     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
-    if (device_name[0] != '\0') {
-        QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
-    }
 
     return bs;
 }
@@ -1888,7 +1883,7 @@ void bdrv_close_all(void)
 {
     BlockDriverState *bs;
 
-    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
         AioContext *aio_context = bdrv_get_aio_context(bs);
 
         aio_context_acquire(aio_context);
@@ -1939,7 +1934,7 @@ void bdrv_drain_all(void)
     while (busy) {
         busy = false;
 
-        QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+        for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
             AioContext *aio_context = bdrv_get_aio_context(bs);
             bool bs_busy;
 
@@ -1960,9 +1955,6 @@ void bdrv_drain_all(void)
    Also, NULL terminate the device_name to prevent double remove */
 void bdrv_make_anon(BlockDriverState *bs)
 {
-    if (bs->device_name[0] != '\0') {
-        QTAILQ_REMOVE(&bdrv_states, bs, device_list);
-    }
     bs->device_name[0] = '\0';
     if (bs->node_name[0] != '\0') {
         QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list);
@@ -2016,10 +2008,9 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     /* job */
     bs_dest->job                = bs_src->job;
 
-    /* keep the same entry in bdrv_states */
     pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
             bs_src->device_name);
-    bs_dest->device_list = bs_src->device_list;
+
     memcpy(bs_dest->op_blockers, bs_src->op_blockers,
            sizeof(bs_dest->op_blockers));
 }
@@ -2363,7 +2354,7 @@ int bdrv_commit_all(void)
 {
     BlockDriverState *bs;
 
-    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
         AioContext *aio_context = bdrv_get_aio_context(bs);
 
         aio_context_acquire(aio_context);
@@ -3807,7 +3798,7 @@ BlockDriverState *bdrv_find(const char *name)
 {
     BlockDriverState *bs;
 
-    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
         if (!strcmp(name, bs->device_name)) {
             return bs;
         }
@@ -3888,17 +3879,21 @@ bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base)
 
 BlockDriverState *bdrv_next(BlockDriverState *bs)
 {
-    if (!bs) {
-        return QTAILQ_FIRST(&bdrv_states);
-    }
-    return QTAILQ_NEXT(bs, device_list);
+    BlockBackend *blk;
+
+    for (blk = blk_next(bs ? bs->blk : NULL);
+         blk && !blk_bs(blk);
+         blk = blk_next(blk))
+        ;
+
+    return blk ? blk_bs(blk) : NULL;
 }
 
 void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
 {
     BlockDriverState *bs;
 
-    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
         it(opaque, bs);
     }
 }
@@ -3918,7 +3913,7 @@ int bdrv_flush_all(void)
     BlockDriverState *bs;
     int result = 0;
 
-    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
         AioContext *aio_context = bdrv_get_aio_context(bs);
         int ret;
 
@@ -5065,7 +5060,7 @@ void bdrv_invalidate_cache_all(Error **errp)
     BlockDriverState *bs;
     Error *local_err = NULL;
 
-    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
         AioContext *aio_context = bdrv_get_aio_context(bs);
 
         aio_context_acquire(aio_context);
@@ -5082,7 +5077,7 @@ void bdrv_clear_incoming_migration_all(void)
 {
     BlockDriverState *bs;
 
-    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
         AioContext *aio_context = bdrv_get_aio_context(bs);
 
         aio_context_acquire(aio_context);
@@ -5918,7 +5913,7 @@ bool bdrv_is_first_non_filter(BlockDriverState *candidate)
     BlockDriverState *bs;
 
     /* walk down the bs forest recursively */
-    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
         bool perm;
 
         /* try to recurse in this top level bs */
diff --git a/block/block-backend.c b/block/block-backend.c
index ae51f7f..c0876fa 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -191,6 +191,10 @@ BlockDriverState *blk_detach_bs(BlockBackend *blk)
 {
     BlockDriverState *bs = blk->bs;
 
+    /*
+     * Must bdrv_unref() before zapping bs->blk, or else
+     * bdrv_drain_all() will miss bs.
+     */
     if (bs) {
         bs->blk = NULL;
         blk->bs = NULL;
diff --git a/include/block/block_int.h b/include/block/block_int.h
index a04c852..d5de08b 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -396,8 +396,6 @@ struct BlockDriverState {
     QTAILQ_ENTRY(BlockDriverState) node_list;
     /* Device name is the name associated with the "drive" the guest sees */
     char device_name[32];
-    /* element of the list of "drives" the guest sees */
-    QTAILQ_ENTRY(BlockDriverState) device_list;
     QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
     int refcnt;
 
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 07/23] block: Eliminate bdrv_iterate(), use bdrv_next()
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (5 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 06/23] block: Eliminate bdrv_states, use block_next() instead Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-11 10:46   ` Benoît Canet
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[] Markus Armbruster
                   ` (16 subsequent siblings)
  23 siblings, 1 reply; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block-migration.c     | 30 +++++++++++++++---------------
 block.c               |  9 ---------
 blockdev.c            | 31 +++++++++++++------------------
 include/block/block.h |  2 --
 monitor.c             | 33 +++++++++------------------------
 5 files changed, 37 insertions(+), 68 deletions(-)

diff --git a/block-migration.c b/block-migration.c
index 3ad31a2..cb3e16c 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -343,12 +343,25 @@ static void unset_dirty_tracking(void)
     }
 }
 
-static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
+static void init_blk_migration(QEMUFile *f)
 {
+    BlockDriverState *bs;
     BlkMigDevState *bmds;
     int64_t sectors;
 
-    if (!bdrv_is_read_only(bs)) {
+    block_mig_state.submitted = 0;
+    block_mig_state.read_done = 0;
+    block_mig_state.transferred = 0;
+    block_mig_state.total_sector_sum = 0;
+    block_mig_state.prev_progress = -1;
+    block_mig_state.bulk_completed = 0;
+    block_mig_state.zero_blocks = migrate_zero_blocks();
+
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
+        if (bdrv_is_read_only(bs)) {
+            continue;
+        }
+
         sectors = bdrv_nb_sectors(bs);
         if (sectors <= 0) {
             return;
@@ -378,19 +391,6 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
     }
 }
 
-static void init_blk_migration(QEMUFile *f)
-{
-    block_mig_state.submitted = 0;
-    block_mig_state.read_done = 0;
-    block_mig_state.transferred = 0;
-    block_mig_state.total_sector_sum = 0;
-    block_mig_state.prev_progress = -1;
-    block_mig_state.bulk_completed = 0;
-    block_mig_state.zero_blocks = migrate_zero_blocks();
-
-    bdrv_iterate(init_blk_migration_it, NULL);
-}
-
 /* Called with no lock taken.  */
 
 static int blk_mig_save_bulked_block(QEMUFile *f)
diff --git a/block.c b/block.c
index 89f9cf0..593d89b 100644
--- a/block.c
+++ b/block.c
@@ -3889,15 +3889,6 @@ BlockDriverState *bdrv_next(BlockDriverState *bs)
     return blk ? blk_bs(blk) : NULL;
 }
 
-void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
-{
-    BlockDriverState *bs;
-
-    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
-        it(opaque, bs);
-    }
-}
-
 const char *bdrv_get_device_name(BlockDriverState *bs)
 {
     return bs->device_name;
diff --git a/blockdev.c b/blockdev.c
index 791f6d9..353563e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -2520,26 +2520,21 @@ fail:
     qmp_output_visitor_cleanup(ov);
 }
 
-static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs)
-{
-    BlockJobInfoList **prev = opaque;
-    BlockJob *job = bs->job;
-
-    if (job) {
-        BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1);
-        elem->value = block_job_query(bs->job);
-        (*prev)->next = elem;
-        *prev = elem;
-    }
-}
-
 BlockJobInfoList *qmp_query_block_jobs(Error **errp)
 {
-    /* Dummy is a fake list element for holding the head pointer */
-    BlockJobInfoList dummy = {};
-    BlockJobInfoList *prev = &dummy;
-    bdrv_iterate(do_qmp_query_block_jobs_one, &prev);
-    return dummy.next;
+    BlockJobInfoList *head = NULL, **p_next = &head;
+    BlockDriverState *bs;
+
+    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
+        if (bs->job) {
+            BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1);
+            elem->value = block_job_query(bs->job);
+            *p_next = elem;
+            p_next = &elem->next;
+        }
+    }
+
+    return head;
 }
 
 QemuOptsList qemu_common_drive_opts = {
diff --git a/include/block/block.h b/include/block/block.h
index 95139c0..8cf9ea3 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -409,8 +409,6 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
                                  Error **errp);
 bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base);
 BlockDriverState *bdrv_next(BlockDriverState *bs);
-void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
-                  void *opaque);
 int bdrv_is_encrypted(BlockDriverState *bs);
 int bdrv_key_required(BlockDriverState *bs);
 int bdrv_set_key(BlockDriverState *bs, const char *key);
diff --git a/monitor.c b/monitor.c
index 34cee74..4ae66df 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4208,24 +4208,6 @@ static void file_completion(Monitor *mon, const char *input)
     closedir(ffs);
 }
 
-typedef struct MonitorBlockComplete {
-    Monitor *mon;
-    const char *input;
-} MonitorBlockComplete;
-
-static void block_completion_it(void *opaque, BlockDriverState *bs)
-{
-    const char *name = bdrv_get_device_name(bs);
-    MonitorBlockComplete *mbc = opaque;
-    Monitor *mon = mbc->mon;
-    const char *input = mbc->input;
-
-    if (input[0] == '\0' ||
-        !strncmp(name, (char *)input, strlen(input))) {
-        readline_add_completion(mon->rs, name);
-    }
-}
-
 static const char *next_arg_type(const char *typestr)
 {
     const char *p = strchr(typestr, ':');
@@ -4663,9 +4645,9 @@ static void monitor_find_completion_by_table(Monitor *mon,
 {
     const char *cmdname;
     int i;
-    const char *ptype, *str;
+    const char *ptype, *str, *name;
     const mon_cmd_t *cmd;
-    MonitorBlockComplete mbs;
+    BlockDriverState *bs;
 
     if (nb_args <= 1) {
         /* command completion */
@@ -4717,10 +4699,13 @@ static void monitor_find_completion_by_table(Monitor *mon,
             break;
         case 'B':
             /* block device name completion */
-            mbs.mon = mon;
-            mbs.input = str;
-            readline_set_completion_index(mon->rs, strlen(str));
-            bdrv_iterate(block_completion_it, &mbs);
+            for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
+                name = bdrv_get_device_name(bs);
+                if (str[0] == '\0' ||
+                    !strncmp(name, str, strlen(str))) {
+                    readline_add_completion(mon->rs, name);
+                }
+            }
             break;
         case 's':
         case 'S':
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[]
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (6 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 07/23] block: Eliminate bdrv_iterate(), use bdrv_next() Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10 16:09   ` Eric Blake
  2014-09-11 11:34   ` Benoît Canet
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 09/23] block: Merge BlockBackend and BlockDriverState name spaces Markus Armbruster
                   ` (15 subsequent siblings)
  23 siblings, 2 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

device_name[] is can become non-empty only in bdrv_new_named() and
bdrv_move_feature_fields().  The latter is used only to undo damage
done by bdrv_swap().  The former is called only by blk_new_with_bs().
Therefore, when a BlockDriverState's device_name[] is non-empty, then
it's owned by a BlockBackend.

The converse is also true, because blk_attach_bs() is called only by
blk_new_with_bs() so far.

Furthermore, blk_new_with_bs() keeps the two names equal.

Therefore, device_name[] is redundant.  Eliminate it.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block-migration.c         | 12 +++++----
 block.c                   | 63 ++++++++++++++---------------------------------
 block/block-backend.c     | 12 ++++-----
 block/cow.c               |  2 +-
 block/mirror.c            |  3 ++-
 block/qapi.c              |  6 ++---
 block/qcow.c              |  4 +--
 block/qcow2.c             |  4 +--
 block/qed.c               |  2 +-
 block/quorum.c            |  4 +--
 block/vdi.c               |  2 +-
 block/vhdx.c              |  2 +-
 block/vmdk.c              |  4 +--
 block/vpc.c               |  2 +-
 block/vvfat.c             |  2 +-
 blockjob.c                |  3 ++-
 include/block/block.h     |  3 +--
 include/block/block_int.h |  2 --
 18 files changed, 53 insertions(+), 79 deletions(-)

diff --git a/block-migration.c b/block-migration.c
index cb3e16c..da30e93 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -14,7 +14,9 @@
  */
 
 #include "qemu-common.h"
-#include "block/block_int.h"
+#include "block/block.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
 #include "hw/hw.h"
 #include "qemu/queue.h"
 #include "qemu/timer.h"
@@ -130,9 +132,9 @@ static void blk_send(QEMUFile *f, BlkMigBlock * blk)
                      | flags);
 
     /* device name */
-    len = strlen(blk->bmds->bs->device_name);
+    len = strlen(bdrv_get_device_name(blk->bmds->bs));
     qemu_put_byte(f, len);
-    qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len);
+    qemu_put_buffer(f, (uint8_t *)bdrv_get_device_name(blk->bmds->bs), len);
 
     /* if a block is zero we need to flush here since the network
      * bandwidth is now a lot higher than the storage device bandwidth.
@@ -382,9 +384,9 @@ static void init_blk_migration(QEMUFile *f)
 
         if (bmds->shared_base) {
             DPRINTF("Start migration for %s with shared base image\n",
-                    bs->device_name);
+                    bdrv_get_device_name(bs));
         } else {
-            DPRINTF("Start full migration for %s\n", bs->device_name);
+            DPRINTF("Start full migration for %s\n", bdrv_get_device_name(bs));
         }
 
         QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
diff --git a/block.c b/block.c
index 593d89b..61ea15d 100644
--- a/block.c
+++ b/block.c
@@ -332,31 +332,6 @@ void bdrv_register(BlockDriver *bdrv)
     QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
 }
 
-/* create a new block device (by default it is empty) */
-BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
-{
-    BlockDriverState *bs;
-
-    assert(*device_name);
-
-    if (bdrv_find(device_name)) {
-        error_setg(errp, "Device with id '%s' already exists",
-                   device_name);
-        return NULL;
-    }
-    if (bdrv_find_node(device_name)) {
-        error_setg(errp, "Device with node-name '%s' already exists",
-                   device_name);
-        return NULL;
-    }
-
-    bs = bdrv_new();
-
-    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
-
-    return bs;
-}
-
 BlockDriverState *bdrv_new(void)
 {
     BlockDriverState *bs;
@@ -1159,7 +1134,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
     } else if (backing_hd) {
         error_setg(&bs->backing_blocker,
                    "device is used as backing hd of '%s'",
-                   bs->device_name);
+                   bdrv_get_device_name(bs));
     }
 
     bs->backing_hd = backing_hd;
@@ -1533,7 +1508,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
         } else {
             error_setg(errp, "Block format '%s' used by device '%s' doesn't "
                        "support the option '%s'", drv->format_name,
-                       bs->device_name, entry->key);
+                       bdrv_get_device_name(bs), entry->key);
         }
 
         ret = -EINVAL;
@@ -1740,7 +1715,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
     if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) &&
         reopen_state->flags & BDRV_O_RDWR) {
         error_set(errp, QERR_DEVICE_IS_READ_ONLY,
-                  reopen_state->bs->device_name);
+                  bdrv_get_device_name(reopen_state->bs));
         goto error;
     }
 
@@ -1767,7 +1742,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
         /* It is currently mandatory to have a bdrv_reopen_prepare()
          * handler for each supported drv. */
         error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
-                  drv->format_name, reopen_state->bs->device_name,
+                  drv->format_name, bdrv_get_device_name(reopen_state->bs),
                  "reopening of file");
         ret = -1;
         goto error;
@@ -1955,7 +1930,6 @@ void bdrv_drain_all(void)
    Also, NULL terminate the device_name to prevent double remove */
 void bdrv_make_anon(BlockDriverState *bs)
 {
-    bs->device_name[0] = '\0';
     if (bs->node_name[0] != '\0') {
         QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list);
     }
@@ -2008,9 +1982,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     /* job */
     bs_dest->job                = bs_src->job;
 
-    pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
-            bs_src->device_name);
-
     memcpy(bs_dest->op_blockers, bs_src->op_blockers,
            sizeof(bs_dest->op_blockers));
 }
@@ -2023,7 +1994,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
  * This will modify the BlockDriverState fields, and swap contents
  * between bs_new and bs_old. Both bs_new and bs_old are modified.
  *
- * bs_new must be nameless and not attached to a BlockBackend.
+ * bs_new must not be attached to a BlockBackend.
  *
  * This function does not create any image files.
  */
@@ -2042,8 +2013,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
         QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list);
     }
 
-    /* bs_new must be nameless and shouldn't have anything fancy enabled */
-    assert(bs_new->device_name[0] == '\0');
+    /* bs_new must be unattached and shouldn't have anything fancy enabled */
     assert(!bs_new->blk);
     assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
     assert(bs_new->job == NULL);
@@ -2060,8 +2030,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
     bdrv_move_feature_fields(bs_old, bs_new);
     bdrv_move_feature_fields(bs_new, &tmp);
 
-    /* bs_new must remain nameless and unattached */
-    assert(bs_new->device_name[0] == '\0');
+    /* bs_new must remain unattached */
     assert(!bs_new->blk);
 
     /* Check a few fields that should remain attached to the device */
@@ -2089,7 +2058,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
  * This will modify the BlockDriverState fields, and swap contents
  * between bs_new and bs_top. Both bs_new and bs_top are modified.
  *
- * bs_new must be nameless and not attached to a BlockBackend.
+ * bs_new must not be attached to a BlockBackend.
  *
  * This function does not create any image files.
  */
@@ -3799,7 +3768,7 @@ BlockDriverState *bdrv_find(const char *name)
     BlockDriverState *bs;
 
     for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
-        if (!strcmp(name, bs->device_name)) {
+        if (!strcmp(name, bdrv_get_device_name(bs))) {
             return bs;
         }
     }
@@ -3889,9 +3858,10 @@ BlockDriverState *bdrv_next(BlockDriverState *bs)
     return blk ? blk_bs(blk) : NULL;
 }
 
-const char *bdrv_get_device_name(BlockDriverState *bs)
+const char *bdrv_get_device_name(const BlockDriverState *bs)
 {
-    return bs->device_name;
+    const char *name = bs->blk ? blk_name(bs->blk) : NULL;
+    return name ?: "";
 }
 
 int bdrv_get_flags(BlockDriverState *bs)
@@ -5253,13 +5223,15 @@ int bdrv_media_changed(BlockDriverState *bs)
 void bdrv_eject(BlockDriverState *bs, bool eject_flag)
 {
     BlockDriver *drv = bs->drv;
+    const char *device_name;
 
     if (drv && drv->bdrv_eject) {
         drv->bdrv_eject(bs, eject_flag);
     }
 
-    if (bs->device_name[0] != '\0') {
-        qapi_event_send_device_tray_moved(bdrv_get_device_name(bs),
+    device_name = bdrv_get_device_name(bs);
+    if (device_name[0] != '\0') {
+        qapi_event_send_device_tray_moved(device_name,
                                           eject_flag, &error_abort);
     }
 }
@@ -5469,7 +5441,8 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
         blocker = QLIST_FIRST(&bs->op_blockers[op]);
         if (errp) {
             error_setg(errp, "Device '%s' is busy: %s",
-                       bs->device_name, error_get_pretty(blocker->reason));
+                       bdrv_get_device_name(bs),
+                       error_get_pretty(blocker->reason));
         }
         return true;
     }
diff --git a/block/block-backend.c b/block/block-backend.c
index c0876fa..2f10d6a 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -67,17 +67,17 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp)
     BlockBackend *blk;
     BlockDriverState *bs;
 
+    if (bdrv_find_node(name)) {
+        error_setg(errp, "Device with node-name '%s' already exists", name);
+        return NULL;
+    }
+
     blk = blk_new(name, errp);
     if (!blk) {
         return NULL;
     }
 
-    bs = bdrv_new_named(name, errp);
-    if (!bs) {
-        blk_unref(blk);
-        return NULL;
-    }
-
+    bs = bdrv_new();
     blk_attach_bs(blk, bs);
     return blk;
 }
diff --git a/block/cow.c b/block/cow.c
index 6ee4833..dda1e17 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -84,7 +84,7 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
         snprintf(version, sizeof(version),
                "COW version %" PRIu32, cow_header.version);
         error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
-            bs->device_name, "cow", version);
+            bdrv_get_device_name(bs), "cow", version);
         ret = -ENOTSUP;
         goto fail;
     }
diff --git a/block/mirror.c b/block/mirror.c
index 18b18e0..829be2f 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -567,7 +567,8 @@ static void mirror_complete(BlockJob *job, Error **errp)
         return;
     }
     if (!s->synced) {
-        error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
+        error_set(errp, QERR_BLOCK_JOB_NOT_READY,
+                  bdrv_get_device_name(job->bs));
         return;
     }
 
diff --git a/block/qapi.c b/block/qapi.c
index 79d1e6a..cc8f711 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -272,7 +272,7 @@ void bdrv_query_info(BlockDriverState *bs,
     BlockDriverState *bs0;
     ImageInfo **p_image_info;
     Error *local_err = NULL;
-    info->device = g_strdup(bs->device_name);
+    info->device = g_strdup(bdrv_get_device_name(bs));
     info->type = g_strdup("unknown");
     info->locked = bdrv_dev_is_medium_locked(bs);
     info->removable = bdrv_dev_has_removable_media(bs);
@@ -327,9 +327,9 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs)
 
     s = g_malloc0(sizeof(*s));
 
-    if (bs->device_name[0]) {
+    if (bdrv_get_device_name(bs)[0]) {
         s->has_device = true;
-        s->device = g_strdup(bs->device_name);
+        s->device = g_strdup(bdrv_get_device_name(bs));
     }
 
     s->stats = g_malloc0(sizeof(*s->stats));
diff --git a/block/qcow.c b/block/qcow.c
index 67c237f..2d803ac 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -124,7 +124,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
         snprintf(version, sizeof(version), "QCOW version %" PRIu32,
                  header.version);
         error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
-                  bs->device_name, "qcow", version);
+                  bdrv_get_device_name(bs), "qcow", version);
         ret = -ENOTSUP;
         goto fail;
     }
@@ -231,7 +231,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
     /* Disable migration when qcow images are used */
     error_set(&s->migration_blocker,
               QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
-              "qcow", bs->device_name, "live migration");
+              "qcow", bdrv_get_device_name(bs), "live migration");
     migrate_add_blocker(s->migration_blocker);
 
     qemu_co_mutex_init(&s->lock);
diff --git a/block/qcow2.c b/block/qcow2.c
index f9e045f..0ab455e 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -203,8 +203,8 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs,
     vsnprintf(msg, sizeof(msg), fmt, ap);
     va_end(ap);
 
-    error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, bs->device_name, "qcow2",
-              msg);
+    error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
+              bdrv_get_device_name(bs), "qcow2", msg);
 }
 
 static void report_unsupported_feature(BlockDriverState *bs,
diff --git a/block/qed.c b/block/qed.c
index ba395af..f20ffb3 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -422,7 +422,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
         snprintf(buf, sizeof(buf), "%" PRIx64,
             s->header.features & ~QED_FEATURE_MASK);
         error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
-            bs->device_name, "QED", buf);
+            bdrv_get_device_name(bs), "QED", buf);
         return -ENOTSUP;
     }
     if (!qed_is_cluster_size_valid(s->header.cluster_size)) {
diff --git a/block/quorum.c b/block/quorum.c
index 093382e..f958269 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -227,8 +227,8 @@ static void quorum_report_bad(QuorumAIOCB *acb, char *node_name, int ret)
 
 static void quorum_report_failure(QuorumAIOCB *acb)
 {
-    const char *reference = acb->common.bs->device_name[0] ?
-                            acb->common.bs->device_name :
+    const char *reference = bdrv_get_device_name(acb->common.bs)[0] ?
+                            bdrv_get_device_name(acb->common.bs) :
                             acb->common.bs->node_name;
 
     qapi_event_send_quorum_failure(reference, acb->sector_num,
diff --git a/block/vdi.c b/block/vdi.c
index 4b10aac..2e6f31c 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -490,7 +490,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
     /* Disable migration when vdi images are used */
     error_set(&s->migration_blocker,
               QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
-              "vdi", bs->device_name, "live migration");
+              "vdi", bdrv_get_device_name(bs), "live migration");
     migrate_add_blocker(s->migration_blocker);
 
     return 0;
diff --git a/block/vhdx.c b/block/vhdx.c
index 87c99fc..8bf1af1 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1003,7 +1003,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
     /* Disable migration when VHDX images are used */
     error_set(&s->migration_blocker,
             QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
-            "vhdx", bs->device_name, "live migration");
+            "vhdx", bdrv_get_device_name(bs), "live migration");
     migrate_add_blocker(s->migration_blocker);
 
     return 0;
diff --git a/block/vmdk.c b/block/vmdk.c
index a1cb911..7bc1474 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -657,7 +657,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
         snprintf(buf, sizeof(buf), "VMDK version %" PRId32,
                  le32_to_cpu(header.version));
         error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
-                  bs->device_name, "vmdk", buf);
+                  bdrv_get_device_name(bs), "vmdk", buf);
         return -ENOTSUP;
     } else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR)) {
         /* VMware KB 2064959 explains that version 3 added support for
@@ -939,7 +939,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
     /* Disable migration when VMDK images are used */
     error_set(&s->migration_blocker,
               QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
-              "vmdk", bs->device_name, "live migration");
+              "vmdk", bdrv_get_device_name(bs), "live migration");
     migrate_add_blocker(s->migration_blocker);
     g_free(buf);
     return 0;
diff --git a/block/vpc.c b/block/vpc.c
index 055efc4..7bb90d5 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -320,7 +320,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
     /* Disable migration when VHD images are used */
     error_set(&s->migration_blocker,
               QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
-              "vpc", bs->device_name, "live migration");
+              "vpc", bdrv_get_device_name(bs), "live migration");
     migrate_add_blocker(s->migration_blocker);
 
     return 0;
diff --git a/block/vvfat.c b/block/vvfat.c
index 6c9fde0..cefe3a4 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -1182,7 +1182,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
     if (s->qcow) {
         error_set(&s->migration_blocker,
                   QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
-                  "vvfat (rw)", bs->device_name, "live migration");
+                  "vvfat (rw)", bdrv_get_device_name(bs), "live migration");
         migrate_add_blocker(s->migration_blocker);
     }
 
diff --git a/blockjob.c b/blockjob.c
index 0689fdd..3af0f6c 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -107,7 +107,8 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
 void block_job_complete(BlockJob *job, Error **errp)
 {
     if (job->paused || job->cancelled || !job->driver->complete) {
-        error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
+        error_set(errp, QERR_BLOCK_JOB_NOT_READY,
+                  bdrv_get_device_name(job->bs));
         return;
     }
 
diff --git a/include/block/block.h b/include/block/block.h
index 8cf9ea3..fb4fff9 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -203,7 +203,6 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
 int bdrv_create(BlockDriver *drv, const char* filename,
                 QemuOpts *opts, Error **errp);
 int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
-BlockDriverState *bdrv_new_named(const char *device_name, Error **errp);
 BlockDriverState *bdrv_new(void);
 void bdrv_make_anon(BlockDriverState *bs);
 void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
@@ -415,7 +414,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key);
 int bdrv_query_missing_keys(void);
 void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
                          void *opaque);
-const char *bdrv_get_device_name(BlockDriverState *bs);
+const char *bdrv_get_device_name(const BlockDriverState *bs);
 int bdrv_get_flags(BlockDriverState *bs);
 int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
                           const uint8_t *buf, int nb_sectors);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index d5de08b..08ccb27 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -394,8 +394,6 @@ struct BlockDriverState {
     char node_name[32];
     /* element of the list of named nodes building the graph */
     QTAILQ_ENTRY(BlockDriverState) node_list;
-    /* Device name is the name associated with the "drive" the guest sees */
-    char device_name[32];
     QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
     int refcnt;
 
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 09/23] block: Merge BlockBackend and BlockDriverState name spaces
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (7 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[] Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo() Markus Armbruster
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

BlockBackend's name space is separate only to keep the patches simple.
Time to merge the two.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block.c               | 11 +++--------
 block/block-backend.c | 10 +++++-----
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/block.c b/block.c
index 61ea15d..34c8f8c 100644
--- a/block.c
+++ b/block.c
@@ -850,7 +850,7 @@ static void bdrv_assign_node_name(BlockDriverState *bs,
     }
 
     /* takes care of avoiding namespaces collisions */
-    if (bdrv_find(node_name)) {
+    if (blk_by_name(node_name)) {
         error_setg(errp, "node-name=%s is conflicting with a device id",
                    node_name);
         return;
@@ -3765,14 +3765,9 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
 /* This function is to find block backend bs */
 BlockDriverState *bdrv_find(const char *name)
 {
-    BlockDriverState *bs;
+    BlockBackend *blk = blk_by_name(name);
 
-    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
-        if (!strcmp(name, bdrv_get_device_name(bs))) {
-            return bs;
-        }
-    }
-    return NULL;
+    return blk ? blk_bs(blk) : NULL;
 }
 
 /* This function is to find a node in the bs graph */
diff --git a/block/block-backend.c b/block/block-backend.c
index 2f10d6a..b2db97b 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -46,6 +46,11 @@ BlockBackend *blk_new(const char *name, Error **errp)
         error_setg(errp, "Device with id '%s' already exists", name);
         return NULL;
     }
+    if (bdrv_find_node(name)) {
+        error_setg(errp, "Device with node-name '%s' already exists", name);
+        return NULL;
+    }
+
     blk->name = g_strdup(name);
     blk->refcnt = 1;
     QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
@@ -67,11 +72,6 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp)
     BlockBackend *blk;
     BlockDriverState *bs;
 
-    if (bdrv_find_node(name)) {
-        error_setg(errp, "Device with node-name '%s' already exists", name);
-        return NULL;
-    }
-
     blk = blk_new(name, errp);
     if (!blk) {
         return NULL;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (8 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 09/23] block: Merge BlockBackend and BlockDriverState name spaces Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-11 12:07   ` Benoît Canet
  2014-09-11 17:06   ` Benoît Canet
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 11/23] block: Rename BlockDriverAIOCB* to BlockAIOCB* Markus Armbruster
                   ` (13 subsequent siblings)
  23 siblings, 2 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 blockdev.c                               |  3 +--
 hw/arm/collie.c                          |  9 +++++----
 hw/arm/gumstix.c                         |  5 +++--
 hw/arm/mainstone.c                       |  8 ++++----
 hw/arm/musicpal.c                        | 11 ++++++-----
 hw/arm/nseries.c                         |  6 ++++--
 hw/arm/omap1.c                           |  4 +++-
 hw/arm/omap2.c                           |  4 +++-
 hw/arm/omap_sx1.c                        |  9 +++++----
 hw/arm/pxa2xx.c                          |  7 +++++--
 hw/arm/spitz.c                           |  4 +++-
 hw/arm/versatilepb.c                     |  4 +++-
 hw/arm/vexpress.c                        |  4 +++-
 hw/arm/xilinx_zynq.c                     |  4 +++-
 hw/arm/z2.c                              |  7 ++++---
 hw/block/fdc.c                           | 16 +++++++++++-----
 hw/block/m25p80.c                        |  5 +++--
 hw/block/xen_disk.c                      |  2 +-
 hw/cris/axis_dev88.c                     |  3 ++-
 hw/display/tc6393xb.c                    |  4 +++-
 hw/i386/pc_sysfw.c                       |  3 ++-
 hw/ide/piix.c                            |  6 ++++--
 hw/ide/qdev.c                            |  4 +++-
 hw/isa/pc87312.c                         |  7 +++++--
 hw/lm32/lm32_boards.c                    | 13 +++++++------
 hw/lm32/milkymist.c                      |  7 ++++---
 hw/microblaze/petalogix_ml605_mmu.c      |  5 +++--
 hw/microblaze/petalogix_s3adsp1800_mmu.c |  5 +++--
 hw/mips/mips_malta.c                     |  4 +++-
 hw/mips/mips_r4k.c                       |  5 +++--
 hw/pci/pci-hotplug-old.c                 |  9 ++++++---
 hw/ppc/ppc405_boards.c                   | 25 ++++++++++++++++---------
 hw/ppc/spapr.c                           |  4 +++-
 hw/ppc/virtex_ml507.c                    |  5 +++--
 hw/scsi/scsi-bus.c                       |  5 +++--
 hw/sd/milkymist-memcard.c                |  7 +++++--
 hw/sd/pl181.c                            |  3 ++-
 hw/sd/sdhci.c                            |  3 ++-
 hw/sd/ssi-sd.c                           |  3 ++-
 hw/sh4/r2d.c                             |  5 +++--
 hw/usb/dev-storage.c                     |  4 +++-
 hw/xtensa/xtfpga.c                       |  4 +++-
 include/sysemu/blockdev.h                |  1 -
 43 files changed, 163 insertions(+), 93 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 353563e..5c75abd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -219,7 +219,7 @@ static void bdrv_format_print(void *opaque, const char *name)
 
 void drive_del(DriveInfo *dinfo)
 {
-    blk_unref(dinfo->bdrv->blk);
+    blk_unref(blk_by_legacy_dinfo(dinfo));
 }
 
 typedef struct {
@@ -472,7 +472,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
 
     dinfo = g_malloc0(sizeof(*dinfo));
     dinfo->id = g_strdup(qemu_opts_id(opts));
-    dinfo->bdrv = bs;
     blk_set_legacy_dinfo(blk, dinfo);
 
     if (!file || !*file) {
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
index ed7851f..0247290 100644
--- a/hw/arm/collie.c
+++ b/hw/arm/collie.c
@@ -15,6 +15,7 @@
 #include "strongarm.h"
 #include "hw/arm/arm.h"
 #include "hw/block/flash.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
@@ -41,13 +42,13 @@ static void collie_init(MachineState *machine)
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
-                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+                    dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                    (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
 
     dinfo = drive_get(IF_PFLASH, 0, 1);
     pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
-                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
+                    dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                    (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
 
     sysbus_create_simple("scoop", 0x40800000, NULL);
 
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
index 3f8465e..49f9339 100644
--- a/hw/arm/gumstix.c
+++ b/hw/arm/gumstix.c
@@ -40,6 +40,7 @@
 #include "hw/block/flash.h"
 #include "hw/devices.h"
 #include "hw/boards.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "sysemu/qtest.h"
@@ -71,7 +72,7 @@ static void connex_init(MachineState *machine)
     be = 0;
 #endif
     if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
-                               dinfo ? dinfo->bdrv : NULL,
+                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
                                sector_len, connex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -109,7 +110,7 @@ static void verdex_init(MachineState *machine)
     be = 0;
 #endif
     if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
-                               dinfo ? dinfo->bdrv : NULL,
+                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
                                sector_len, verdex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
index 44f1873..fb17d85 100644
--- a/hw/arm/mainstone.c
+++ b/hw/arm/mainstone.c
@@ -18,7 +18,7 @@
 #include "hw/devices.h"
 #include "hw/boards.h"
 #include "hw/block/flash.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 #include "sysemu/qtest.h"
@@ -148,9 +148,9 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
         if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
                                    i ? "mainstone.flash1" : "mainstone.flash0",
                                    MAINSTONE_FLASH,
-                                   dinfo->bdrv, sector_len,
-                                   MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
-                                   be)) {
+                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                   sector_len, MAINSTONE_FLASH / sector_len,
+                                   4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory.\n");
             exit(1);
         }
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 6a134f2..6a41d9c 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -22,6 +22,7 @@
 #include "hw/block/flash.h"
 #include "ui/console.h"
 #include "hw/i2c/i2c.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "ui/pixel_ops.h"
@@ -1630,7 +1631,9 @@ static void musicpal_init(MachineState *machine)
     /* Register flash */
     dinfo = drive_get(IF_PFLASH, 0, 0);
     if (dinfo) {
-        flash_size = bdrv_getlength(dinfo->bdrv);
+        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
+
+        flash_size = bdrv_getlength(bs);
         if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
             flash_size != 32*1024*1024) {
             fprintf(stderr, "Invalid flash image size\n");
@@ -1645,16 +1648,14 @@ static void musicpal_init(MachineState *machine)
 #ifdef TARGET_WORDS_BIGENDIAN
         pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
                               "musicpal.flash", flash_size,
-                              dinfo->bdrv, 0x10000,
-                              (flash_size + 0xffff) >> 16,
+                              bs, 0x10000, (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 1);
 #else
         pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
                               "musicpal.flash", flash_size,
-                              dinfo->bdrv, 0x10000,
-                              (flash_size + 0xffff) >> 16,
+                              bs, 0x10000, (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 0);
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index 4f092d6..2536078 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -31,6 +31,7 @@
 #include "hw/hw.h"
 #include "hw/bt.h"
 #include "hw/loader.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
@@ -172,8 +173,9 @@ static void n8x0_nand_setup(struct n800_s *s)
     qdev_prop_set_uint16(s->nand, "version_id", 0);
     qdev_prop_set_int32(s->nand, "shift", 1);
     dinfo = drive_get(IF_MTD, 0, 0);
-    if (dinfo && dinfo->bdrv) {
-        qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv);
+    if (dinfo) {
+        qdev_prop_set_drive_nofail(s->nand, "drive",
+                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
     }
     qdev_init_nofail(s->nand);
     sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index e7cc5d7..e38e07f 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -21,6 +21,7 @@
 #include "hw/arm/omap.h"
 #include "sysemu/sysemu.h"
 #include "hw/arm/soc_dma.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "qemu/range.h"
 #include "hw/sysbus.h"
@@ -3976,7 +3977,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv,
+    s->mmc = omap_mmc_init(0xfffb7800, system_memory,
+                           blk_bs(blk_by_legacy_dinfo(dinfo)),
                            qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
                            &s->drq[OMAP_DMA_MMC_TX],
                     omap_findclk(s, "mmc_ck"));
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
index dc53a7a..e47dd63 100644
--- a/hw/arm/omap2.c
+++ b/hw/arm/omap2.c
@@ -18,6 +18,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/hw.h"
 #include "hw/arm/arm.h"
@@ -2459,7 +2460,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), dinfo->bdrv,
+    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9),
+                    blk_bs(blk_by_legacy_dinfo(dinfo)),
                     qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
                     &s->drq[OMAP24XX_DMA_MMC1_TX],
                     omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
index b4f6da6..f475afc 100644
--- a/hw/arm/omap_sx1.c
+++ b/hw/arm/omap_sx1.c
@@ -31,6 +31,7 @@
 #include "hw/boards.h"
 #include "hw/arm/arm.h"
 #include "hw/block/flash.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/qtest.h"
 #include "exec/address-spaces.h"
@@ -153,8 +154,8 @@ static void sx1_init(MachineState *machine, const int version)
     if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
         if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
                                    "omap_sx1.flash0-1", flash_size,
-                                   dinfo->bdrv, sector_size,
-                                   flash_size / sector_size,
+                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                   sector_size, flash_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
                            fl_idx);
@@ -176,8 +177,8 @@ static void sx1_init(MachineState *machine, const int version)
 
         if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
                                    "omap_sx1.flash1-1", flash1_size,
-                                   dinfo->bdrv, sector_size,
-                                   flash1_size / sector_size,
+                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                   sector_size, flash1_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
                            fl_idx);
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 557e0f1..7ec0da8 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -14,6 +14,7 @@
 #include "hw/i2c/i2c.h"
 #include "hw/ssi.h"
 #include "sysemu/char.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 
 static struct {
@@ -2083,7 +2084,8 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
+                    blk_bs(blk_by_legacy_dinfo(dinfo)),
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
@@ -2214,7 +2216,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
+    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
+                    blk_bs(blk_by_legacy_dinfo(dinfo)),
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 03cc6ce..5d684a2 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -25,6 +25,7 @@
 #include "block/block.h"
 #include "audio/audio.h"
 #include "hw/boards.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
@@ -170,7 +171,8 @@ static int sl_nand_init(SysBusDevice *dev)
 
     s->ctl = 0;
     nand = drive_get(IF_MTD, 0, 0);
-    s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
+    s->nand = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,
+                        s->manf_id, s->chip_id);
 
     memory_region_init_io(&s->iomem, OBJECT(s), &sl_ops, s, "sl", 0x40);
     sysbus_init_mmio(dev, &s->iomem);
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index dea5fc7..c88be6b 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -15,6 +15,7 @@
 #include "hw/pci/pci.h"
 #include "hw/i2c/i2c.h"
 #include "hw/boards.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "hw/block/flash.h"
@@ -337,7 +338,8 @@ static void versatile_init(MachineState *machine, int board_id)
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
-                          VERSATILE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
+                          VERSATILE_FLASH_SIZE,
+                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
                           VERSATILE_FLASH_SECT_SIZE,
                           VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
                           4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index a88732c..a492c22 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -30,6 +30,7 @@
 #include "hw/boards.h"
 #include "hw/loader.h"
 #include "exec/address-spaces.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/block/flash.h"
 #include "sysemu/device_tree.h"
@@ -488,7 +489,8 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
 {
     DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
 
-    if (di && qdev_prop_set_drive(dev, "drive", di->bdrv)) {
+    if (di && qdev_prop_set_drive(dev, "drive",
+                                  blk_bs(blk_by_legacy_dinfo(di)))) {
         abort();
     }
 
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index ba5aa82..78e6934 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -22,6 +22,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/boards.h"
 #include "hw/block/flash.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/loader.h"
 #include "hw/ssi.h"
@@ -162,7 +163,8 @@ static void zynq_init(MachineState *machine)
 
     /* AMD */
     pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE,
+                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          FLASH_SECTOR_SIZE,
                           FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
                           1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
                               0);
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 36b3b50..9b38a2b 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -20,6 +20,7 @@
 #include "hw/boards.h"
 #include "sysemu/sysemu.h"
 #include "hw/block/flash.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "ui/console.h"
 #include "audio/audio.h"
@@ -336,9 +337,9 @@ static void z2_init(MachineState *machine)
 
     if (!pflash_cfi01_register(Z2_FLASH_BASE,
                                NULL, "z2.flash0", Z2_FLASH_SIZE,
-                               dinfo ? dinfo->bdrv : NULL, sector_len,
-                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
-                               be)) {
+                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                               sector_len, Z2_FLASH_SIZE / sector_len,
+                               4, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
         exit(1);
     }
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 490d127..19f215f 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -33,6 +33,7 @@
 #include "qemu/timer.h"
 #include "hw/isa/isa.h"
 #include "hw/sysbus.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "qemu/log.h"
@@ -2033,10 +2034,12 @@ ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds)
     dev = DEVICE(isadev);
 
     if (fds[0]) {
-        qdev_prop_set_drive_nofail(dev, "driveA", fds[0]->bdrv);
+        qdev_prop_set_drive_nofail(dev, "driveA",
+                                   blk_bs(blk_by_legacy_dinfo(fds[0])));
     }
     if (fds[1]) {
-        qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv);
+        qdev_prop_set_drive_nofail(dev, "driveB",
+                                   blk_bs(blk_by_legacy_dinfo(fds[1])));
     }
     qdev_init_nofail(dev);
 
@@ -2056,10 +2059,12 @@ void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
     fdctrl = &sys->state;
     fdctrl->dma_chann = dma_chann; /* FIXME */
     if (fds[0]) {
-        qdev_prop_set_drive_nofail(dev, "driveA", fds[0]->bdrv);
+        qdev_prop_set_drive_nofail(dev, "driveA",
+                                   blk_bs(blk_by_legacy_dinfo(fds[0])));
     }
     if (fds[1]) {
-        qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv);
+        qdev_prop_set_drive_nofail(dev, "driveB",
+                                   blk_bs(blk_by_legacy_dinfo(fds[1])));
     }
     qdev_init_nofail(dev);
     sbd = SYS_BUS_DEVICE(dev);
@@ -2075,7 +2080,8 @@ void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
 
     dev = qdev_create(NULL, "SUNW,fdtwo");
     if (fds[0]) {
-        qdev_prop_set_drive_nofail(dev, "drive", fds[0]->bdrv);
+        qdev_prop_set_drive_nofail(dev, "drive",
+                                   blk_bs(blk_by_legacy_dinfo(fds[0])));
     }
     qdev_init_nofail(dev);
     sys = SYSBUS_FDC(dev);
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 5893773..78280a8 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -22,6 +22,7 @@
  */
 
 #include "hw/hw.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/ssi.h"
 
@@ -624,9 +625,9 @@ static int m25p80_init(SSISlave *ss)
 
     dinfo = drive_get_next(IF_MTD);
 
-    if (dinfo && dinfo->bdrv) {
+    if (dinfo) {
         DB_PRINT_L(0, "Binding to IF_MTD drive\n");
-        s->bdrv = dinfo->bdrv;
+        s->bdrv = blk_bs(blk_by_legacy_dinfo(dinfo));
 
         /* FIXME: Move to late init */
         if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size,
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 6d474b9..b571bbe 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -877,7 +877,7 @@ static int blk_connect(struct XenDevice *xendev)
     } else {
         /* setup via qemu cmdline -> already setup for us */
         xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n");
-        blkdev->bs = blkdev->dinfo->bdrv;
+        blkdev->bs = blk_bs(blk_by_legacy_dinfo(blkdev->dinfo));
         if (bdrv_is_read_only(blkdev->bs) && !readonly) {
             xen_be_printf(&blkdev->xendev, 0, "Unexpected read-only drive");
             blkdev->bs = NULL;
diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c
index 1849338..280722d 100644
--- a/hw/cris/axis_dev88.c
+++ b/hw/cris/axis_dev88.c
@@ -30,6 +30,7 @@
 #include "hw/loader.h"
 #include "elf.h"
 #include "boot.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "sysemu/qtest.h"
@@ -282,7 +283,7 @@ void axisdev88_init(MachineState *machine)
 
       /* Attach a NAND flash to CS1.  */
     nand = drive_get(IF_MTD, 0, 0);
-    nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
+    nand_state.nand = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,
                                 NAND_MFR_STMICRO, 0x39);
     memory_region_init_io(&nand_state.iomem, NULL, &nand_ops, &nand_state,
                           "nand", 0x05000000);
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
index f4011d2..62d6663 100644
--- a/hw/display/tc6393xb.c
+++ b/hw/display/tc6393xb.c
@@ -15,6 +15,7 @@
 #include "hw/block/flash.h"
 #include "ui/console.h"
 #include "ui/pixel_ops.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 
 #define IRQ_TC6393_NAND		0
@@ -576,7 +577,8 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
     s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);
 
     nand = drive_get(IF_MTD, 0, 0);
-    s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76);
+    s->flash = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,
+                         NAND_MFR_TOSHIBA, 0x76);
 
     memory_region_init_io(&s->iomem, NULL, &tc6393xb_ops, s, "tc6393xb", 0x10000);
     memory_region_add_subregion(sysmem, base, &s->iomem);
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 75a7ebb..6cd264a 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -23,6 +23,7 @@
  * THE SOFTWARE.
  */
 
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "qemu/error-report.h"
 #include "hw/sysbus.h"
@@ -118,7 +119,7 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
          (unit < FLASH_MAP_UNIT_MAX &&
           (pflash_drv = drive_get(IF_PFLASH, 0, unit)) != NULL);
          ++unit) {
-        bdrv = pflash_drv->bdrv;
+        bdrv = blk_bs(blk_by_legacy_dinfo(pflash_drv));
         size = bdrv_getlength(bdrv);
         if (size < 0) {
             fatal_errmsg = g_strdup_printf("failed to get backing file size");
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 49e78a7..c6c256f 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -27,6 +27,7 @@
 #include <hw/i386/pc.h>
 #include <hw/pci/pci.h>
 #include <hw/isa/isa.h>
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
@@ -178,9 +179,10 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
     for (; i < 3; i++) {
         di = drive_get_by_index(IF_IDE, i);
         if (di != NULL && !di->media_cd) {
-            DeviceState *ds = bdrv_get_attached_dev(di->bdrv);
+            BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(di));
+            DeviceState *ds = bdrv_get_attached_dev(bs);
             if (ds) {
-                bdrv_detach_dev(di->bdrv, ds);
+                bdrv_detach_dev(bs, ds);
             }
             pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
             drive_del(di);
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index efab95b..75e8eb3 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -20,6 +20,7 @@
 #include "sysemu/dma.h"
 #include "qemu/error-report.h"
 #include <hw/ide/internal.h>
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/block/block.h"
 #include "sysemu/sysemu.h"
@@ -116,7 +117,8 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
 
     dev = qdev_create(&bus->qbus, drive->media_cd ? "ide-cd" : "ide-hd");
     qdev_prop_set_uint32(dev, "unit", unit);
-    qdev_prop_set_drive_nofail(dev, "drive", drive->bdrv);
+    qdev_prop_set_drive_nofail(dev, "drive",
+                               blk_bs(blk_by_legacy_dinfo(drive)));
     qdev_init_nofail(dev);
     return DO_UPCAST(IDEDevice, qdev, dev);
 }
diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c
index 9327c53..b691a0c 100644
--- a/hw/isa/pc87312.c
+++ b/hw/isa/pc87312.c
@@ -25,6 +25,7 @@
 
 #include "hw/isa/pc87312.h"
 #include "qemu/error-report.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/char.h"
@@ -320,11 +321,13 @@ static void pc87312_realize(DeviceState *dev, Error **errp)
         qdev_prop_set_uint32(d, "irq", 6);
         drive = drive_get(IF_FLOPPY, 0, 0);
         if (drive != NULL) {
-            qdev_prop_set_drive_nofail(d, "driveA", drive->bdrv);
+            qdev_prop_set_drive_nofail(d, "driveA",
+                                       blk_bs(blk_by_legacy_dinfo(drive)));
         }
         drive = drive_get(IF_FLOPPY, 0, 1);
         if (drive != NULL) {
-            qdev_prop_set_drive_nofail(d, "driveB", drive->bdrv);
+            qdev_prop_set_drive_nofail(d, "driveB",
+                                       blk_bs(blk_by_legacy_dinfo(drive)));
         }
         qdev_init_nofail(d);
         s->fdc.dev = isa;
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
index 0e01340..17c5610 100644
--- a/hw/lm32/lm32_boards.c
+++ b/hw/lm32/lm32_boards.c
@@ -23,6 +23,7 @@
 #include "hw/devices.h"
 #include "hw/boards.h"
 #include "hw/loader.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "elf.h"
 #include "lm32_hwsetup.h"
@@ -118,9 +119,9 @@ static void lm32_evr_init(MachineState *machine)
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
     pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
-                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
-                          flash_size / flash_sector_size, 1, 2,
-                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
+                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          flash_sector_size, flash_size / flash_sector_size,
+                          1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
 
     /* create irq lines */
     cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1);
@@ -220,9 +221,9 @@ static void lm32_uclinux_init(MachineState *machine)
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
     pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
-                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
-                          flash_size / flash_sector_size, 1, 2,
-                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
+                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          flash_sector_size, flash_size / flash_sector_size,
+                          1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
 
     /* create irq lines */
     cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 81c3933..904b9c0 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -26,6 +26,7 @@
 #include "hw/boards.h"
 #include "hw/loader.h"
 #include "elf.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "milkymist-hw.h"
 #include "lm32.h"
@@ -125,9 +126,9 @@ milkymist_init(MachineState *machine)
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Numonyx JS28F256J3F105 */
     pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
-                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
-                          flash_size / flash_sector_size, 2,
-                          0x00, 0x89, 0x00, 0x1d, 1);
+                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          flash_sector_size, flash_size / flash_sector_size,
+                          2, 0x00, 0x89, 0x00, 0x1d, 1);
 
     /* create irq lines */
     cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1);
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 6843abf..2974791 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -32,6 +32,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/devices.h"
 #include "hw/boards.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/char/serial.h"
 #include "exec/address-spaces.h"
@@ -112,8 +113,8 @@ petalogix_ml605_init(MachineState *machine)
      * 10th paremeter 0 means little-endian */
     pflash_cfi01_register(FLASH_BASEADDR,
                           NULL, "petalogix_ml605.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                          FLASH_SIZE >> 16,
+                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          (64 * 1024), FLASH_SIZE >> 16,
                           2, 0x89, 0x18, 0x0000, 0x0, 0);
 
 
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index 49dc6d1..a69301f 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -30,6 +30,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/devices.h"
 #include "hw/boards.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
@@ -92,8 +93,8 @@ petalogix_s3adsp1800_init(MachineState *machine)
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(FLASH_BASEADDR,
                           NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                          FLASH_SIZE >> 16,
+                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          (64 * 1024), FLASH_SIZE >> 16,
                           1, 0x89, 0x18, 0x0000, 0x0, 1);
 
     dev = qdev_create(NULL, "xlnx.xps-intc");
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index cfb60af..9f84ad6 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -44,6 +44,7 @@
 #include "elf.h"
 #include "hw/timer/mc146818rtc.h"
 #include "hw/timer/i8254.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "hw/sysbus.h"             /* SysBusDevice */
@@ -1035,7 +1036,8 @@ void mips_malta_init(MachineState *machine)
     }
 #endif
     fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
-                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
+                               BIOS_SIZE,
+                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
                                65536, fl_sectors,
                                4, 0x0000, 0x0000, 0x0000, 0x0000, be);
     bios = pflash_cfi01_get_memory(fl);
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index 7120293..6fd69b9 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -24,6 +24,7 @@
 #include "elf.h"
 #include "hw/timer/mc146818rtc.h"
 #include "hw/timer/i8254.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "sysemu/qtest.h"
@@ -240,8 +241,8 @@ void mips_r4k_init(MachineState *machine)
     } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
         uint32_t mips_rom = 0x00400000;
         if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
-                                   dinfo->bdrv, sector_len,
-                                   mips_rom / sector_len,
+                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                   sector_len, mips_rom / sector_len,
                                    4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory.\n");
 	}
diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c
index cf2caeb..e4d51de 100644
--- a/hw/pci/pci-hotplug-old.c
+++ b/hw/pci/pci-hotplug-old.c
@@ -33,6 +33,7 @@
 #include "hw/scsi/scsi.h"
 #include "hw/virtio/virtio-blk.h"
 #include "qemu/config-file.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "qapi/error.h"
 
@@ -126,8 +127,9 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
      */
     dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
     dinfo->bus = scsibus->busnr;
-    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
-                                        false, -1, NULL, NULL);
+    scsidev = scsi_bus_legacy_add_drive(scsibus,
+                                        blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                        dinfo->unit, false, -1, NULL, NULL);
     if (!scsidev) {
         return -1;
     }
@@ -247,7 +249,8 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
             return NULL;
         }
         dev = pci_create(bus, devfn, "virtio-blk-pci");
-        if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
+        if (qdev_prop_set_drive(&dev->qdev, "drive",
+                                blk_bs(blk_by_legacy_dinfo(dinfo))) < 0) {
             object_unparent(OBJECT(dev));
             dev = NULL;
             break;
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 11d3379..7ff5ee5 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -33,6 +33,7 @@
 #include "qemu/log.h"
 #include "qemu/error-report.h"
 #include "hw/loader.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
@@ -225,17 +226,19 @@ static void ref405ep_init(MachineState *machine)
 #ifdef USE_FLASH_BIOS
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
-        bios_size = bdrv_getlength(dinfo->bdrv);
+        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
+
+        bios_size = bdrv_getlength(bs);
         fl_sectors = (bios_size + 65535) >> 16;
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size %lx"
                " at addr %lx '%s' %d\n",
                fl_idx, bios_size, -bios_size,
-               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+               bdrv_get_device_name(bs), fl_sectors);
 #endif
         pflash_cfi02_register((uint32_t)(-bios_size),
                               NULL, "ef405ep.bios", bios_size,
-                              dinfo->bdrv, 65536, fl_sectors, 1,
+                              bs, 65536, fl_sectors, 1,
                               2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
         fl_idx++;
@@ -547,7 +550,9 @@ static void taihu_405ep_init(MachineState *machine)
 #if defined(USE_FLASH_BIOS)
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
-        bios_size = bdrv_getlength(dinfo->bdrv);
+        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
+
+        bios_size = bdrv_getlength(bs);
         /* XXX: should check that size is 2MB */
         //        bios_size = 2 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
@@ -555,11 +560,11 @@ static void taihu_405ep_init(MachineState *machine)
         printf("Register parallel flash %d size %lx"
                " at addr %lx '%s' %d\n",
                fl_idx, bios_size, -bios_size,
-               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+               bdrv_get_device_name(bs), fl_sectors);
 #endif
         pflash_cfi02_register((uint32_t)(-bios_size),
                               NULL, "taihu_405ep.bios", bios_size,
-                              dinfo->bdrv, 65536, fl_sectors, 1,
+                              bs, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
         fl_idx++;
@@ -593,7 +598,9 @@ static void taihu_405ep_init(MachineState *machine)
     /* Register Linux flash */
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
-        bios_size = bdrv_getlength(dinfo->bdrv);
+        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
+
+        bios_size = bdrv_getlength(bs);
         /* XXX: should check that size is 32MB */
         bios_size = 32 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
@@ -601,10 +608,10 @@ static void taihu_405ep_init(MachineState *machine)
         printf("Register parallel flash %d size %lx"
                " at addr " TARGET_FMT_lx " '%s'\n",
                fl_idx, bios_size, (target_ulong)0xfc000000,
-               bdrv_get_device_name(dinfo->bdrv));
+               bdrv_get_device_name(bs));
 #endif
         pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
-                              dinfo->bdrv, 65536, fl_sectors, 1,
+                              bs, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
         fl_idx++;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 2ab4460..a577812 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -29,6 +29,7 @@
 #include "hw/fw-path-provider.h"
 #include "elf.h"
 #include "net/net.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/cpus.h"
 #include "sysemu/kvm.h"
@@ -925,7 +926,8 @@ static void spapr_create_nvram(sPAPREnvironment *spapr)
     DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
 
     if (dinfo) {
-        qdev_prop_set_drive_nofail(dev, "drive", dinfo->bdrv);
+        qdev_prop_set_drive_nofail(dev, "drive",
+                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
     }
 
     qdev_init_nofail(dev);
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index 0de5148..a0ce447 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -39,6 +39,7 @@
 #include "hw/ppc/ppc4xx.h"
 #include "ppc405.h"
 
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "qapi/qmp/qerror.h"
 
@@ -227,8 +228,8 @@ static void virtex_init(MachineState *machine)
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(PFLASH_BASEADDR, NULL, "virtex.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
-                          FLASH_SIZE >> 16,
+                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          (64 * 1024), FLASH_SIZE >> 16,
                           1, 0x89, 0x18, 0x0000, 0x0, 1);
 
     cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 954c607..f5156ae 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -3,6 +3,7 @@
 #include "hw/scsi/scsi.h"
 #include "block/scsi.h"
 #include "hw/qdev.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "trace.h"
 #include "sysemu/dma.h"
@@ -267,8 +268,8 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp)
             continue;
         }
         qemu_opts_loc_restore(dinfo->opts);
-        scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL,
-                                  &err);
+        scsi_bus_legacy_add_drive(bus, blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                  unit, false, -1, NULL, &err);
         if (err != NULL) {
             error_report("%s", error_get_pretty(err));
             error_propagate(errp, err);
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 2a40f92..501aa3a 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -26,6 +26,7 @@
 #include "sysemu/sysemu.h"
 #include "trace.h"
 #include "qemu/error-report.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/sd.h"
 
@@ -252,14 +253,16 @@ static int milkymist_memcard_init(SysBusDevice *dev)
 {
     MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
     DriveInfo *dinfo;
+    BlockDriverState *bs;
 
     dinfo = drive_get_next(IF_SD);
-    s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false);
+    bs = dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL;
+    s->card = sd_init(bs, false);
     if (s->card == NULL) {
         return -1;
     }
 
-    s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0;
+    s->enabled = bs && bdrv_is_inserted(bs);
 
     memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s,
             "milkymist-memcard", R_MAX * 4);
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 462558b..0501d40 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -7,6 +7,7 @@
  * This code is licensed under the GPL.
  */
 
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/sysbus.h"
 #include "hw/sd.h"
@@ -490,7 +491,7 @@ static int pl181_init(SysBusDevice *sbd)
     sysbus_init_irq(sbd, &s->irq[1]);
     qdev_init_gpio_out(dev, s->cardstatus, 2);
     dinfo = drive_get_next(IF_SD);
-    s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false);
+    s->card = sd_init(dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL, false);
     if (s->card == NULL) {
         return -1;
     }
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index f9fe700..0b7d754 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -23,6 +23,7 @@
  */
 
 #include "hw/hw.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/dma.h"
 #include "qemu/timer.h"
@@ -1165,7 +1166,7 @@ static void sdhci_initfn(Object *obj)
     DriveInfo *di;
 
     di = drive_get_next(IF_SD);
-    s->card = sd_init(di ? di->bdrv : NULL, false);
+    s->card = sd_init(di ? blk_bs(blk_by_legacy_dinfo(di)) : NULL, false);
     if (s->card == NULL) {
         exit(1);
     }
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index b012e57..6ae99e4 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -10,6 +10,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/ssi.h"
 #include "hw/sd.h"
@@ -255,7 +256,7 @@ static int ssi_sd_init(SSISlave *d)
 
     s->mode = SSI_SD_CMD;
     dinfo = drive_get_next(IF_SD);
-    s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, true);
+    s->sd = sd_init(dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL, true);
     if (s->sd == NULL) {
         return -1;
     }
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 95c0246..d652619 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -36,6 +36,7 @@
 #include "hw/loader.h"
 #include "hw/usb.h"
 #include "hw/block/flash.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
@@ -290,8 +291,8 @@ static void r2d_init(MachineState *machine)
     /* onboard flash memory */
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
-                          dinfo ? dinfo->bdrv : NULL, (16 * 1024),
-                          FLASH_SIZE >> 16,
+                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          (16 * 1024), FLASH_SIZE >> 16,
                           1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
                           0x555, 0x2aa, 0);
 
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index ae4efcb..525f657 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -16,6 +16,7 @@
 #include "ui/console.h"
 #include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 
 //#define DEBUG_MSD
@@ -702,7 +703,8 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
     if (!dev) {
         return NULL;
     }
-    if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
+    if (qdev_prop_set_drive(&dev->qdev, "drive",
+                            blk_bs(blk_by_legacy_dinfo(dinfo))) < 0) {
         object_unparent(OBJECT(dev));
         return NULL;
     }
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index a2dff5a..7c4719e 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -35,6 +35,7 @@
 #include "net/net.h"
 #include "hw/sysbus.h"
 #include "hw/block/flash.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/char.h"
 #include "sysemu/device_tree.h"
@@ -229,7 +230,8 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
     if (dinfo) {
         flash = pflash_cfi01_register(board->flash_base,
                 NULL, "lx60.io.flash", board->flash_size,
-                dinfo->bdrv, board->flash_sector_size,
+                blk_bs(blk_by_legacy_dinfo(dinfo)),
+                board->flash_sector_size,
                 board->flash_size / board->flash_sector_size,
                 4, 0x0000, 0x0000, 0x0000, 0x0000, be);
         if (flash == NULL) {
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 2ed297b..75f6ac6 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -30,7 +30,6 @@ typedef enum {
 } BlockInterfaceType;
 
 struct DriveInfo {
-    BlockDriverState *bdrv;
     char *id;
     const char *devaddr;
     BlockInterfaceType type;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 11/23] block: Rename BlockDriverAIOCB* to BlockAIOCB*
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (9 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo() Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-11 12:15   ` Benoît Canet
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 12/23] virtio-blk: Drop redundant VirtIOBlock member conf Markus Armbruster
                   ` (12 subsequent siblings)
  23 siblings, 1 reply; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

I'll use BlockDriverAIOCB with block backends shortly, and the name is
going to fit badly there.  It's a block layer thing anyway, not just a
block driver thing.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block-migration.c           |   2 +-
 block.c                     | 151 ++++++++++++++++++++++----------------------
 block/archipelago.c         |  30 ++++-----
 block/backup.c              |   2 +-
 block/blkdebug.c            |  22 +++----
 block/blkverify.c           |  20 +++---
 block/commit.c              |   2 +-
 block/curl.c                |   8 +--
 block/iscsi.c               |   8 +--
 block/linux-aio.c           |   8 +--
 block/mirror.c              |   6 +-
 block/qed-gencb.c           |   4 +-
 block/qed-table.c           |  10 +--
 block/qed.c                 |  46 +++++++-------
 block/qed.h                 |  12 ++--
 block/quorum.c              |  38 +++++------
 block/raw-aio.h             |   8 +--
 block/raw-posix.c           |  32 +++++-----
 block/raw-win32.c           |  16 ++---
 block/raw_bsd.c             |   8 +--
 block/rbd.c                 |  58 ++++++++---------
 block/sheepdog.c            |   4 +-
 block/stream.c              |   2 +-
 block/win32-aio.c           |   8 +--
 blockjob.c                  |   4 +-
 dma-helpers.c               |  24 +++----
 hw/block/nvme.h             |   2 +-
 hw/ide/ahci.c               |   2 +-
 hw/ide/ahci.h               |   2 +-
 hw/ide/core.c               |  12 ++--
 hw/ide/internal.h           |  12 ++--
 hw/ide/macio.c              |   2 +-
 hw/ide/pci.c                |   2 +-
 hw/ide/pci.h                |   2 +-
 hw/ppc/mac.h                |   2 +-
 hw/scsi/scsi-generic.c      |   2 +-
 include/block/aio.h         |  12 ++--
 include/block/block.h       |  36 +++++------
 include/block/block_int.h   |  30 ++++-----
 include/block/blockjob.h    |   4 +-
 include/block/thread-pool.h |   4 +-
 include/hw/scsi/scsi.h      |   2 +-
 include/monitor/monitor.h   |   4 +-
 include/sysemu/dma.h        |  26 ++++----
 monitor.c                   |   6 +-
 tests/test-thread-pool.c    |   2 +-
 thread-pool.c               |   8 +--
 47 files changed, 353 insertions(+), 354 deletions(-)

diff --git a/block-migration.c b/block-migration.c
index da30e93..08db01a 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -72,7 +72,7 @@ typedef struct BlkMigBlock {
     int nr_sectors;
     struct iovec iov;
     QEMUIOVector qiov;
-    BlockDriverAIOCB *aiocb;
+    BlockAIOCB *aiocb;
 
     /* Protected by block migration lock.  */
     int ret;
diff --git a/block.c b/block.c
index 34c8f8c..f71b87c 100644
--- a/block.c
+++ b/block.c
@@ -61,12 +61,12 @@ struct BdrvDirtyBitmap {
 #define COROUTINE_POOL_RESERVATION 64 /* number of coroutines to reserve */
 
 static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load);
-static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
+static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque);
-static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
+        BlockCompletionFunc *cb, void *opaque);
+static BlockAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque);
+        BlockCompletionFunc *cb, void *opaque);
 static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs,
                                          int64_t sector_num, int nb_sectors,
                                          QEMUIOVector *iov);
@@ -79,14 +79,14 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs,
 static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
     int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
     BdrvRequestFlags flags);
-static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
-                                               int64_t sector_num,
-                                               QEMUIOVector *qiov,
-                                               int nb_sectors,
-                                               BdrvRequestFlags flags,
-                                               BlockDriverCompletionFunc *cb,
-                                               void *opaque,
-                                               bool is_write);
+static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
+                                         int64_t sector_num,
+                                         QEMUIOVector *qiov,
+                                         int nb_sectors,
+                                         BdrvRequestFlags flags,
+                                         BlockCompletionFunc *cb,
+                                         void *opaque,
+                                         bool is_write);
 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);
@@ -4383,9 +4383,9 @@ int bdrv_get_backing_file_depth(BlockDriverState *bs)
 /**************************************************************/
 /* async I/Os */
 
-BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
-                                 QEMUIOVector *qiov, int nb_sectors,
-                                 BlockDriverCompletionFunc *cb, void *opaque)
+BlockAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
+                           QEMUIOVector *qiov, int nb_sectors,
+                           BlockCompletionFunc *cb, void *opaque)
 {
     trace_bdrv_aio_readv(bs, sector_num, nb_sectors, opaque);
 
@@ -4393,9 +4393,9 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
                                  cb, opaque, false);
 }
 
-BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
-                                  QEMUIOVector *qiov, int nb_sectors,
-                                  BlockDriverCompletionFunc *cb, void *opaque)
+BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
+                            QEMUIOVector *qiov, int nb_sectors,
+                            BlockCompletionFunc *cb, void *opaque)
 {
     trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque);
 
@@ -4403,9 +4403,9 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
                                  cb, opaque, true);
 }
 
-BlockDriverAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs,
+BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors, BdrvRequestFlags flags,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     trace_bdrv_aio_write_zeroes(bs, sector_num, nb_sectors, flags, opaque);
 
@@ -4420,7 +4420,7 @@ typedef struct MultiwriteCB {
     int num_requests;
     int num_callbacks;
     struct {
-        BlockDriverCompletionFunc *cb;
+        BlockCompletionFunc *cb;
         void *opaque;
         QEMUIOVector *free_qiov;
     } callbacks[];
@@ -4597,7 +4597,7 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
     return 0;
 }
 
-void bdrv_aio_cancel(BlockDriverAIOCB *acb)
+void bdrv_aio_cancel(BlockAIOCB *acb)
 {
     acb->aiocb_info->cancel(acb);
 }
@@ -4605,33 +4605,32 @@ void bdrv_aio_cancel(BlockDriverAIOCB *acb)
 /**************************************************************/
 /* async block device emulation */
 
-typedef struct BlockDriverAIOCBSync {
-    BlockDriverAIOCB common;
+typedef struct BlockAIOCBSync {
+    BlockAIOCB common;
     QEMUBH *bh;
     int ret;
     /* vector translation state */
     QEMUIOVector *qiov;
     uint8_t *bounce;
     int is_write;
-} BlockDriverAIOCBSync;
+} BlockAIOCBSync;
 
-static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
+static void bdrv_aio_cancel_em(BlockAIOCB *blockacb)
 {
-    BlockDriverAIOCBSync *acb =
-        container_of(blockacb, BlockDriverAIOCBSync, common);
+    BlockAIOCBSync *acb = container_of(blockacb, BlockAIOCBSync, common);
     qemu_bh_delete(acb->bh);
     acb->bh = NULL;
     qemu_aio_release(acb);
 }
 
 static const AIOCBInfo bdrv_em_aiocb_info = {
-    .aiocb_size         = sizeof(BlockDriverAIOCBSync),
+    .aiocb_size         = sizeof(BlockAIOCBSync),
     .cancel             = bdrv_aio_cancel_em,
 };
 
 static void bdrv_aio_bh_cb(void *opaque)
 {
-    BlockDriverAIOCBSync *acb = opaque;
+    BlockAIOCBSync *acb = opaque;
 
     if (!acb->is_write && acb->ret >= 0) {
         qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size);
@@ -4643,16 +4642,16 @@ static void bdrv_aio_bh_cb(void *opaque)
     qemu_aio_release(acb);
 }
 
-static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
-                                            int64_t sector_num,
-                                            QEMUIOVector *qiov,
-                                            int nb_sectors,
-                                            BlockDriverCompletionFunc *cb,
-                                            void *opaque,
-                                            int is_write)
+static BlockAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
+                                      int64_t sector_num,
+                                      QEMUIOVector *qiov,
+                                      int nb_sectors,
+                                      BlockCompletionFunc *cb,
+                                      void *opaque,
+                                      int is_write)
 
 {
-    BlockDriverAIOCBSync *acb;
+    BlockAIOCBSync *acb;
 
     acb = qemu_aio_get(&bdrv_em_aiocb_info, bs, cb, opaque);
     acb->is_write = is_write;
@@ -4674,34 +4673,34 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
     return &acb->common;
 }
 
-static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
+static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
 }
 
-static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
+static BlockAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
 }
 
 
-typedef struct BlockDriverAIOCBCoroutine {
-    BlockDriverAIOCB common;
+typedef struct BlockAIOCBCoroutine {
+    BlockAIOCB common;
     BlockRequest req;
     bool is_write;
     bool *done;
     QEMUBH* bh;
-} BlockDriverAIOCBCoroutine;
+} BlockAIOCBCoroutine;
 
-static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
+static void bdrv_aio_co_cancel_em(BlockAIOCB *blockacb)
 {
     AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
-    BlockDriverAIOCBCoroutine *acb =
-        container_of(blockacb, BlockDriverAIOCBCoroutine, common);
+    BlockAIOCBCoroutine *acb =
+        container_of(blockacb, BlockAIOCBCoroutine, common);
     bool done = false;
 
     acb->done = &done;
@@ -4711,13 +4710,13 @@ static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
 }
 
 static const AIOCBInfo bdrv_em_co_aiocb_info = {
-    .aiocb_size         = sizeof(BlockDriverAIOCBCoroutine),
+    .aiocb_size         = sizeof(BlockAIOCBCoroutine),
     .cancel             = bdrv_aio_co_cancel_em,
 };
 
 static void bdrv_co_em_bh(void *opaque)
 {
-    BlockDriverAIOCBCoroutine *acb = opaque;
+    BlockAIOCBCoroutine *acb = opaque;
 
     acb->common.cb(acb->common.opaque, acb->req.error);
 
@@ -4732,7 +4731,7 @@ static void bdrv_co_em_bh(void *opaque)
 /* Invoke bdrv_co_do_readv/bdrv_co_do_writev */
 static void coroutine_fn bdrv_co_do_rw(void *opaque)
 {
-    BlockDriverAIOCBCoroutine *acb = opaque;
+    BlockAIOCBCoroutine *acb = opaque;
     BlockDriverState *bs = acb->common.bs;
 
     if (!acb->is_write) {
@@ -4747,17 +4746,17 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque)
     qemu_bh_schedule(acb->bh);
 }
 
-static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
-                                               int64_t sector_num,
-                                               QEMUIOVector *qiov,
-                                               int nb_sectors,
-                                               BdrvRequestFlags flags,
-                                               BlockDriverCompletionFunc *cb,
-                                               void *opaque,
-                                               bool is_write)
+static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
+                                         int64_t sector_num,
+                                         QEMUIOVector *qiov,
+                                         int nb_sectors,
+                                         BdrvRequestFlags flags,
+                                         BlockCompletionFunc *cb,
+                                         void *opaque,
+                                         bool is_write)
 {
     Coroutine *co;
-    BlockDriverAIOCBCoroutine *acb;
+    BlockAIOCBCoroutine *acb;
 
     acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
     acb->req.sector = sector_num;
@@ -4775,7 +4774,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
 
 static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque)
 {
-    BlockDriverAIOCBCoroutine *acb = opaque;
+    BlockAIOCBCoroutine *acb = opaque;
     BlockDriverState *bs = acb->common.bs;
 
     acb->req.error = bdrv_co_flush(bs);
@@ -4783,13 +4782,13 @@ static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque)
     qemu_bh_schedule(acb->bh);
 }
 
-BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
-        BlockDriverCompletionFunc *cb, void *opaque)
+BlockAIOCB *bdrv_aio_flush(BlockDriverState *bs,
+        BlockCompletionFunc *cb, void *opaque)
 {
     trace_bdrv_aio_flush(bs, opaque);
 
     Coroutine *co;
-    BlockDriverAIOCBCoroutine *acb;
+    BlockAIOCBCoroutine *acb;
 
     acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
     acb->done = NULL;
@@ -4802,7 +4801,7 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
 
 static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque)
 {
-    BlockDriverAIOCBCoroutine *acb = opaque;
+    BlockAIOCBCoroutine *acb = opaque;
     BlockDriverState *bs = acb->common.bs;
 
     acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors);
@@ -4810,12 +4809,12 @@ static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque)
     qemu_bh_schedule(acb->bh);
 }
 
-BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
+BlockAIOCB *bdrv_aio_discard(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     Coroutine *co;
-    BlockDriverAIOCBCoroutine *acb;
+    BlockAIOCBCoroutine *acb;
 
     trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque);
 
@@ -4841,9 +4840,9 @@ void bdrv_init_with_whitelist(void)
 }
 
 void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
-                   BlockDriverCompletionFunc *cb, void *opaque)
+                   BlockCompletionFunc *cb, void *opaque)
 {
-    BlockDriverAIOCB *acb;
+    BlockAIOCB *acb;
 
     acb = g_slice_alloc(aiocb_info->aiocb_size);
     acb->aiocb_info = aiocb_info;
@@ -4855,7 +4854,7 @@ void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
 
 void qemu_aio_release(void *p)
 {
-    BlockDriverAIOCB *acb = p;
+    BlockAIOCB *acb = p;
     g_slice_free1(acb->aiocb_info->aiocb_size, acb);
 }
 
@@ -4882,7 +4881,7 @@ static int coroutine_fn bdrv_co_io_em(BlockDriverState *bs, int64_t sector_num,
     CoroutineIOCompletion co = {
         .coroutine = qemu_coroutine_self(),
     };
-    BlockDriverAIOCB *acb;
+    BlockAIOCB *acb;
 
     if (is_write) {
         acb = bs->drv->bdrv_aio_writev(bs, sector_num, iov, nb_sectors,
@@ -4948,7 +4947,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
     if (bs->drv->bdrv_co_flush_to_disk) {
         ret = bs->drv->bdrv_co_flush_to_disk(bs);
     } else if (bs->drv->bdrv_aio_flush) {
-        BlockDriverAIOCB *acb;
+        BlockAIOCB *acb;
         CoroutineIOCompletion co = {
             .coroutine = qemu_coroutine_self(),
         };
@@ -5131,7 +5130,7 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
         if (bs->drv->bdrv_co_discard) {
             ret = bs->drv->bdrv_co_discard(bs, sector_num, num);
         } else {
-            BlockDriverAIOCB *acb;
+            BlockAIOCB *acb;
             CoroutineIOCompletion co = {
                 .coroutine = qemu_coroutine_self(),
             };
@@ -5257,9 +5256,9 @@ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
     return -ENOTSUP;
 }
 
-BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
+BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
         unsigned long int req, void *buf,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     BlockDriver *drv = bs->drv;
 
diff --git a/block/archipelago.c b/block/archipelago.c
index 22a7daa..9bbae4e 100644
--- a/block/archipelago.c
+++ b/block/archipelago.c
@@ -87,7 +87,7 @@ typedef enum {
 } ARCHIPCmd;
 
 typedef struct ArchipelagoAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     QEMUBH *bh;
     struct BDRVArchipelagoState *s;
     QEMUIOVector *qiov;
@@ -724,7 +724,7 @@ static int qemu_archipelago_create(const char *filename,
     return ret;
 }
 
-static void qemu_archipelago_aio_cancel(BlockDriverAIOCB *blockacb)
+static void qemu_archipelago_aio_cancel(BlockAIOCB *blockacb)
 {
     ArchipelagoAIOCB *aio_cb = (ArchipelagoAIOCB *) blockacb;
     aio_cb->cancelled = true;
@@ -869,13 +869,13 @@ err_exit:
     return ret;
 }
 
-static BlockDriverAIOCB *qemu_archipelago_aio_rw(BlockDriverState *bs,
-                                                 int64_t sector_num,
-                                                 QEMUIOVector *qiov,
-                                                 int nb_sectors,
-                                                 BlockDriverCompletionFunc *cb,
-                                                 void *opaque,
-                                                 int op)
+static BlockAIOCB *qemu_archipelago_aio_rw(BlockDriverState *bs,
+                                           int64_t sector_num,
+                                           QEMUIOVector *qiov,
+                                           int nb_sectors,
+                                           BlockCompletionFunc *cb,
+                                           void *opaque,
+                                           int op)
 {
     ArchipelagoAIOCB *aio_cb;
     BDRVArchipelagoState *s = bs->opaque;
@@ -908,17 +908,17 @@ err_exit:
     return NULL;
 }
 
-static BlockDriverAIOCB *qemu_archipelago_aio_readv(BlockDriverState *bs,
+static BlockAIOCB *qemu_archipelago_aio_readv(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     return qemu_archipelago_aio_rw(bs, sector_num, qiov, nb_sectors, cb,
                                    opaque, ARCHIP_OP_READ);
 }
 
-static BlockDriverAIOCB *qemu_archipelago_aio_writev(BlockDriverState *bs,
+static BlockAIOCB *qemu_archipelago_aio_writev(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     return qemu_archipelago_aio_rw(bs, sector_num, qiov, nb_sectors, cb,
                                    opaque, ARCHIP_OP_WRITE);
@@ -1008,8 +1008,8 @@ static QemuOptsList qemu_archipelago_create_opts = {
     }
 };
 
-static BlockDriverAIOCB *qemu_archipelago_aio_flush(BlockDriverState *bs,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static BlockAIOCB *qemu_archipelago_aio_flush(BlockDriverState *bs,
+        BlockCompletionFunc *cb, void *opaque)
 {
     return qemu_archipelago_aio_rw(bs, 0, NULL, 0, cb, opaque,
                                    ARCHIP_OP_FLUSH);
diff --git a/block/backup.c b/block/backup.c
index d0b0225..e334740 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -353,7 +353,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
                   int64_t speed, MirrorSyncMode sync_mode,
                   BlockdevOnError on_source_error,
                   BlockdevOnError on_target_error,
-                  BlockDriverCompletionFunc *cb, void *opaque,
+                  BlockCompletionFunc *cb, void *opaque,
                   Error **errp)
 {
     int64_t len;
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 69b330e..008d3e3 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -41,7 +41,7 @@ typedef struct BDRVBlkdebugState {
 } BDRVBlkdebugState;
 
 typedef struct BlkdebugAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     QEMUBH *bh;
     int ret;
 } BlkdebugAIOCB;
@@ -52,7 +52,7 @@ typedef struct BlkdebugSuspendedReq {
     QLIST_ENTRY(BlkdebugSuspendedReq) next;
 } BlkdebugSuspendedReq;
 
-static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
+static void blkdebug_aio_cancel(BlockAIOCB *blockacb);
 
 static const AIOCBInfo blkdebug_aiocb_info = {
     .aiocb_size = sizeof(BlkdebugAIOCB),
@@ -450,7 +450,7 @@ static void error_callback_bh(void *opaque)
     qemu_aio_release(acb);
 }
 
-static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
+static void blkdebug_aio_cancel(BlockAIOCB *blockacb)
 {
     BlkdebugAIOCB *acb = container_of(blockacb, BlkdebugAIOCB, common);
     if (acb->bh) {
@@ -460,8 +460,8 @@ static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
     qemu_aio_release(acb);
 }
 
-static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
-    BlockDriverCompletionFunc *cb, void *opaque, BlkdebugRule *rule)
+static BlockAIOCB *inject_error(BlockDriverState *bs,
+    BlockCompletionFunc *cb, void *opaque, BlkdebugRule *rule)
 {
     BDRVBlkdebugState *s = bs->opaque;
     int error = rule->options.inject.error;
@@ -486,9 +486,9 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
     return &acb->common;
 }
 
-static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
+static BlockAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
     int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-    BlockDriverCompletionFunc *cb, void *opaque)
+    BlockCompletionFunc *cb, void *opaque)
 {
     BDRVBlkdebugState *s = bs->opaque;
     BlkdebugRule *rule = NULL;
@@ -508,9 +508,9 @@ static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
     return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
 }
 
-static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
+static BlockAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
     int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-    BlockDriverCompletionFunc *cb, void *opaque)
+    BlockCompletionFunc *cb, void *opaque)
 {
     BDRVBlkdebugState *s = bs->opaque;
     BlkdebugRule *rule = NULL;
@@ -530,8 +530,8 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
     return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
 }
 
-static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
-    BlockDriverCompletionFunc *cb, void *opaque)
+static BlockAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
+    BlockCompletionFunc *cb, void *opaque)
 {
     BDRVBlkdebugState *s = bs->opaque;
     BlkdebugRule *rule = NULL;
diff --git a/block/blkverify.c b/block/blkverify.c
index 163064c..d4553cc 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -19,7 +19,7 @@ typedef struct {
 
 typedef struct BlkverifyAIOCB BlkverifyAIOCB;
 struct BlkverifyAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     QEMUBH *bh;
 
     /* Request metadata */
@@ -38,7 +38,7 @@ struct BlkverifyAIOCB {
     void (*verify)(BlkverifyAIOCB *acb);
 };
 
-static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
+static void blkverify_aio_cancel(BlockAIOCB *blockacb)
 {
     BlkverifyAIOCB *acb = (BlkverifyAIOCB *)blockacb;
     AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
@@ -180,7 +180,7 @@ static int64_t blkverify_getlength(BlockDriverState *bs)
 static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write,
                                          int64_t sector_num, QEMUIOVector *qiov,
                                          int nb_sectors,
-                                         BlockDriverCompletionFunc *cb,
+                                         BlockCompletionFunc *cb,
                                          void *opaque)
 {
     BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aiocb_info, bs, cb, opaque);
@@ -248,9 +248,9 @@ static void blkverify_verify_readv(BlkverifyAIOCB *acb)
     }
 }
 
-static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs,
+static BlockAIOCB *blkverify_aio_readv(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     BDRVBlkverifyState *s = bs->opaque;
     BlkverifyAIOCB *acb = blkverify_aio_get(bs, false, sector_num, qiov,
@@ -268,9 +268,9 @@ static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs,
     return &acb->common;
 }
 
-static BlockDriverAIOCB *blkverify_aio_writev(BlockDriverState *bs,
+static BlockAIOCB *blkverify_aio_writev(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     BDRVBlkverifyState *s = bs->opaque;
     BlkverifyAIOCB *acb = blkverify_aio_get(bs, true, sector_num, qiov,
@@ -283,9 +283,9 @@ static BlockDriverAIOCB *blkverify_aio_writev(BlockDriverState *bs,
     return &acb->common;
 }
 
-static BlockDriverAIOCB *blkverify_aio_flush(BlockDriverState *bs,
-                                             BlockDriverCompletionFunc *cb,
-                                             void *opaque)
+static BlockAIOCB *blkverify_aio_flush(BlockDriverState *bs,
+                                       BlockCompletionFunc *cb,
+                                       void *opaque)
 {
     BDRVBlkverifyState *s = bs->opaque;
 
diff --git a/block/commit.c b/block/commit.c
index 91517d3..60a2acc 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -182,7 +182,7 @@ static const BlockJobDriver commit_job_driver = {
 
 void commit_start(BlockDriverState *bs, BlockDriverState *base,
                   BlockDriverState *top, int64_t speed,
-                  BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
+                  BlockdevOnError on_error, BlockCompletionFunc *cb,
                   void *opaque, const char *backing_file_str, Error **errp)
 {
     CommitBlockJob *s;
diff --git a/block/curl.c b/block/curl.c
index 938f9d9..5e96b05 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -78,7 +78,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
 struct BDRVCURLState;
 
 typedef struct CURLAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     QEMUBH *bh;
     QEMUIOVector *qiov;
 
@@ -613,7 +613,7 @@ out_noclean:
     return -EINVAL;
 }
 
-static void curl_aio_cancel(BlockDriverAIOCB *blockacb)
+static void curl_aio_cancel(BlockAIOCB *blockacb)
 {
     // Do we have to implement canceling? Seems to work without...
 }
@@ -686,9 +686,9 @@ static void curl_readv_bh_cb(void *p)
     curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
 }
 
-static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
+static BlockAIOCB *curl_aio_readv(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     CURLAIOCB *acb;
 
diff --git a/block/iscsi.c b/block/iscsi.c
index af3d0f6..1a1a389 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -81,7 +81,7 @@ typedef struct IscsiTask {
 } IscsiTask;
 
 typedef struct IscsiAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     QEMUIOVector *qiov;
     QEMUBH *bh;
     IscsiLun *iscsilun;
@@ -231,7 +231,7 @@ iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
 }
 
 static void
-iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
+iscsi_aio_cancel(BlockAIOCB *blockacb)
 {
     IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
     IscsiLun *iscsilun = acb->iscsilun;
@@ -669,9 +669,9 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
     iscsi_schedule_bh(acb);
 }
 
-static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
+static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
         unsigned long int req, void *buf,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     IscsiLun *iscsilun = bs->opaque;
     struct iscsi_context *iscsi = iscsilun->iscsi;
diff --git a/block/linux-aio.c b/block/linux-aio.c
index 9aca758..2436140 100644
--- a/block/linux-aio.c
+++ b/block/linux-aio.c
@@ -28,7 +28,7 @@
 #define MAX_QUEUED_IO  128
 
 struct qemu_laiocb {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     struct qemu_laio_state *ctx;
     struct iocb iocb;
     ssize_t ret;
@@ -147,7 +147,7 @@ static void qemu_laio_completion_cb(EventNotifier *e)
     }
 }
 
-static void laio_cancel(BlockDriverAIOCB *blockacb)
+static void laio_cancel(BlockAIOCB *blockacb)
 {
     struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb;
     struct io_event event;
@@ -257,9 +257,9 @@ int laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug)
     return ret;
 }
 
-BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
+BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int type)
+        BlockCompletionFunc *cb, void *opaque, int type)
 {
     struct qemu_laio_state *s = aio_ctx;
     struct qemu_laiocb *laiocb;
diff --git a/block/mirror.c b/block/mirror.c
index 829be2f..e8a43eb 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -613,7 +613,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
                              int64_t buf_size,
                              BlockdevOnError on_source_error,
                              BlockdevOnError on_target_error,
-                             BlockDriverCompletionFunc *cb,
+                             BlockCompletionFunc *cb,
                              void *opaque, Error **errp,
                              const BlockJobDriver *driver,
                              bool is_none_mode, BlockDriverState *base)
@@ -673,7 +673,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
                   int64_t speed, int64_t granularity, int64_t buf_size,
                   MirrorSyncMode mode, BlockdevOnError on_source_error,
                   BlockdevOnError on_target_error,
-                  BlockDriverCompletionFunc *cb,
+                  BlockCompletionFunc *cb,
                   void *opaque, Error **errp)
 {
     bool is_none_mode;
@@ -690,7 +690,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
 void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
                          int64_t speed,
                          BlockdevOnError on_error,
-                         BlockDriverCompletionFunc *cb,
+                         BlockCompletionFunc *cb,
                          void *opaque, Error **errp)
 {
     int64_t length, base_length;
diff --git a/block/qed-gencb.c b/block/qed-gencb.c
index 7d7ac1f..b817a8b 100644
--- a/block/qed-gencb.c
+++ b/block/qed-gencb.c
@@ -13,7 +13,7 @@
 
 #include "qed.h"
 
-void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque)
+void *gencb_alloc(size_t len, BlockCompletionFunc *cb, void *opaque)
 {
     GenericCB *gencb = g_malloc(len);
     gencb->cb = cb;
@@ -24,7 +24,7 @@ void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque)
 void gencb_complete(void *opaque, int ret)
 {
     GenericCB *gencb = opaque;
-    BlockDriverCompletionFunc *cb = gencb->cb;
+    BlockCompletionFunc *cb = gencb->cb;
     void *user_opaque = gencb->opaque;
 
     g_free(gencb);
diff --git a/block/qed-table.c b/block/qed-table.c
index f61107a..513aa87 100644
--- a/block/qed-table.c
+++ b/block/qed-table.c
@@ -49,7 +49,7 @@ out:
 }
 
 static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
-                           BlockDriverCompletionFunc *cb, void *opaque)
+                           BlockCompletionFunc *cb, void *opaque)
 {
     QEDReadTableCB *read_table_cb = gencb_alloc(sizeof(*read_table_cb),
                                                 cb, opaque);
@@ -119,7 +119,7 @@ out:
  */
 static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
                             unsigned int index, unsigned int n, bool flush,
-                            BlockDriverCompletionFunc *cb, void *opaque)
+                            BlockCompletionFunc *cb, void *opaque)
 {
     QEDWriteTableCB *write_table_cb;
     unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
@@ -180,7 +180,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s)
 }
 
 void qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n,
-                        BlockDriverCompletionFunc *cb, void *opaque)
+                        BlockCompletionFunc *cb, void *opaque)
 {
     BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE);
     qed_write_table(s, s->header.l1_table_offset,
@@ -235,7 +235,7 @@ static void qed_read_l2_table_cb(void *opaque, int ret)
 }
 
 void qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset,
-                       BlockDriverCompletionFunc *cb, void *opaque)
+                       BlockCompletionFunc *cb, void *opaque)
 {
     QEDReadL2TableCB *read_l2_table_cb;
 
@@ -275,7 +275,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
 
 void qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
                         unsigned int index, unsigned int n, bool flush,
-                        BlockDriverCompletionFunc *cb, void *opaque)
+                        BlockCompletionFunc *cb, void *opaque)
 {
     BLKDBG_EVENT(s->bs->file, BLKDBG_L2_UPDATE);
     qed_write_table(s, request->l2_table->offset,
diff --git a/block/qed.c b/block/qed.c
index f20ffb3..a0eafa9 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -18,7 +18,7 @@
 #include "qapi/qmp/qerror.h"
 #include "migration/migration.h"
 
-static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
+static void qed_aio_cancel(BlockAIOCB *blockacb)
 {
     QEDAIOCB *acb = (QEDAIOCB *)blockacb;
     AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
@@ -144,7 +144,7 @@ static void qed_write_header_read_cb(void *opaque, int ret)
  * This function only updates known header fields in-place and does not affect
  * extra data after the QED header.
  */
-static void qed_write_header(BDRVQEDState *s, BlockDriverCompletionFunc cb,
+static void qed_write_header(BDRVQEDState *s, BlockCompletionFunc cb,
                              void *opaque)
 {
     /* We must write full sectors for O_DIRECT but cannot necessarily generate
@@ -772,7 +772,7 @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
 static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
                                   QEMUIOVector *qiov,
                                   QEMUIOVector **backing_qiov,
-                                  BlockDriverCompletionFunc *cb, void *opaque)
+                                  BlockCompletionFunc *cb, void *opaque)
 {
     uint64_t backing_length = 0;
     size_t size;
@@ -864,7 +864,7 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret)
  */
 static void qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos,
                                        uint64_t len, uint64_t offset,
-                                       BlockDriverCompletionFunc *cb,
+                                       BlockCompletionFunc *cb,
                                        void *opaque)
 {
     CopyFromBackingFileCB *copy_cb;
@@ -915,7 +915,7 @@ static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
 static void qed_aio_complete_bh(void *opaque)
 {
     QEDAIOCB *acb = opaque;
-    BlockDriverCompletionFunc *cb = acb->common.cb;
+    BlockCompletionFunc *cb = acb->common.cb;
     void *user_opaque = acb->common.opaque;
     int ret = acb->bh_ret;
     bool *finished = acb->finished;
@@ -1083,7 +1083,7 @@ static void qed_aio_write_main(void *opaque, int ret)
     BDRVQEDState *s = acb_to_s(acb);
     uint64_t offset = acb->cur_cluster +
                       qed_offset_into_cluster(s, acb->cur_pos);
-    BlockDriverCompletionFunc *next_fn;
+    BlockCompletionFunc *next_fn;
 
     trace_qed_aio_write_main(s, acb, ret, offset, acb->cur_qiov.size);
 
@@ -1183,7 +1183,7 @@ static void qed_aio_write_zero_cluster(void *opaque, int ret)
 static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
 {
     BDRVQEDState *s = acb_to_s(acb);
-    BlockDriverCompletionFunc *cb;
+    BlockCompletionFunc *cb;
 
     /* Cancel timer when the first allocating request comes in */
     if (QSIMPLEQ_EMPTY(&s->allocating_write_reqs)) {
@@ -1384,11 +1384,11 @@ static void qed_aio_next_io(void *opaque, int ret)
                       io_fn, acb);
 }
 
-static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs,
-                                       int64_t sector_num,
-                                       QEMUIOVector *qiov, int nb_sectors,
-                                       BlockDriverCompletionFunc *cb,
-                                       void *opaque, int flags)
+static BlockAIOCB *qed_aio_setup(BlockDriverState *bs,
+                                 int64_t sector_num,
+                                 QEMUIOVector *qiov, int nb_sectors,
+                                 BlockCompletionFunc *cb,
+                                 void *opaque, int flags)
 {
     QEDAIOCB *acb = qemu_aio_get(&qed_aiocb_info, bs, cb, opaque);
 
@@ -1410,20 +1410,20 @@ static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs,
     return &acb->common;
 }
 
-static BlockDriverAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs,
-                                            int64_t sector_num,
-                                            QEMUIOVector *qiov, int nb_sectors,
-                                            BlockDriverCompletionFunc *cb,
-                                            void *opaque)
+static BlockAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs,
+                                      int64_t sector_num,
+                                      QEMUIOVector *qiov, int nb_sectors,
+                                      BlockCompletionFunc *cb,
+                                      void *opaque)
 {
     return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
 }
 
-static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs,
-                                             int64_t sector_num,
-                                             QEMUIOVector *qiov, int nb_sectors,
-                                             BlockDriverCompletionFunc *cb,
-                                             void *opaque)
+static BlockAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs,
+                                       int64_t sector_num,
+                                       QEMUIOVector *qiov, int nb_sectors,
+                                       BlockCompletionFunc *cb,
+                                       void *opaque)
 {
     return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb,
                          opaque, QED_AIOCB_WRITE);
@@ -1451,7 +1451,7 @@ static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs,
                                                  int nb_sectors,
                                                  BdrvRequestFlags flags)
 {
-    BlockDriverAIOCB *blockacb;
+    BlockAIOCB *blockacb;
     BDRVQEDState *s = bs->opaque;
     QEDWriteZeroesCB cb = { .done = false };
     QEMUIOVector qiov;
diff --git a/block/qed.h b/block/qed.h
index 2b0e724..d3934a0 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -128,7 +128,7 @@ enum {
 };
 
 typedef struct QEDAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     QEMUBH *bh;
     int bh_ret;                     /* final return status for completion bh */
     QSIMPLEQ_ENTRY(QEDAIOCB) next;  /* next request */
@@ -203,11 +203,11 @@ typedef void QEDFindClusterFunc(void *opaque, int ret, uint64_t offset, size_t l
  * Generic callback for chaining async callbacks
  */
 typedef struct {
-    BlockDriverCompletionFunc *cb;
+    BlockCompletionFunc *cb;
     void *opaque;
 } GenericCB;
 
-void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque);
+void *gencb_alloc(size_t len, BlockCompletionFunc *cb, void *opaque);
 void gencb_complete(void *opaque, int ret);
 
 /**
@@ -230,16 +230,16 @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table);
  */
 int qed_read_l1_table_sync(BDRVQEDState *s);
 void qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n,
-                        BlockDriverCompletionFunc *cb, void *opaque);
+                        BlockCompletionFunc *cb, void *opaque);
 int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
                             unsigned int n);
 int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
                            uint64_t offset);
 void qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset,
-                       BlockDriverCompletionFunc *cb, void *opaque);
+                       BlockCompletionFunc *cb, void *opaque);
 void qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
                         unsigned int index, unsigned int n, bool flush,
-                        BlockDriverCompletionFunc *cb, void *opaque);
+                        BlockCompletionFunc *cb, void *opaque);
 int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
                             unsigned int index, unsigned int n, bool flush);
 
diff --git a/block/quorum.c b/block/quorum.c
index f958269..26f8dfa 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -92,7 +92,7 @@ typedef struct QuorumAIOCB QuorumAIOCB;
  * $children_count QuorumChildRequest.
  */
 typedef struct QuorumChildRequest {
-    BlockDriverAIOCB *aiocb;
+    BlockAIOCB *aiocb;
     QEMUIOVector qiov;
     uint8_t *buf;
     int ret;
@@ -105,7 +105,7 @@ typedef struct QuorumChildRequest {
  * used to do operations on each children and track overall progress.
  */
 struct QuorumAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
 
     /* Request metadata */
     uint64_t sector_num;
@@ -130,7 +130,7 @@ struct QuorumAIOCB {
 
 static bool quorum_vote(QuorumAIOCB *acb);
 
-static void quorum_aio_cancel(BlockDriverAIOCB *blockacb)
+static void quorum_aio_cancel(BlockAIOCB *blockacb)
 {
     QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common);
     BDRVQuorumState *s = acb->common.bs->opaque;
@@ -187,7 +187,7 @@ static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s,
                                    QEMUIOVector *qiov,
                                    uint64_t sector_num,
                                    int nb_sectors,
-                                   BlockDriverCompletionFunc *cb,
+                                   BlockCompletionFunc *cb,
                                    void *opaque)
 {
     QuorumAIOCB *acb = qemu_aio_get(&quorum_aiocb_info, bs, cb, opaque);
@@ -265,7 +265,7 @@ static void quorum_rewrite_aio_cb(void *opaque, int ret)
     quorum_aio_finalize(acb);
 }
 
-static BlockDriverAIOCB *read_fifo_child(QuorumAIOCB *acb);
+static BlockAIOCB *read_fifo_child(QuorumAIOCB *acb);
 
 static void quorum_copy_qiov(QEMUIOVector *dest, QEMUIOVector *source)
 {
@@ -641,7 +641,7 @@ free_exit:
     return rewrite;
 }
 
-static BlockDriverAIOCB *read_quorum_children(QuorumAIOCB *acb)
+static BlockAIOCB *read_quorum_children(QuorumAIOCB *acb)
 {
     BDRVQuorumState *s = acb->common.bs->opaque;
     int i;
@@ -660,7 +660,7 @@ static BlockDriverAIOCB *read_quorum_children(QuorumAIOCB *acb)
     return &acb->common;
 }
 
-static BlockDriverAIOCB *read_fifo_child(QuorumAIOCB *acb)
+static BlockAIOCB *read_fifo_child(QuorumAIOCB *acb)
 {
     BDRVQuorumState *s = acb->common.bs->opaque;
 
@@ -676,12 +676,12 @@ static BlockDriverAIOCB *read_fifo_child(QuorumAIOCB *acb)
     return &acb->common;
 }
 
-static BlockDriverAIOCB *quorum_aio_readv(BlockDriverState *bs,
-                                          int64_t sector_num,
-                                          QEMUIOVector *qiov,
-                                          int nb_sectors,
-                                          BlockDriverCompletionFunc *cb,
-                                          void *opaque)
+static BlockAIOCB *quorum_aio_readv(BlockDriverState *bs,
+                                    int64_t sector_num,
+                                    QEMUIOVector *qiov,
+                                    int nb_sectors,
+                                    BlockCompletionFunc *cb,
+                                    void *opaque)
 {
     BDRVQuorumState *s = bs->opaque;
     QuorumAIOCB *acb = quorum_aio_get(s, bs, qiov, sector_num,
@@ -697,12 +697,12 @@ static BlockDriverAIOCB *quorum_aio_readv(BlockDriverState *bs,
     return read_fifo_child(acb);
 }
 
-static BlockDriverAIOCB *quorum_aio_writev(BlockDriverState *bs,
-                                          int64_t sector_num,
-                                          QEMUIOVector *qiov,
-                                          int nb_sectors,
-                                          BlockDriverCompletionFunc *cb,
-                                          void *opaque)
+static BlockAIOCB *quorum_aio_writev(BlockDriverState *bs,
+                                     int64_t sector_num,
+                                     QEMUIOVector *qiov,
+                                     int nb_sectors,
+                                     BlockCompletionFunc *cb,
+                                     void *opaque)
 {
     BDRVQuorumState *s = bs->opaque;
     QuorumAIOCB *acb = quorum_aio_get(s, bs, qiov, sector_num, nb_sectors,
diff --git a/block/raw-aio.h b/block/raw-aio.h
index e18c975..80681ce 100644
--- a/block/raw-aio.h
+++ b/block/raw-aio.h
@@ -35,9 +35,9 @@
 #ifdef CONFIG_LINUX_AIO
 void *laio_init(void);
 void laio_cleanup(void *s);
-BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
+BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int type);
+        BlockCompletionFunc *cb, void *opaque, int type);
 void laio_detach_aio_context(void *s, AioContext *old_context);
 void laio_attach_aio_context(void *s, AioContext *new_context);
 void laio_io_plug(BlockDriverState *bs, void *aio_ctx);
@@ -49,10 +49,10 @@ typedef struct QEMUWin32AIOState QEMUWin32AIOState;
 QEMUWin32AIOState *win32_aio_init(void);
 void win32_aio_cleanup(QEMUWin32AIOState *aio);
 int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
-BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
+BlockAIOCB *win32_aio_submit(BlockDriverState *bs,
         QEMUWin32AIOState *aio, HANDLE hfile,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int type);
+        BlockCompletionFunc *cb, void *opaque, int type);
 void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
                                   AioContext *old_context);
 void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
diff --git a/block/raw-posix.c b/block/raw-posix.c
index d737f3a..2efbfeb 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -1040,9 +1040,9 @@ static int paio_submit_co(BlockDriverState *bs, int fd,
     return thread_pool_submit_co(pool, aio_worker, acb);
 }
 
-static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
+static BlockAIOCB *paio_submit(BlockDriverState *bs, int fd,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int type)
+        BlockCompletionFunc *cb, void *opaque, int type)
 {
     RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
     ThreadPool *pool;
@@ -1065,9 +1065,9 @@ static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
     return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
 }
 
-static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
+static BlockAIOCB *raw_aio_submit(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int type)
+        BlockCompletionFunc *cb, void *opaque, int type)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -1124,24 +1124,24 @@ static void raw_aio_flush_io_queue(BlockDriverState *bs)
 #endif
 }
 
-static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
+static BlockAIOCB *raw_aio_readv(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
                           cb, opaque, QEMU_AIO_READ);
 }
 
-static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
+static BlockAIOCB *raw_aio_writev(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
                           cb, opaque, QEMU_AIO_WRITE);
 }
 
-static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
-        BlockDriverCompletionFunc *cb, void *opaque)
+static BlockAIOCB *raw_aio_flush(BlockDriverState *bs,
+        BlockCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -1536,9 +1536,9 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
     return ret;
 }
 
-static coroutine_fn BlockDriverAIOCB *raw_aio_discard(BlockDriverState *bs,
+static coroutine_fn BlockAIOCB *raw_aio_discard(BlockDriverState *bs,
     int64_t sector_num, int nb_sectors,
-    BlockDriverCompletionFunc *cb, void *opaque)
+    BlockCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
 
@@ -1871,9 +1871,9 @@ static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
     return ioctl(s->fd, req, buf);
 }
 
-static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
+static BlockAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
         unsigned long int req, void *buf,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
     RawPosixAIOData *acb;
@@ -1912,9 +1912,9 @@ static int fd_open(BlockDriverState *bs)
 
 #endif /* !linux && !FreeBSD */
 
-static coroutine_fn BlockDriverAIOCB *hdev_aio_discard(BlockDriverState *bs,
+static coroutine_fn BlockAIOCB *hdev_aio_discard(BlockDriverState *bs,
     int64_t sector_num, int nb_sectors,
-    BlockDriverCompletionFunc *cb, void *opaque)
+    BlockCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
 
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 902eab6..88a2a33 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -138,9 +138,9 @@ static int aio_worker(void *arg)
     return ret;
 }
 
-static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
+static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int type)
+        BlockCompletionFunc *cb, void *opaque, int type)
 {
     RawWin32AIOData *acb = g_slice_new(RawWin32AIOData);
     ThreadPool *pool;
@@ -369,9 +369,9 @@ fail:
     return ret;
 }
 
-static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
+static BlockAIOCB *raw_aio_readv(BlockDriverState *bs,
                          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-                         BlockDriverCompletionFunc *cb, void *opaque)
+                         BlockCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
     if (s->aio) {
@@ -383,9 +383,9 @@ static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
     }
 }
 
-static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
+static BlockAIOCB *raw_aio_writev(BlockDriverState *bs,
                           int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-                          BlockDriverCompletionFunc *cb, void *opaque)
+                          BlockCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
     if (s->aio) {
@@ -397,8 +397,8 @@ static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
     }
 }
 
-static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
-                         BlockDriverCompletionFunc *cb, void *opaque)
+static BlockAIOCB *raw_aio_flush(BlockDriverState *bs,
+                         BlockCompletionFunc *cb, void *opaque)
 {
     BDRVRawState *s = bs->opaque;
     return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
diff --git a/block/raw_bsd.c b/block/raw_bsd.c
index f82f4c2..401b967 100644
--- a/block/raw_bsd.c
+++ b/block/raw_bsd.c
@@ -129,10 +129,10 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
     return bdrv_ioctl(bs->file, req, buf);
 }
 
-static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
-                                       unsigned long int req, void *buf,
-                                       BlockDriverCompletionFunc *cb,
-                                       void *opaque)
+static BlockAIOCB *raw_aio_ioctl(BlockDriverState *bs,
+                                 unsigned long int req, void *buf,
+                                 BlockCompletionFunc *cb,
+                                 void *opaque)
 {
     return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque);
 }
diff --git a/block/rbd.c b/block/rbd.c
index ea969e7..ceddc11 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -68,7 +68,7 @@ typedef enum {
 } RBDAIOCmd;
 
 typedef struct RBDAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     QEMUBH *bh;
     int64_t ret;
     QEMUIOVector *qiov;
@@ -542,7 +542,7 @@ static void qemu_rbd_close(BlockDriverState *bs)
  * Cancel aio. Since we don't reference acb in a non qemu threads,
  * it is safe to access it here.
  */
-static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
+static void qemu_rbd_aio_cancel(BlockAIOCB *blockacb)
 {
     RBDAIOCB *acb = (RBDAIOCB *) blockacb;
     acb->cancelled = 1;
@@ -608,13 +608,13 @@ static int rbd_aio_flush_wrapper(rbd_image_t image,
 #endif
 }
 
-static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
-                                       int64_t sector_num,
-                                       QEMUIOVector *qiov,
-                                       int nb_sectors,
-                                       BlockDriverCompletionFunc *cb,
-                                       void *opaque,
-                                       RBDAIOCmd cmd)
+static BlockAIOCB *rbd_start_aio(BlockDriverState *bs,
+                                 int64_t sector_num,
+                                 QEMUIOVector *qiov,
+                                 int nb_sectors,
+                                 BlockCompletionFunc *cb,
+                                 void *opaque,
+                                 RBDAIOCmd cmd)
 {
     RBDAIOCB *acb;
     RADOSCB *rcb = NULL;
@@ -695,32 +695,32 @@ failed:
     return NULL;
 }
 
-static BlockDriverAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs,
-                                            int64_t sector_num,
-                                            QEMUIOVector *qiov,
-                                            int nb_sectors,
-                                            BlockDriverCompletionFunc *cb,
-                                            void *opaque)
+static BlockAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs,
+                                      int64_t sector_num,
+                                      QEMUIOVector *qiov,
+                                      int nb_sectors,
+                                      BlockCompletionFunc *cb,
+                                      void *opaque)
 {
     return rbd_start_aio(bs, sector_num, qiov, nb_sectors, cb, opaque,
                          RBD_AIO_READ);
 }
 
-static BlockDriverAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
-                                             int64_t sector_num,
-                                             QEMUIOVector *qiov,
-                                             int nb_sectors,
-                                             BlockDriverCompletionFunc *cb,
-                                             void *opaque)
+static BlockAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
+                                       int64_t sector_num,
+                                       QEMUIOVector *qiov,
+                                       int nb_sectors,
+                                       BlockCompletionFunc *cb,
+                                       void *opaque)
 {
     return rbd_start_aio(bs, sector_num, qiov, nb_sectors, cb, opaque,
                          RBD_AIO_WRITE);
 }
 
 #ifdef LIBRBD_SUPPORTS_AIO_FLUSH
-static BlockDriverAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs,
-                                            BlockDriverCompletionFunc *cb,
-                                            void *opaque)
+static BlockAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs,
+                                      BlockCompletionFunc *cb,
+                                      void *opaque)
 {
     return rbd_start_aio(bs, 0, NULL, 0, cb, opaque, RBD_AIO_FLUSH);
 }
@@ -896,11 +896,11 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
 }
 
 #ifdef LIBRBD_SUPPORTS_DISCARD
-static BlockDriverAIOCB* qemu_rbd_aio_discard(BlockDriverState *bs,
-                                              int64_t sector_num,
-                                              int nb_sectors,
-                                              BlockDriverCompletionFunc *cb,
-                                              void *opaque)
+static BlockAIOCB *qemu_rbd_aio_discard(BlockDriverState *bs,
+                                        int64_t sector_num,
+                                        int nb_sectors,
+                                        BlockCompletionFunc *cb,
+                                        void *opaque)
 {
     return rbd_start_aio(bs, sector_num, NULL, nb_sectors, cb, opaque,
                          RBD_AIO_DISCARD);
diff --git a/block/sheepdog.c b/block/sheepdog.c
index f91afc3..86085d3 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -301,7 +301,7 @@ enum AIOCBState {
 };
 
 struct SheepdogAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
 
     QEMUIOVector *qiov;
 
@@ -477,7 +477,7 @@ static bool sd_acb_cancelable(const SheepdogAIOCB *acb)
     return true;
 }
 
-static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
+static void sd_aio_cancel(BlockAIOCB *blockacb)
 {
     SheepdogAIOCB *acb = (SheepdogAIOCB *)blockacb;
     BDRVSheepdogState *s = acb->common.bs->opaque;
diff --git a/block/stream.c b/block/stream.c
index cdea3e8..a1dc8da 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -220,7 +220,7 @@ static const BlockJobDriver stream_job_driver = {
 void stream_start(BlockDriverState *bs, BlockDriverState *base,
                   const char *backing_file_str, int64_t speed,
                   BlockdevOnError on_error,
-                  BlockDriverCompletionFunc *cb,
+                  BlockCompletionFunc *cb,
                   void *opaque, Error **errp)
 {
     StreamBlockJob *s;
diff --git a/block/win32-aio.c b/block/win32-aio.c
index 5030e32..de273b8 100644
--- a/block/win32-aio.c
+++ b/block/win32-aio.c
@@ -44,7 +44,7 @@ struct QEMUWin32AIOState {
 };
 
 typedef struct QEMUWin32AIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     struct QEMUWin32AIOState *ctx;
     int nbytes;
     OVERLAPPED ov;
@@ -106,7 +106,7 @@ static void win32_aio_completion_cb(EventNotifier *e)
     }
 }
 
-static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
+static void win32_aio_cancel(BlockAIOCB *blockacb)
 {
     QEMUWin32AIOCB *waiocb = (QEMUWin32AIOCB *)blockacb;
 
@@ -124,10 +124,10 @@ static const AIOCBInfo win32_aiocb_info = {
     .cancel             = win32_aio_cancel,
 };
 
-BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
+BlockAIOCB *win32_aio_submit(BlockDriverState *bs,
         QEMUWin32AIOState *aio, HANDLE hfile,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque, int type)
+        BlockCompletionFunc *cb, void *opaque, int type)
 {
     struct QEMUWin32AIOCB *waiocb;
     uint64_t offset = sector_num * 512;
diff --git a/blockjob.c b/blockjob.c
index 3af0f6c..ff0908a 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -36,7 +36,7 @@
 #include "qapi-event.h"
 
 void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
-                       int64_t speed, BlockDriverCompletionFunc *cb,
+                       int64_t speed, BlockCompletionFunc *cb,
                        void *opaque, Error **errp)
 {
     BlockJob *job;
@@ -155,7 +155,7 @@ void block_job_iostatus_reset(BlockJob *job)
 
 struct BlockCancelData {
     BlockJob *job;
-    BlockDriverCompletionFunc *cb;
+    BlockCompletionFunc *cb;
     void *opaque;
     bool cancelled;
     int ret;
diff --git a/dma-helpers.c b/dma-helpers.c
index 499b52b..e7bea06 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -67,9 +67,9 @@ void qemu_sglist_destroy(QEMUSGList *qsg)
 }
 
 typedef struct {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     BlockDriverState *bs;
-    BlockDriverAIOCB *acb;
+    BlockAIOCB *acb;
     QEMUSGList *sg;
     uint64_t sector_num;
     DMADirection dir;
@@ -179,14 +179,14 @@ static void dma_bdrv_cb(void *opaque, int ret)
     assert(dbs->acb);
 }
 
-static void dma_aio_cancel(BlockDriverAIOCB *acb)
+static void dma_aio_cancel(BlockAIOCB *acb)
 {
     DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common);
 
     trace_dma_aio_cancel(dbs);
 
     if (dbs->acb) {
-        BlockDriverAIOCB *acb = dbs->acb;
+        BlockAIOCB *acb = dbs->acb;
         dbs->acb = NULL;
         dbs->in_cancel = true;
         bdrv_aio_cancel(acb);
@@ -201,9 +201,9 @@ static const AIOCBInfo dma_aiocb_info = {
     .cancel             = dma_aio_cancel,
 };
 
-BlockDriverAIOCB *dma_bdrv_io(
+BlockAIOCB *dma_bdrv_io(
     BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,
-    DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
+    DMAIOFunc *io_func, BlockCompletionFunc *cb,
     void *opaque, DMADirection dir)
 {
     DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque);
@@ -226,17 +226,17 @@ BlockDriverAIOCB *dma_bdrv_io(
 }
 
 
-BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
-                                QEMUSGList *sg, uint64_t sector,
-                                void (*cb)(void *opaque, int ret), void *opaque)
+BlockAIOCB *dma_bdrv_read(BlockDriverState *bs,
+                          QEMUSGList *sg, uint64_t sector,
+                          void (*cb)(void *opaque, int ret), void *opaque)
 {
     return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque,
                        DMA_DIRECTION_FROM_DEVICE);
 }
 
-BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
-                                 QEMUSGList *sg, uint64_t sector,
-                                 void (*cb)(void *opaque, int ret), void *opaque)
+BlockAIOCB *dma_bdrv_write(BlockDriverState *bs,
+                           QEMUSGList *sg, uint64_t sector,
+                           void (*cb)(void *opaque, int ret), void *opaque)
 {
     return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque,
                        DMA_DIRECTION_TO_DEVICE);
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index bd8fc3e..993c511 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -636,7 +636,7 @@ typedef struct NvmeAsyncEvent {
 
 typedef struct NvmeRequest {
     struct NvmeSQueue       *sq;
-    BlockDriverAIOCB        *aiocb;
+    BlockAIOCB              *aiocb;
     uint16_t                status;
     NvmeCqe                 cqe;
     BlockAcctCookie         acct;
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 0ee713b..97c997c 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1104,7 +1104,7 @@ out:
 }
 
 static void ahci_start_dma(IDEDMA *dma, IDEState *s,
-                           BlockDriverCompletionFunc *dma_cb)
+                           BlockCompletionFunc *dma_cb)
 {
 #ifdef DEBUG_AHCI
     AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 1543df7..fe32eab 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -241,7 +241,7 @@ typedef struct AHCIDevice AHCIDevice;
 
 typedef struct NCQTransferState {
     AHCIDevice *drive;
-    BlockDriverAIOCB *aiocb;
+    BlockAIOCB *aiocb;
     QEMUSGList sglist;
     BlockAcctCookie acct;
     uint16_t sector_count;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 191f893..36df217 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -360,15 +360,15 @@ static void ide_set_signature(IDEState *s)
 }
 
 typedef struct TrimAIOCB {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     QEMUBH *bh;
     int ret;
     QEMUIOVector *qiov;
-    BlockDriverAIOCB *aiocb;
+    BlockAIOCB *aiocb;
     int i, j;
 } TrimAIOCB;
 
-static void trim_aio_cancel(BlockDriverAIOCB *acb)
+static void trim_aio_cancel(BlockAIOCB *acb)
 {
     TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
 
@@ -440,9 +440,9 @@ static void ide_issue_trim_cb(void *opaque, int ret)
     }
 }
 
-BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
+BlockAIOCB *ide_issue_trim(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     TrimAIOCB *iocb;
 
@@ -784,7 +784,7 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
     ide_start_dma(s, ide_dma_cb);
 }
 
-void ide_start_dma(IDEState *s, BlockDriverCompletionFunc *cb)
+void ide_start_dma(IDEState *s, BlockCompletionFunc *cb)
 {
     if (s->bus->dma->ops->start_dma) {
         s->bus->dma->ops->start_dma(s->bus->dma, s, cb);
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 5c19f79..9314c80 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -319,7 +319,7 @@ typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind;
 
 typedef void EndTransferFunc(IDEState *);
 
-typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *);
+typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *);
 typedef void DMAVoidFunc(IDEDMA *);
 typedef int DMAIntFunc(IDEDMA *, int);
 typedef void DMAStopFunc(IDEDMA *, bool);
@@ -389,7 +389,7 @@ struct IDEState {
     int cd_sector_size;
     int atapi_dma; /* true if dma is requested for the packet cmd */
     BlockAcctCookie acct;
-    BlockDriverAIOCB *pio_aiocb;
+    BlockAIOCB *pio_aiocb;
     struct iovec iov;
     QEMUIOVector qiov;
     /* ATA DMA state */
@@ -442,7 +442,7 @@ struct IDEDMA {
     const struct IDEDMAOps *ops;
     struct iovec iov;
     QEMUIOVector qiov;
-    BlockDriverAIOCB *aiocb;
+    BlockAIOCB *aiocb;
 };
 
 struct IDEBus {
@@ -521,7 +521,7 @@ void ide_bus_reset(IDEBus *bus);
 int64_t ide_get_sector(IDEState *s);
 void ide_set_sector(IDEState *s, int64_t sector_num);
 
-void ide_start_dma(IDEState *s, BlockDriverCompletionFunc *cb);
+void ide_start_dma(IDEState *s, BlockCompletionFunc *cb);
 void ide_dma_error(IDEState *s);
 
 void ide_atapi_cmd_ok(IDEState *s);
@@ -555,9 +555,9 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
                         EndTransferFunc *end_transfer_func);
 void ide_transfer_stop(IDEState *s);
 void ide_set_inactive(IDEState *s, bool more);
-BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
+BlockAIOCB *ide_issue_trim(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque);
+        BlockCompletionFunc *cb, void *opaque);
 
 /* hw/ide/atapi.c */
 void ide_atapi_cmd(IDEState *s);
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index b0c0d40..371e172 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -555,7 +555,7 @@ static void ide_nop_restart(void *opaque, int x, RunState y)
 }
 
 static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
-                            BlockDriverCompletionFunc *cb)
+                            BlockCompletionFunc *cb)
 {
     MACIOIDEState *m = container_of(dma, MACIOIDEState, dma);
 
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 2397f35..6ff1c58 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -38,7 +38,7 @@
         IDE_RETRY_READ | IDE_RETRY_FLUSH)
 
 static void bmdma_start_dma(IDEDMA *dma, IDEState *s,
-                            BlockDriverCompletionFunc *dma_cb)
+                            BlockCompletionFunc *dma_cb)
 {
     BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
 
diff --git a/hw/ide/pci.h b/hw/ide/pci.h
index 517711f..2e9314a 100644
--- a/hw/ide/pci.h
+++ b/hw/ide/pci.h
@@ -23,7 +23,7 @@ typedef struct BMDMAState {
     uint32_t cur_prd_addr;
     uint32_t cur_prd_len;
     uint8_t unit;
-    BlockDriverCompletionFunc *dma_cb;
+    BlockCompletionFunc *dma_cb;
     int64_t sector_num;
     uint32_t nsector;
     MemoryRegion addr_ioport;
diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index aff2b9a..8bdba30 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -131,7 +131,7 @@ typedef struct MACIOIDEState {
 
     MemoryRegion mem;
     IDEBus bus;
-    BlockDriverAIOCB *aiocb;
+    BlockAIOCB *aiocb;
     IDEDMA dma;
     void *dbdma;
     bool dma_active;
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index 20587b4..5301886 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -157,7 +157,7 @@ static void scsi_cancel_io(SCSIRequest *req)
 
 static int execute_command(BlockDriverState *bdrv,
                            SCSIGenericReq *r, int direction,
-			   BlockDriverCompletionFunc *complete)
+                           BlockCompletionFunc *complete)
 {
     r->io_header.interface_id = 'S';
     r->io_header.dxfer_direction = direction;
diff --git a/include/block/aio.h b/include/block/aio.h
index 4603c0f..57619ab 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -22,23 +22,23 @@
 #include "qemu/rfifolock.h"
 #include "qemu/timer.h"
 
-typedef struct BlockDriverAIOCB BlockDriverAIOCB;
-typedef void BlockDriverCompletionFunc(void *opaque, int ret);
+typedef struct BlockAIOCB BlockAIOCB;
+typedef void BlockCompletionFunc(void *opaque, int ret);
 
 typedef struct AIOCBInfo {
-    void (*cancel)(BlockDriverAIOCB *acb);
+    void (*cancel)(BlockAIOCB *acb);
     size_t aiocb_size;
 } AIOCBInfo;
 
-struct BlockDriverAIOCB {
+struct BlockAIOCB {
     const AIOCBInfo *aiocb_info;
     BlockDriverState *bs;
-    BlockDriverCompletionFunc *cb;
+    BlockCompletionFunc *cb;
     void *opaque;
 };
 
 void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
-                   BlockDriverCompletionFunc *cb, void *opaque);
+                   BlockCompletionFunc *cb, void *opaque);
 void qemu_aio_release(void *p);
 
 typedef struct AioHandler AioHandler;
diff --git a/include/block/block.h b/include/block/block.h
index fb4fff9..15a5290 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -246,9 +246,9 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
                const uint8_t *buf, int nb_sectors);
 int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
                int nb_sectors, BdrvRequestFlags flags);
-BlockDriverAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, int64_t sector_num,
-                                        int nb_sectors, BdrvRequestFlags flags,
-                                        BlockDriverCompletionFunc *cb, void *opaque);
+BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, int64_t sector_num,
+                                  int nb_sectors, BdrvRequestFlags flags,
+                                  BlockCompletionFunc *cb, void *opaque);
 int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags);
 int bdrv_pread(BlockDriverState *bs, int64_t offset,
                void *buf, int count);
@@ -324,18 +324,18 @@ BlockDriverState *check_to_replace_node(const char *node_name, Error **errp);
 /* async block I/O */
 typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector,
                                      int sector_num);
-BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
-                                 QEMUIOVector *iov, int nb_sectors,
-                                 BlockDriverCompletionFunc *cb, void *opaque);
-BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
-                                  QEMUIOVector *iov, int nb_sectors,
-                                  BlockDriverCompletionFunc *cb, void *opaque);
-BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
-                                 BlockDriverCompletionFunc *cb, void *opaque);
-BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
-                                   int64_t sector_num, int nb_sectors,
-                                   BlockDriverCompletionFunc *cb, void *opaque);
-void bdrv_aio_cancel(BlockDriverAIOCB *acb);
+BlockAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
+                           QEMUIOVector *iov, int nb_sectors,
+                           BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
+                            QEMUIOVector *iov, int nb_sectors,
+                            BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *bdrv_aio_flush(BlockDriverState *bs,
+                           BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *bdrv_aio_discard(BlockDriverState *bs,
+                             int64_t sector_num, int nb_sectors,
+                             BlockCompletionFunc *cb, void *opaque);
+void bdrv_aio_cancel(BlockAIOCB *acb);
 
 typedef struct BlockRequest {
     /* Fields to be filled by multiwrite caller */
@@ -343,7 +343,7 @@ typedef struct BlockRequest {
     int nb_sectors;
     int flags;
     QEMUIOVector *qiov;
-    BlockDriverCompletionFunc *cb;
+    BlockCompletionFunc *cb;
     void *opaque;
 
     /* Filled by multiwrite implementation */
@@ -355,9 +355,9 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs,
 
 /* sg packet commands */
 int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf);
-BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
+BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
         unsigned long int req, void *buf,
-        BlockDriverCompletionFunc *cb, void *opaque);
+        BlockCompletionFunc *cb, void *opaque);
 
 /* Invalidate any cached metadata used by image formats */
 void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 08ccb27..b3246e7 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -127,17 +127,17 @@ struct BlockDriver {
     void (*bdrv_refresh_filename)(BlockDriverState *bs);
 
     /* aio */
-    BlockDriverAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs,
+    BlockAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque);
-    BlockDriverAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs,
+        BlockCompletionFunc *cb, void *opaque);
+    BlockAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque);
-    BlockDriverAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
-        BlockDriverCompletionFunc *cb, void *opaque);
-    BlockDriverAIOCB *(*bdrv_aio_discard)(BlockDriverState *bs,
+        BlockCompletionFunc *cb, void *opaque);
+    BlockAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
+        BlockCompletionFunc *cb, void *opaque);
+    BlockAIOCB *(*bdrv_aio_discard)(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors,
-        BlockDriverCompletionFunc *cb, void *opaque);
+        BlockCompletionFunc *cb, void *opaque);
 
     int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
         int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
@@ -217,9 +217,9 @@ struct BlockDriver {
 
     /* to control generic scsi devices */
     int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
-    BlockDriverAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
+    BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
         unsigned long int req, void *buf,
-        BlockDriverCompletionFunc *cb, void *opaque);
+        BlockCompletionFunc *cb, void *opaque);
 
     /* List of options for creating images, terminated by name == NULL */
     QemuOptsList *create_opts;
@@ -501,7 +501,7 @@ int is_windows_drive(const char *filename);
  */
 void stream_start(BlockDriverState *bs, BlockDriverState *base,
                   const char *base_id, int64_t speed, BlockdevOnError on_error,
-                  BlockDriverCompletionFunc *cb,
+                  BlockCompletionFunc *cb,
                   void *opaque, Error **errp);
 
 /**
@@ -519,7 +519,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
  */
 void commit_start(BlockDriverState *bs, BlockDriverState *base,
                  BlockDriverState *top, int64_t speed,
-                 BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
+                 BlockdevOnError on_error, BlockCompletionFunc *cb,
                  void *opaque, const char *backing_file_str, Error **errp);
 /**
  * commit_active_start:
@@ -535,7 +535,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
 void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
                          int64_t speed,
                          BlockdevOnError on_error,
-                         BlockDriverCompletionFunc *cb,
+                         BlockCompletionFunc *cb,
                          void *opaque, Error **errp);
 /*
  * mirror_start:
@@ -563,7 +563,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
                   int64_t speed, int64_t granularity, int64_t buf_size,
                   MirrorSyncMode mode, BlockdevOnError on_source_error,
                   BlockdevOnError on_target_error,
-                  BlockDriverCompletionFunc *cb,
+                  BlockCompletionFunc *cb,
                   void *opaque, Error **errp);
 
 /*
@@ -584,7 +584,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
                   int64_t speed, MirrorSyncMode sync_mode,
                   BlockdevOnError on_source_error,
                   BlockdevOnError on_target_error,
-                  BlockDriverCompletionFunc *cb, void *opaque,
+                  BlockCompletionFunc *cb, void *opaque,
                   Error **errp);
 
 #endif /* BLOCK_INT_H */
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
index 60aa835..acb399f 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -104,7 +104,7 @@ struct BlockJob {
     int64_t speed;
 
     /** The completion function that will be called when the job completes.  */
-    BlockDriverCompletionFunc *cb;
+    BlockCompletionFunc *cb;
 
     /** Block other operations when block job is running */
     Error *blocker;
@@ -132,7 +132,7 @@ struct BlockJob {
  * called from a wrapper that is specific to the job type.
  */
 void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
-                       int64_t speed, BlockDriverCompletionFunc *cb,
+                       int64_t speed, BlockCompletionFunc *cb,
                        void *opaque, Error **errp);
 
 /**
diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h
index 4723752..42eb5e8 100644
--- a/include/block/thread-pool.h
+++ b/include/block/thread-pool.h
@@ -27,9 +27,9 @@ typedef struct ThreadPool ThreadPool;
 ThreadPool *thread_pool_new(struct AioContext *ctx);
 void thread_pool_free(ThreadPool *pool);
 
-BlockDriverAIOCB *thread_pool_submit_aio(ThreadPool *pool,
+BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
         ThreadPoolFunc *func, void *arg,
-        BlockDriverCompletionFunc *cb, void *opaque);
+        BlockCompletionFunc *cb, void *opaque);
 int coroutine_fn thread_pool_submit_co(ThreadPool *pool,
         ThreadPoolFunc *func, void *arg);
 void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg);
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 2e3a8f9..e3e27cb 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -52,7 +52,7 @@ struct SCSIRequest {
     uint32_t          status;
     size_t            resid;
     SCSICommand       cmd;
-    BlockDriverAIOCB  *aiocb;
+    BlockAIOCB        *aiocb;
     QEMUSGList        *sg;
     bool              dma_started;
     uint8_t sense[SCSI_SENSE_BUF_SIZE];
diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 78a5fc8..47606d0 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -27,10 +27,10 @@ int monitor_suspend(Monitor *mon);
 void monitor_resume(Monitor *mon);
 
 int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
-                                BlockDriverCompletionFunc *completion_cb,
+                                BlockCompletionFunc *completion_cb,
                                 void *opaque);
 int monitor_read_block_device_key(Monitor *mon, const char *device,
-                                  BlockDriverCompletionFunc *completion_cb,
+                                  BlockCompletionFunc *completion_cb,
                                   void *opaque);
 
 int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp);
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index 00f21f3..464f9f7 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -196,20 +196,20 @@ void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
 void qemu_sglist_destroy(QEMUSGList *qsg);
 #endif
 
-typedef BlockDriverAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
-                                 QEMUIOVector *iov, int nb_sectors,
-                                 BlockDriverCompletionFunc *cb, void *opaque);
+typedef BlockAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
+                              QEMUIOVector *iov, int nb_sectors,
+                              BlockCompletionFunc *cb, void *opaque);
 
-BlockDriverAIOCB *dma_bdrv_io(BlockDriverState *bs,
-                              QEMUSGList *sg, uint64_t sector_num,
-                              DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
-                              void *opaque, DMADirection dir);
-BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
-                                QEMUSGList *sg, uint64_t sector,
-                                BlockDriverCompletionFunc *cb, void *opaque);
-BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
-                                 QEMUSGList *sg, uint64_t sector,
-                                 BlockDriverCompletionFunc *cb, void *opaque);
+BlockAIOCB *dma_bdrv_io(BlockDriverState *bs,
+                        QEMUSGList *sg, uint64_t sector_num,
+                        DMAIOFunc *io_func, BlockCompletionFunc *cb,
+                        void *opaque, DMADirection dir);
+BlockAIOCB *dma_bdrv_read(BlockDriverState *bs,
+                          QEMUSGList *sg, uint64_t sector,
+                          BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *dma_bdrv_write(BlockDriverState *bs,
+                           QEMUSGList *sg, uint64_t sector,
+                           BlockCompletionFunc *cb, void *opaque);
 uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
 uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
 
diff --git a/monitor.c b/monitor.c
index 4ae66df..eaa6de7 100644
--- a/monitor.c
+++ b/monitor.c
@@ -206,7 +206,7 @@ struct Monitor {
     ReadLineState *rs;
     MonitorControl *mc;
     CPUState *mon_cpu;
-    BlockDriverCompletionFunc *password_completion_cb;
+    BlockCompletionFunc *password_completion_cb;
     void *password_opaque;
     mon_cmd_t *cmd_table;
     QError *error;
@@ -5361,7 +5361,7 @@ ReadLineState *monitor_get_rs(Monitor *mon)
 }
 
 int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
-                                BlockDriverCompletionFunc *completion_cb,
+                                BlockCompletionFunc *completion_cb,
                                 void *opaque)
 {
     int err;
@@ -5393,7 +5393,7 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
 }
 
 int monitor_read_block_device_key(Monitor *mon, const char *device,
-                                  BlockDriverCompletionFunc *completion_cb,
+                                  BlockCompletionFunc *completion_cb,
                                   void *opaque)
 {
     BlockDriverState *bs;
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index f40b7fc..acc911b 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -10,7 +10,7 @@ static ThreadPool *pool;
 static int active;
 
 typedef struct {
-    BlockDriverAIOCB *aiocb;
+    BlockAIOCB *aiocb;
     int n;
     int ret;
 } WorkerTestData;
diff --git a/thread-pool.c b/thread-pool.c
index bc07d7a..f9e9901 100644
--- a/thread-pool.c
+++ b/thread-pool.c
@@ -35,7 +35,7 @@ enum ThreadState {
 };
 
 struct ThreadPoolElement {
-    BlockDriverAIOCB common;
+    BlockAIOCB common;
     ThreadPool *pool;
     ThreadPoolFunc *func;
     void *arg;
@@ -201,7 +201,7 @@ restart:
     }
 }
 
-static void thread_pool_cancel(BlockDriverAIOCB *acb)
+static void thread_pool_cancel(BlockAIOCB *acb)
 {
     ThreadPoolElement *elem = (ThreadPoolElement *)acb;
     ThreadPool *pool = elem->pool;
@@ -235,9 +235,9 @@ static const AIOCBInfo thread_pool_aiocb_info = {
     .cancel             = thread_pool_cancel,
 };
 
-BlockDriverAIOCB *thread_pool_submit_aio(ThreadPool *pool,
+BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
         ThreadPoolFunc *func, void *arg,
-        BlockDriverCompletionFunc *cb, void *opaque)
+        BlockCompletionFunc *cb, void *opaque)
 {
     ThreadPoolElement *req;
 
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 12/23] virtio-blk: Drop redundant VirtIOBlock member conf
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (10 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 11/23] block: Rename BlockDriverAIOCB* to BlockAIOCB* Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 13/23] virtio-blk: Rename VirtIOBlkConf variables to conf Markus Armbruster
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Commit 12c5674 turned it into a pointer to member blk.conf.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 hw/block/virtio-blk.c          | 28 ++++++++++++++--------------
 include/hw/virtio/virtio-blk.h |  1 -
 2 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index a7f2827..0be7203 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -297,7 +297,7 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
     if (sector & dev->sector_mask) {
         return false;
     }
-    if (size % dev->conf->logical_block_size) {
+    if (size % dev->blk.conf.logical_block_size) {
         return false;
     }
     bdrv_get_geometry(dev->bs, &total_sectors);
@@ -516,19 +516,20 @@ static void virtio_blk_reset(VirtIODevice *vdev)
 static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 {
     VirtIOBlock *s = VIRTIO_BLK(vdev);
+    BlockConf *conf = &s->blk.conf;
     struct virtio_blk_config blkcfg;
     uint64_t capacity;
-    int blk_size = s->conf->logical_block_size;
+    int blk_size = conf->logical_block_size;
 
     bdrv_get_geometry(s->bs, &capacity);
     memset(&blkcfg, 0, sizeof(blkcfg));
     virtio_stq_p(vdev, &blkcfg.capacity, capacity);
     virtio_stl_p(vdev, &blkcfg.seg_max, 128 - 2);
-    virtio_stw_p(vdev, &blkcfg.cylinders, s->conf->cyls);
+    virtio_stw_p(vdev, &blkcfg.cylinders, conf->cyls);
     virtio_stl_p(vdev, &blkcfg.blk_size, blk_size);
-    virtio_stw_p(vdev, &blkcfg.min_io_size, s->conf->min_io_size / blk_size);
-    virtio_stw_p(vdev, &blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
-    blkcfg.heads = s->conf->heads;
+    virtio_stw_p(vdev, &blkcfg.min_io_size, conf->min_io_size / blk_size);
+    virtio_stw_p(vdev, &blkcfg.opt_io_size, conf->opt_io_size / blk_size);
+    blkcfg.heads = conf->heads;
     /*
      * We must ensure that the block device capacity is a multiple of
      * the logical block size. If that is not the case, let's use
@@ -540,13 +541,13 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
      * divided by 512 - instead it is the amount of blk_size blocks
      * per track (cylinder).
      */
-    if (bdrv_getlength(s->bs) /  s->conf->heads / s->conf->secs % blk_size) {
-        blkcfg.sectors = s->conf->secs & ~s->sector_mask;
+    if (bdrv_getlength(s->bs) /  conf->heads / conf->secs % blk_size) {
+        blkcfg.sectors = conf->secs & ~s->sector_mask;
     } else {
-        blkcfg.sectors = s->conf->secs;
+        blkcfg.sectors = conf->secs;
     }
     blkcfg.size_max = 0;
-    blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
+    blkcfg.physical_block_exp = get_physical_block_exp(&s->blk.conf);
     blkcfg.alignment_offset = 0;
     blkcfg.wce = bdrv_enable_write_cache(s->bs);
     memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
@@ -753,9 +754,8 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
                 sizeof(struct virtio_blk_config));
 
     s->bs = blk->conf.bs;
-    s->conf = &blk->conf;
     s->rq = NULL;
-    s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
+    s->sector_mask = (s->blk.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1;
 
     s->vq = virtio_add_queue(vdev, 128, virtio_blk_handle_output);
     s->complete_request = virtio_blk_complete_request;
@@ -774,11 +774,11 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
     register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
     bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
-    bdrv_set_guest_block_size(s->bs, s->conf->logical_block_size);
+    bdrv_set_guest_block_size(s->bs, s->blk.conf.logical_block_size);
 
     bdrv_iostatus_enable(s->bs);
 
-    add_boot_device_path(s->conf->bootindex, dev, "/disk@0,0");
+    add_boot_device_path(s->blk.conf.bootindex, dev, "/disk@0,0");
 }
 
 static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index afb7b8d..1329482 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -124,7 +124,6 @@ typedef struct VirtIOBlock {
     VirtQueue *vq;
     void *rq;
     QEMUBH *bh;
-    BlockConf *conf;
     VirtIOBlkConf blk;
     unsigned short sector_mask;
     bool original_wce;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 13/23] virtio-blk: Rename VirtIOBlkConf variables to conf
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (11 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 12/23] virtio-blk: Drop redundant VirtIOBlock member conf Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 14/23] hw: Convert from BlockDriverState to BlockBackend, mostly Markus Armbruster
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

This is consistent with how VirtIOFOOConf variables are named
elsewhere, and makes blk available for BlockBackend variables.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 hw/block/dataplane/virtio-blk.c | 33 +++++++++++++-------------
 hw/block/dataplane/virtio-blk.h |  2 +-
 hw/block/virtio-blk.c           | 52 ++++++++++++++++++++---------------------
 include/hw/virtio/virtio-blk.h  |  2 +-
 4 files changed, 45 insertions(+), 44 deletions(-)

diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index b55188c..af67dc3 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -30,7 +30,7 @@ struct VirtIOBlockDataPlane {
     bool stopping;
     bool disabled;
 
-    VirtIOBlkConf *blk;
+    VirtIOBlkConf *conf;
 
     VirtIODevice *vdev;
     Vring vring;                    /* virtqueue vring */
@@ -94,7 +94,7 @@ static void handle_notify(EventNotifier *e)
     VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
 
     event_notifier_test_and_clear(&s->host_notifier);
-    bdrv_io_plug(s->blk->conf.bs);
+    bdrv_io_plug(s->conf->conf.bs);
     for (;;) {
         MultiReqBuffer mrb = {
             .num_writes = 0,
@@ -120,7 +120,7 @@ static void handle_notify(EventNotifier *e)
             virtio_blk_handle_request(req, &mrb);
         }
 
-        virtio_submit_multiwrite(s->blk->conf.bs, &mrb);
+        virtio_submit_multiwrite(s->conf->conf.bs, &mrb);
 
         if (likely(ret == -EAGAIN)) { /* vring emptied */
             /* Re-enable guest->host notifies and stop processing the vring.
@@ -133,11 +133,11 @@ static void handle_notify(EventNotifier *e)
             break;
         }
     }
-    bdrv_io_unplug(s->blk->conf.bs);
+    bdrv_io_unplug(s->conf->conf.bs);
 }
 
 /* Context: QEMU global mutex held */
-void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
+void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
                                   VirtIOBlockDataPlane **dataplane,
                                   Error **errp)
 {
@@ -148,7 +148,7 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
 
     *dataplane = NULL;
 
-    if (!blk->data_plane && !blk->iothread) {
+    if (!conf->data_plane && !conf->iothread) {
         return;
     }
 
@@ -163,7 +163,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
     /* If dataplane is (re-)enabled while the guest is running there could be
      * block jobs that can conflict.
      */
-    if (bdrv_op_is_blocked(blk->conf.bs, BLOCK_OP_TYPE_DATAPLANE, &local_err)) {
+    if (bdrv_op_is_blocked(conf->conf.bs, BLOCK_OP_TYPE_DATAPLANE,
+                           &local_err)) {
         error_report("cannot start dataplane thread: %s",
                       error_get_pretty(local_err));
         error_free(local_err);
@@ -172,10 +173,10 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
 
     s = g_new0(VirtIOBlockDataPlane, 1);
     s->vdev = vdev;
-    s->blk = blk;
+    s->conf = conf;
 
-    if (blk->iothread) {
-        s->iothread = blk->iothread;
+    if (conf->iothread) {
+        s->iothread = conf->iothread;
         object_ref(OBJECT(s->iothread));
     } else {
         /* Create per-device IOThread if none specified.  This is for
@@ -192,9 +193,9 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
     s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
 
     error_setg(&s->blocker, "block device is in use by data plane");
-    bdrv_op_block_all(blk->conf.bs, s->blocker);
-    bdrv_op_unblock(blk->conf.bs, BLOCK_OP_TYPE_RESIZE, s->blocker);
-    bdrv_op_unblock(blk->conf.bs, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
+    bdrv_op_block_all(conf->conf.bs, s->blocker);
+    bdrv_op_unblock(conf->conf.bs, BLOCK_OP_TYPE_RESIZE, s->blocker);
+    bdrv_op_unblock(conf->conf.bs, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
 
     *dataplane = s;
 }
@@ -207,7 +208,7 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
     }
 
     virtio_blk_data_plane_stop(s);
-    bdrv_op_unblock_all(s->blk->conf.bs, s->blocker);
+    bdrv_op_unblock_all(s->conf->conf.bs, s->blocker);
     error_free(s->blocker);
     object_unref(OBJECT(s->iothread));
     qemu_bh_delete(s->bh);
@@ -262,7 +263,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
     s->started = true;
     trace_virtio_blk_data_plane_start(s);
 
-    bdrv_set_aio_context(s->blk->conf.bs, s->ctx);
+    bdrv_set_aio_context(s->conf->conf.bs, s->ctx);
 
     /* Kick right away to begin processing requests already in vring */
     event_notifier_set(virtio_queue_get_host_notifier(vq));
@@ -308,7 +309,7 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
     aio_set_event_notifier(s->ctx, &s->host_notifier, NULL);
 
     /* Drain and switch bs back to the QEMU main loop */
-    bdrv_set_aio_context(s->blk->conf.bs, qemu_get_aio_context());
+    bdrv_set_aio_context(s->conf->conf.bs, qemu_get_aio_context());
 
     aio_context_release(s->ctx);
 
diff --git a/hw/block/dataplane/virtio-blk.h b/hw/block/dataplane/virtio-blk.h
index 1750c99..c88d40e 100644
--- a/hw/block/dataplane/virtio-blk.h
+++ b/hw/block/dataplane/virtio-blk.h
@@ -19,7 +19,7 @@
 
 typedef struct VirtIOBlockDataPlane VirtIOBlockDataPlane;
 
-void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
+void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
                                   VirtIOBlockDataPlane **dataplane,
                                   Error **errp);
 void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s);
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 0be7203..347f372 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -157,7 +157,7 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
      */
     scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base;
 
-    if (!blk->blk.scsi) {
+    if (!blk->conf.scsi) {
         status = VIRTIO_BLK_S_UNSUPP;
         goto fail;
     }
@@ -297,7 +297,7 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
     if (sector & dev->sector_mask) {
         return false;
     }
-    if (size % dev->blk.conf.logical_block_size) {
+    if (size % dev->conf.conf.logical_block_size) {
         return false;
     }
     bdrv_get_geometry(dev->bs, &total_sectors);
@@ -404,7 +404,7 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
          * NB: per existing s/n string convention the string is
          * terminated by '\0' only when shorter than buffer.
          */
-        const char *serial = s->blk.serial ? s->blk.serial : "";
+        const char *serial = s->conf.serial ? s->conf.serial : "";
         size_t size = MIN(strlen(serial) + 1,
                           MIN(iov_size(in_iov, in_num),
                               VIRTIO_BLK_ID_BYTES));
@@ -487,7 +487,7 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running,
     }
 
     if (!s->bh) {
-        s->bh = aio_bh_new(bdrv_get_aio_context(s->blk.conf.bs),
+        s->bh = aio_bh_new(bdrv_get_aio_context(s->conf.conf.bs),
                            virtio_blk_dma_restart_bh, s);
         qemu_bh_schedule(s->bh);
     }
@@ -516,7 +516,7 @@ static void virtio_blk_reset(VirtIODevice *vdev)
 static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
 {
     VirtIOBlock *s = VIRTIO_BLK(vdev);
-    BlockConf *conf = &s->blk.conf;
+    BlockConf *conf = &s->conf.conf;
     struct virtio_blk_config blkcfg;
     uint64_t capacity;
     int blk_size = conf->logical_block_size;
@@ -547,7 +547,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
         blkcfg.sectors = conf->secs;
     }
     blkcfg.size_max = 0;
-    blkcfg.physical_block_exp = get_physical_block_exp(&s->blk.conf);
+    blkcfg.physical_block_exp = get_physical_block_exp(&s->conf.conf);
     blkcfg.alignment_offset = 0;
     blkcfg.wce = bdrv_enable_write_cache(s->bs);
     memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
@@ -575,7 +575,7 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
     features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
     features |= (1 << VIRTIO_BLK_F_SCSI);
 
-    if (s->blk.config_wce) {
+    if (s->conf.config_wce) {
         features |= (1 << VIRTIO_BLK_F_CONFIG_WCE);
     }
     if (bdrv_enable_write_cache(s->bs))
@@ -715,7 +715,7 @@ static void virtio_blk_migration_state_changed(Notifier *notifier, void *data)
             return;
         }
         bdrv_drain_all(); /* complete in-flight non-dataplane requests */
-        virtio_blk_data_plane_create(VIRTIO_DEVICE(s), &s->blk,
+        virtio_blk_data_plane_create(VIRTIO_DEVICE(s), &s->conf,
                                      &s->dataplane, &err);
         if (err != NULL) {
             error_report("%s", error_get_pretty(err));
@@ -729,22 +729,22 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VirtIOBlock *s = VIRTIO_BLK(dev);
-    VirtIOBlkConf *blk = &(s->blk);
+    VirtIOBlkConf *conf = &s->conf;
     Error *err = NULL;
     static int virtio_blk_id;
 
-    if (!blk->conf.bs) {
+    if (!conf->conf.bs) {
         error_setg(errp, "drive property not set");
         return;
     }
-    if (!bdrv_is_inserted(blk->conf.bs)) {
+    if (!bdrv_is_inserted(conf->conf.bs)) {
         error_setg(errp, "Device needs media, but drive is empty");
         return;
     }
 
-    blkconf_serial(&blk->conf, &blk->serial);
-    s->original_wce = bdrv_enable_write_cache(blk->conf.bs);
-    blkconf_geometry(&blk->conf, NULL, 65535, 255, 255, &err);
+    blkconf_serial(&conf->conf, &conf->serial);
+    s->original_wce = bdrv_enable_write_cache(conf->conf.bs);
+    blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, &err);
     if (err) {
         error_propagate(errp, err);
         return;
@@ -753,14 +753,14 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
     virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
                 sizeof(struct virtio_blk_config));
 
-    s->bs = blk->conf.bs;
+    s->bs = conf->conf.bs;
     s->rq = NULL;
-    s->sector_mask = (s->blk.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1;
+    s->sector_mask = (s->conf.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1;
 
     s->vq = virtio_add_queue(vdev, 128, virtio_blk_handle_output);
     s->complete_request = virtio_blk_complete_request;
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-    virtio_blk_data_plane_create(vdev, blk, &s->dataplane, &err);
+    virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err);
     if (err != NULL) {
         error_propagate(errp, err);
         virtio_cleanup(vdev);
@@ -774,11 +774,11 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
     register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
     bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
-    bdrv_set_guest_block_size(s->bs, s->blk.conf.logical_block_size);
+    bdrv_set_guest_block_size(s->bs, s->conf.conf.logical_block_size);
 
     bdrv_iostatus_enable(s->bs);
 
-    add_boot_device_path(s->blk.conf.bootindex, dev, "/disk@0,0");
+    add_boot_device_path(s->conf.conf.bootindex, dev, "/disk@0,0");
 }
 
 static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
@@ -802,21 +802,21 @@ static void virtio_blk_instance_init(Object *obj)
     VirtIOBlock *s = VIRTIO_BLK(obj);
 
     object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
-                             (Object **)&s->blk.iothread,
+                             (Object **)&s->conf.iothread,
                              qdev_prop_allow_set_link_before_realize,
                              OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
 }
 
 static Property virtio_blk_properties[] = {
-    DEFINE_BLOCK_PROPERTIES(VirtIOBlock, blk.conf),
-    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, blk.conf),
-    DEFINE_PROP_STRING("serial", VirtIOBlock, blk.serial),
-    DEFINE_PROP_BIT("config-wce", VirtIOBlock, blk.config_wce, 0, true),
+    DEFINE_BLOCK_PROPERTIES(VirtIOBlock, conf.conf),
+    DEFINE_BLOCK_CHS_PROPERTIES(VirtIOBlock, conf.conf),
+    DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial),
+    DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true),
 #ifdef __linux__
-    DEFINE_PROP_BIT("scsi", VirtIOBlock, blk.scsi, 0, true),
+    DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, true),
 #endif
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
-    DEFINE_PROP_BIT("x-data-plane", VirtIOBlock, blk.data_plane, 0, false),
+    DEFINE_PROP_BIT("x-data-plane", VirtIOBlock, conf.data_plane, 0, false),
 #endif
     DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index 1329482..b30237f 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -124,7 +124,7 @@ typedef struct VirtIOBlock {
     VirtQueue *vq;
     void *rq;
     QEMUBH *bh;
-    VirtIOBlkConf blk;
+    VirtIOBlkConf conf;
     unsigned short sector_mask;
     bool original_wce;
     VMChangeStateEntry *change;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 14/23] hw: Convert from BlockDriverState to BlockBackend, mostly
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (12 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 13/23] virtio-blk: Rename VirtIOBlkConf variables to conf Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 15/23] ide: Complete conversion from BlockDriverState to BlockBackend Markus Armbruster
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Just four uses of BlockDriverState are left:

* The Xen paravirtual block device backend (xen_disk.c) opens images
  itself when set up via xenbus, bypassing blockdev.c.  I figure it
  should go through qmp_blockdev_add() instead.

* Device model "usb-storage" prompts for keys.  No other device model
  does, and this one probably shouldn't do it, either.

* ide_issue_trim_cb() uses bdrv_aio_discard() instead of
  blk_aio_discard() because it fishes its backend out of a BlockAIOCB,
  which has only the BlockDriverState.

* PC87312State has an unused BlockDriverState[] member.

The next two commits take care of the latter two.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block/block-backend.c                    | 276 +++++++++++++++++++++++++++++++
 blockdev.c                               |  23 +--
 dma-helpers.c                            |  61 +++----
 hw/arm/collie.c                          |   5 +-
 hw/arm/gumstix.c                         |   5 +-
 hw/arm/highbank.c                        |   2 +-
 hw/arm/mainstone.c                       |   2 +-
 hw/arm/musicpal.c                        |  10 +-
 hw/arm/nseries.c                         |   3 +-
 hw/arm/omap1.c                           |   2 +-
 hw/arm/omap2.c                           |   2 +-
 hw/arm/omap_sx1.c                        |   5 +-
 hw/arm/pxa2xx.c                          |   4 +-
 hw/arm/realview.c                        |   2 +-
 hw/arm/spitz.c                           |   4 +-
 hw/arm/tosa.c                            |   3 +-
 hw/arm/versatilepb.c                     |   3 +-
 hw/arm/vexpress.c                        |   3 +-
 hw/arm/xilinx_zynq.c                     |   3 +-
 hw/arm/z2.c                              |   3 +-
 hw/block/block.c                         |   7 +-
 hw/block/dataplane/virtio-blk.c          |  24 +--
 hw/block/fdc.c                           |  78 +++++----
 hw/block/hd-geometry.c                   |  24 +--
 hw/block/m25p80.c                        |  28 ++--
 hw/block/nand.c                          |  50 +++---
 hw/block/nvme.c                          |  17 +-
 hw/block/onenand.c                       |  67 ++++----
 hw/block/pflash_cfi01.c                  |  24 +--
 hw/block/pflash_cfi02.c                  |  24 +--
 hw/block/virtio-blk.c                    |  95 +++++------
 hw/block/xen_disk.c                      |  83 +++++-----
 hw/core/qdev-properties-system.c         |  26 +--
 hw/core/qdev-properties.c                |   2 +-
 hw/cris/axis_dev88.c                     |   3 +-
 hw/display/tc6393xb.c                    |   2 +-
 hw/i386/pc.c                             |   2 +-
 hw/i386/pc_piix.c                        |   2 +-
 hw/i386/pc_sysfw.c                       |   9 +-
 hw/i386/xen/xen_platform.c               |   5 +-
 hw/ide/ahci.c                            |  31 ++--
 hw/ide/atapi.c                           |  33 ++--
 hw/ide/cmd646.c                          |   2 +-
 hw/ide/core.c                            | 190 +++++++++++----------
 hw/ide/ich.c                             |   2 +-
 hw/ide/internal.h                        |   6 +-
 hw/ide/isa.c                             |   2 +-
 hw/ide/macio.c                           |  52 +++---
 hw/ide/microdrive.c                      |   4 +-
 hw/ide/mmio.c                            |   2 +-
 hw/ide/pci.c                             |   4 +-
 hw/ide/piix.c                            |   9 +-
 hw/ide/qdev.c                            |  11 +-
 hw/ide/via.c                             |   2 +-
 hw/isa/pc87312.c                         |   4 +-
 hw/lm32/lm32_boards.c                    |   5 +-
 hw/lm32/milkymist.c                      |   3 +-
 hw/microblaze/petalogix_ml605_mmu.c      |   3 +-
 hw/microblaze/petalogix_s3adsp1800_mmu.c |   3 +-
 hw/mips/mips_fulong2e.c                  |   2 +-
 hw/mips/mips_jazz.c                      |   2 +-
 hw/mips/mips_malta.c                     |   6 +-
 hw/mips/mips_r4k.c                       |   3 +-
 hw/nvram/spapr_nvram.c                   |  17 +-
 hw/pci/pci-hotplug-old.c                 |   5 +-
 hw/ppc/mac_newworld.c                    |   2 +-
 hw/ppc/mac_oldworld.c                    |   2 +-
 hw/ppc/ppc405_boards.c                   |  26 +--
 hw/ppc/prep.c                            |   2 +-
 hw/ppc/spapr.c                           |   4 +-
 hw/ppc/virtex_ml507.c                    |   3 +-
 hw/s390x/s390-virtio-bus.c               |   2 +-
 hw/s390x/s390-virtio.c                   |   2 +-
 hw/s390x/virtio-ccw.c                    |   2 +-
 hw/scsi/megasas.c                        |  15 +-
 hw/scsi/scsi-bus.c                       |   8 +-
 hw/scsi/scsi-disk.c                      | 192 ++++++++++-----------
 hw/scsi/scsi-generic.c                   |  39 +++--
 hw/sd/milkymist-memcard.c                |   8 +-
 hw/sd/omap_mmc.c                         |   8 +-
 hw/sd/pl181.c                            |   2 +-
 hw/sd/pxa2xx_mmci.c                      |   4 +-
 hw/sd/sd.c                               |  60 +++----
 hw/sd/sdhci.c                            |   2 +-
 hw/sd/ssi-sd.c                           |   2 +-
 hw/sh4/r2d.c                             |   3 +-
 hw/sparc/sun4m.c                         |   2 +-
 hw/sparc64/sun4u.c                       |   2 +-
 hw/tpm/tpm_tis.c                         |   2 +-
 hw/tricore/tricore_testboard.c           |   2 +-
 hw/usb/dev-storage.c                     |  17 +-
 hw/virtio/virtio-pci.c                   |   2 +-
 hw/xen/xen_devconfig.c                   |   1 +
 hw/xenpv/xen_machine_pv.c                |   2 +-
 hw/xtensa/xtfpga.c                       |   3 +-
 include/hw/arm/omap.h                    |   4 +-
 include/hw/arm/pxa.h                     |   2 +-
 include/hw/block/block.h                 |   6 +-
 include/hw/block/flash.h                 |   6 +-
 include/hw/qdev-properties.h             |   8 +-
 include/hw/scsi/scsi.h                   |   4 +-
 include/hw/sd.h                          |   2 +-
 include/hw/virtio/virtio-blk.h           |   6 +-
 include/qemu/typedefs.h                  |   1 +
 include/sysemu/block-backend.h           |  78 +++++++++
 include/sysemu/blockdev.h                |   5 +-
 include/sysemu/dma.h                     |  24 +--
 trace-events                             |   8 +-
 108 files changed, 1157 insertions(+), 814 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index b2db97b..cc21f3c 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -129,6 +129,19 @@ static void drive_info_del(DriveInfo *dinfo)
     }
 }
 
+/**
+ * blk_make_anon:
+ *
+ * Strictly for use by do_drive_del().
+ * TODO get rid of it!
+ */
+void blk_make_anon(BlockBackend *blk)
+{
+    blk->name[0] = 0;
+    QTAILQ_REMOVE(&blk_backends, blk, link);
+    bdrv_make_anon(blk->bs);
+}
+
 const char *blk_name(BlockBackend *blk)
 {
     return blk->name;
@@ -224,3 +237,266 @@ BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
     }
     assert(0);
 }
+
+void blk_iostatus_enable(BlockBackend *blk)
+{
+    bdrv_iostatus_enable(blk->bs);
+}
+
+int blk_attach_dev(BlockBackend *blk, void *dev)
+{
+    return bdrv_attach_dev(blk->bs, dev);
+}
+
+void blk_attach_dev_nofail(BlockBackend *blk, void *dev)
+{
+    bdrv_attach_dev_nofail(blk->bs, dev);
+}
+
+void blk_detach_dev(BlockBackend *blk, void *dev)
+{
+    bdrv_detach_dev(blk->bs, dev);
+}
+
+void *blk_get_attached_dev(BlockBackend *blk)
+{
+    return bdrv_get_attached_dev(blk->bs);
+}
+
+void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque)
+{
+    bdrv_set_dev_ops(blk->bs, ops, opaque);
+}
+
+int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
+             int nb_sectors)
+{
+    return bdrv_read(blk->bs, sector_num, buf, nb_sectors);
+}
+
+int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
+                         int nb_sectors)
+{
+    return bdrv_read_unthrottled(blk->bs, sector_num, buf, nb_sectors);
+}
+
+int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf,
+              int nb_sectors)
+{
+    return bdrv_write(blk->bs, sector_num, buf, nb_sectors);
+}
+
+BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num,
+                                 int nb_sectors, BdrvRequestFlags flags,
+                                 BlockCompletionFunc *cb, void *opaque)
+{
+    return bdrv_aio_write_zeroes(blk->bs, sector_num, nb_sectors, flags,
+                                 cb, opaque);
+}
+
+int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count)
+{
+    return bdrv_pread(blk->bs, offset, buf, count);
+}
+
+int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count)
+{
+    return bdrv_pwrite(blk->bs, offset, buf, count);
+}
+
+int64_t blk_getlength(BlockBackend *blk)
+{
+    return bdrv_getlength(blk->bs);
+}
+
+void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
+{
+    bdrv_get_geometry(blk->bs, nb_sectors_ptr);
+}
+
+BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num,
+                          QEMUIOVector *iov, int nb_sectors,
+                          BlockCompletionFunc *cb, void *opaque)
+{
+    return bdrv_aio_readv(blk->bs, sector_num, iov, nb_sectors, cb, opaque);
+}
+
+BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num,
+                           QEMUIOVector *iov, int nb_sectors,
+                           BlockCompletionFunc *cb, void *opaque)
+{
+    return bdrv_aio_writev(blk->bs, sector_num, iov, nb_sectors, cb, opaque);
+}
+
+BlockAIOCB *blk_aio_flush(BlockBackend *blk,
+                          BlockCompletionFunc *cb, void *opaque)
+{
+    return bdrv_aio_flush(blk->bs, cb, opaque);
+}
+
+BlockAIOCB *blk_aio_discard(BlockBackend *blk,
+                            int64_t sector_num, int nb_sectors,
+                            BlockCompletionFunc *cb, void *opaque)
+{
+    return bdrv_aio_discard(blk->bs, sector_num, nb_sectors, cb, opaque);
+}
+
+void blk_aio_cancel(BlockAIOCB *acb)
+{
+    bdrv_aio_cancel(acb);
+}
+
+int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs)
+{
+    return bdrv_aio_multiwrite(blk->bs, reqs, num_reqs);
+}
+
+int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
+{
+    return bdrv_ioctl(blk->bs, req, buf);
+}
+
+BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
+                          BlockCompletionFunc *cb, void *opaque)
+{
+    return bdrv_aio_ioctl(blk->bs, req, buf, cb, opaque);
+}
+
+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();
+}
+
+BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read)
+{
+    return bdrv_get_on_error(blk->bs, is_read);
+}
+
+BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
+                                      int error)
+{
+    return bdrv_get_error_action(blk->bs, is_read, error);
+}
+
+void blk_error_action(BlockBackend *blk, BlockErrorAction action,
+                      bool is_read, int error)
+{
+    bdrv_error_action(blk->bs, action, is_read, error);
+}
+
+int blk_is_read_only(BlockBackend *blk)
+{
+    return bdrv_is_read_only(blk->bs);
+}
+
+int blk_is_sg(BlockBackend *blk)
+{
+    return bdrv_is_sg(blk->bs);
+}
+
+int blk_enable_write_cache(BlockBackend *blk)
+{
+    return bdrv_enable_write_cache(blk->bs);
+}
+
+void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
+{
+    bdrv_set_enable_write_cache(blk->bs, wce);
+}
+
+int blk_is_inserted(BlockBackend *blk)
+{
+    return bdrv_is_inserted(blk->bs);
+}
+
+void blk_lock_medium(BlockBackend *blk, bool locked)
+{
+    bdrv_lock_medium(blk->bs, locked);
+}
+
+void blk_eject(BlockBackend *blk, bool eject_flag)
+{
+    bdrv_eject(blk->bs, eject_flag);
+}
+
+int blk_get_flags(BlockBackend *blk)
+{
+    return bdrv_get_flags(blk->bs);
+}
+
+void blk_set_guest_block_size(BlockBackend *blk, int align)
+{
+    bdrv_set_guest_block_size(blk->bs, align);
+}
+
+void *blk_blockalign(BlockBackend *blk, size_t size)
+{
+    return qemu_blockalign(blk ? blk->bs : NULL, size);
+}
+
+bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
+{
+    return bdrv_op_is_blocked(blk->bs, op, errp);
+}
+
+void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason)
+{
+    bdrv_op_unblock(blk->bs, op, reason);
+}
+
+void blk_op_block_all(BlockBackend *blk, Error *reason)
+{
+    bdrv_op_block_all(blk->bs, reason);
+}
+
+void blk_op_unblock_all(BlockBackend *blk, Error *reason)
+{
+    bdrv_op_unblock_all(blk->bs, reason);
+}
+
+void blk_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
+                    int64_t bytes, enum BlockAcctType type)
+{
+    bdrv_acct_start(blk->bs, cookie, bytes, type);
+}
+
+void blk_acct_done(BlockBackend *blk, BlockAcctCookie *cookie)
+{
+    bdrv_acct_done(blk->bs, cookie);
+}
+
+AioContext *blk_get_aio_context(BlockBackend *blk)
+{
+    return bdrv_get_aio_context(blk->bs);
+}
+
+void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
+{
+    bdrv_set_aio_context(blk->bs, new_context);
+}
+
+void blk_io_plug(BlockBackend *blk)
+{
+    bdrv_io_plug(blk->bs);
+}
+
+void blk_io_unplug(BlockBackend *blk)
+{
+    bdrv_io_unplug(blk->bs);
+}
+
+void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
+                  BlockCompletionFunc *cb, void *opaque)
+{
+    return qemu_aio_get(aiocb_info, blk_bs(blk), cb, opaque);
+}
diff --git a/blockdev.c b/blockdev.c
index 5c75abd..6f1e479 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -85,10 +85,10 @@ static const int if_max_devs[IF_COUNT] = {
  * automatic deletion, and generic qdev code calls blockdev_auto_del()
  * when deletion is actually safe.
  */
-void blockdev_mark_auto_del(BlockDriverState *bs)
+void blockdev_mark_auto_del(BlockBackend *blk)
 {
-    BlockBackend *blk = bs->blk;
     DriveInfo *dinfo = blk_legacy_dinfo(blk);
+    BlockDriverState *bs = blk_bs(blk);
 
     if (dinfo && !dinfo->enable_auto_del) {
         return;
@@ -102,9 +102,8 @@ void blockdev_mark_auto_del(BlockDriverState *bs)
     }
 }
 
-void blockdev_auto_del(BlockDriverState *bs)
+void blockdev_auto_del(BlockBackend *blk)
 {
-    BlockBackend *blk = bs->blk;
     DriveInfo *dinfo = blk_legacy_dinfo(blk);
 
     if (dinfo && dinfo->auto_del) {
@@ -200,18 +199,6 @@ DriveInfo *drive_get_next(BlockInterfaceType type)
     return drive_get(type, 0, next_block_unit[type]++);
 }
 
-DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
-{
-    BlockBackend *blk;
-
-    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
-        if (blk_bs(blk) == bs) {
-            return blk_legacy_dinfo(blk);
-        }
-    }
-    return NULL;
-}
-
 static void bdrv_format_print(void *opaque, const char *name)
 {
     error_printf(" %s", name);
@@ -1766,9 +1753,7 @@ 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 (bdrv_get_attached_dev(bs)) {
-        blk_detach_bs(blk);
-        blk_unref(blk);
-        bdrv_make_anon(bs);
+        blk_make_anon(blk);
         /* Further I/O must not pause the guest */
         bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
                           BLOCKDEV_ON_ERROR_REPORT);
diff --git a/dma-helpers.c b/dma-helpers.c
index e7bea06..76d2597 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -7,6 +7,7 @@
  * (GNU GPL), version 2 or later.
  */
 
+#include "sysemu/block-backend.h"
 #include "sysemu/dma.h"
 #include "trace.h"
 #include "qemu/range.h"
@@ -68,7 +69,7 @@ void qemu_sglist_destroy(QEMUSGList *qsg)
 
 typedef struct {
     BlockAIOCB common;
-    BlockDriverState *bs;
+    BlockBackend *blk;
     BlockAIOCB *acb;
     QEMUSGList *sg;
     uint64_t sector_num;
@@ -81,7 +82,7 @@ typedef struct {
     DMAIOFunc *io_func;
 } DMAAIOCB;
 
-static void dma_bdrv_cb(void *opaque, int ret);
+static void dma_blk_cb(void *opaque, int ret);
 
 static void reschedule_dma(void *opaque)
 {
@@ -89,7 +90,7 @@ static void reschedule_dma(void *opaque)
 
     qemu_bh_delete(dbs->bh);
     dbs->bh = NULL;
-    dma_bdrv_cb(dbs, 0);
+    dma_blk_cb(dbs, 0);
 }
 
 static void continue_after_map_failure(void *opaque)
@@ -100,7 +101,7 @@ static void continue_after_map_failure(void *opaque)
     qemu_bh_schedule(dbs->bh);
 }
 
-static void dma_bdrv_unmap(DMAAIOCB *dbs)
+static void dma_blk_unmap(DMAAIOCB *dbs)
 {
     int i;
 
@@ -116,7 +117,7 @@ static void dma_complete(DMAAIOCB *dbs, int ret)
 {
     trace_dma_complete(dbs, ret, dbs->common.cb);
 
-    dma_bdrv_unmap(dbs);
+    dma_blk_unmap(dbs);
     if (dbs->common.cb) {
         dbs->common.cb(dbs->common.opaque, ret);
     }
@@ -133,13 +134,13 @@ static void dma_complete(DMAAIOCB *dbs, int ret)
     }
 }
 
-static void dma_bdrv_cb(void *opaque, int ret)
+static void dma_blk_cb(void *opaque, int ret)
 {
     DMAAIOCB *dbs = (DMAAIOCB *)opaque;
     dma_addr_t cur_addr, cur_len;
     void *mem;
 
-    trace_dma_bdrv_cb(dbs, ret);
+    trace_dma_blk_cb(dbs, ret);
 
     dbs->acb = NULL;
     dbs->sector_num += dbs->iov.size / 512;
@@ -148,7 +149,7 @@ static void dma_bdrv_cb(void *opaque, int ret)
         dma_complete(dbs, ret);
         return;
     }
-    dma_bdrv_unmap(dbs);
+    dma_blk_unmap(dbs);
 
     while (dbs->sg_cur_index < dbs->sg->nsg) {
         cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
@@ -174,8 +175,8 @@ static void dma_bdrv_cb(void *opaque, int ret)
         qemu_iovec_discard_back(&dbs->iov, dbs->iov.size & ~BDRV_SECTOR_MASK);
     }
 
-    dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
-                            dbs->iov.size / 512, dma_bdrv_cb, dbs);
+    dbs->acb = dbs->io_func(dbs->blk, dbs->sector_num, &dbs->iov,
+                            dbs->iov.size / 512, dma_blk_cb, dbs);
     assert(dbs->acb);
 }
 
@@ -189,7 +190,7 @@ static void dma_aio_cancel(BlockAIOCB *acb)
         BlockAIOCB *acb = dbs->acb;
         dbs->acb = NULL;
         dbs->in_cancel = true;
-        bdrv_aio_cancel(acb);
+        blk_aio_cancel(acb);
         dbs->in_cancel = false;
     }
     dbs->common.cb = NULL;
@@ -201,17 +202,17 @@ static const AIOCBInfo dma_aiocb_info = {
     .cancel             = dma_aio_cancel,
 };
 
-BlockAIOCB *dma_bdrv_io(
-    BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,
+BlockAIOCB *dma_blk_io(
+    BlockBackend *blk, QEMUSGList *sg, uint64_t sector_num,
     DMAIOFunc *io_func, BlockCompletionFunc *cb,
     void *opaque, DMADirection dir)
 {
-    DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque);
+    DMAAIOCB *dbs = blk_aio_get(&dma_aiocb_info, blk, cb, opaque);
 
-    trace_dma_bdrv_io(dbs, bs, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));
+    trace_dma_blk_io(dbs, blk, sector_num, (dir == DMA_DIRECTION_TO_DEVICE));
 
     dbs->acb = NULL;
-    dbs->bs = bs;
+    dbs->blk = blk;
     dbs->sg = sg;
     dbs->sector_num = sector_num;
     dbs->sg_cur_index = 0;
@@ -221,25 +222,25 @@ BlockAIOCB *dma_bdrv_io(
     dbs->io_func = io_func;
     dbs->bh = NULL;
     qemu_iovec_init(&dbs->iov, sg->nsg);
-    dma_bdrv_cb(dbs, 0);
+    dma_blk_cb(dbs, 0);
     return &dbs->common;
 }
 
 
-BlockAIOCB *dma_bdrv_read(BlockDriverState *bs,
+BlockAIOCB *dma_blk_read(BlockBackend *blk,
+                         QEMUSGList *sg, uint64_t sector,
+                         void (*cb)(void *opaque, int ret), void *opaque)
+{
+    return dma_blk_io(blk, sg, sector, blk_aio_readv, cb, opaque,
+                      DMA_DIRECTION_FROM_DEVICE);
+}
+
+BlockAIOCB *dma_blk_write(BlockBackend *blk,
                           QEMUSGList *sg, uint64_t sector,
                           void (*cb)(void *opaque, int ret), void *opaque)
 {
-    return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque,
-                       DMA_DIRECTION_FROM_DEVICE);
-}
-
-BlockAIOCB *dma_bdrv_write(BlockDriverState *bs,
-                           QEMUSGList *sg, uint64_t sector,
-                           void (*cb)(void *opaque, int ret), void *opaque)
-{
-    return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque,
-                       DMA_DIRECTION_TO_DEVICE);
+    return dma_blk_io(blk, sg, sector, blk_aio_writev, cb, opaque,
+                      DMA_DIRECTION_TO_DEVICE);
 }
 
 
@@ -274,8 +275,8 @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg)
     return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE);
 }
 
-void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
+void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
                     QEMUSGList *sg, enum BlockAcctType type)
 {
-    bdrv_acct_start(bs, cookie, sg->size, type);
+    blk_acct_start(blk, cookie, sg->size, type);
 }
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
index 0247290..6c9b82f 100644
--- a/hw/arm/collie.c
+++ b/hw/arm/collie.c
@@ -16,7 +16,6 @@
 #include "hw/arm/arm.h"
 #include "hw/block/flash.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
 static struct arm_boot_info collie_binfo = {
@@ -42,12 +41,12 @@ static void collie_init(MachineState *machine)
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
-                    dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                    dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                     (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
 
     dinfo = drive_get(IF_PFLASH, 0, 1);
     pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
-                    dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                    dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                     (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
 
     sysbus_create_simple("scoop", 0x40800000, NULL);
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
index 49f9339..8103278 100644
--- a/hw/arm/gumstix.c
+++ b/hw/arm/gumstix.c
@@ -41,7 +41,6 @@
 #include "hw/devices.h"
 #include "hw/boards.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "sysemu/qtest.h"
 
@@ -72,7 +71,7 @@ static void connex_init(MachineState *machine)
     be = 0;
 #endif
     if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
-                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                               dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                                sector_len, connex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
@@ -110,7 +109,7 @@ static void verdex_init(MachineState *machine)
     be = 0;
 #endif
     if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
-                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                               dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                                sector_len, verdex_rom / sector_len,
                                2, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index 8340434..2c2eb6b 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -24,7 +24,7 @@
 #include "net/net.h"
 #include "sysemu/sysemu.h"
 #include "hw/boards.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "exec/address-spaces.h"
 #include "qemu/error-report.h"
 
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
index fb17d85..6ec7892 100644
--- a/hw/arm/mainstone.c
+++ b/hw/arm/mainstone.c
@@ -148,7 +148,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
         if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
                                    i ? "mainstone.flash1" : "mainstone.flash0",
                                    MAINSTONE_FLASH,
-                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                   blk_by_legacy_dinfo(dinfo),
                                    sector_len, MAINSTONE_FLASH / sector_len,
                                    4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory.\n");
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 6a41d9c..92a634a 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -18,12 +18,10 @@
 #include "hw/char/serial.h"
 #include "qemu/timer.h"
 #include "hw/ptimer.h"
-#include "block/block.h"
 #include "hw/block/flash.h"
 #include "ui/console.h"
 #include "hw/i2c/i2c.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "ui/pixel_ops.h"
 
@@ -1631,9 +1629,9 @@ static void musicpal_init(MachineState *machine)
     /* Register flash */
     dinfo = drive_get(IF_PFLASH, 0, 0);
     if (dinfo) {
-        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
+        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
 
-        flash_size = bdrv_getlength(bs);
+        flash_size = blk_getlength(blk);
         if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
             flash_size != 32*1024*1024) {
             fprintf(stderr, "Invalid flash image size\n");
@@ -1648,14 +1646,14 @@ static void musicpal_init(MachineState *machine)
 #ifdef TARGET_WORDS_BIGENDIAN
         pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
                               "musicpal.flash", flash_size,
-                              bs, 0x10000, (flash_size + 0xffff) >> 16,
+                              blk, 0x10000, (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 1);
 #else
         pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
                               "musicpal.flash", flash_size,
-                              bs, 0x10000, (flash_size + 0xffff) >> 16,
+                              blk, 0x10000, (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
                               0x5555, 0x2AAA, 0);
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
index 2536078..c7ebaa6 100644
--- a/hw/arm/nseries.c
+++ b/hw/arm/nseries.c
@@ -32,7 +32,6 @@
 #include "hw/bt.h"
 #include "hw/loader.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
@@ -175,7 +174,7 @@ static void n8x0_nand_setup(struct n800_s *s)
     dinfo = drive_get(IF_MTD, 0, 0);
     if (dinfo) {
         qdev_prop_set_drive_nofail(s->nand, "drive",
-                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
+                                   blk_by_legacy_dinfo(dinfo));
     }
     qdev_init_nofail(s->nand);
     sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index e38e07f..786b571 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -3978,7 +3978,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
         exit(1);
     }
     s->mmc = omap_mmc_init(0xfffb7800, system_memory,
-                           blk_bs(blk_by_legacy_dinfo(dinfo)),
+                           blk_by_legacy_dinfo(dinfo),
                            qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
                            &s->drq[OMAP_DMA_MMC_TX],
                     omap_findclk(s, "mmc_ck"));
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
index e47dd63..e2accbf 100644
--- a/hw/arm/omap2.c
+++ b/hw/arm/omap2.c
@@ -2461,7 +2461,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
         exit(1);
     }
     s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9),
-                    blk_bs(blk_by_legacy_dinfo(dinfo)),
+                    blk_by_legacy_dinfo(dinfo),
                     qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
                     &s->drq[OMAP24XX_DMA_MMC1_TX],
                     omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
index f475afc..5ee0d4e 100644
--- a/hw/arm/omap_sx1.c
+++ b/hw/arm/omap_sx1.c
@@ -32,7 +32,6 @@
 #include "hw/arm/arm.h"
 #include "hw/block/flash.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "sysemu/qtest.h"
 #include "exec/address-spaces.h"
 
@@ -154,7 +153,7 @@ static void sx1_init(MachineState *machine, const int version)
     if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
         if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
                                    "omap_sx1.flash0-1", flash_size,
-                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                   blk_by_legacy_dinfo(dinfo),
                                    sector_size, flash_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
@@ -177,7 +176,7 @@ static void sx1_init(MachineState *machine, const int version)
 
         if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
                                    "omap_sx1.flash1-1", flash1_size,
-                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                   blk_by_legacy_dinfo(dinfo),
                                    sector_size, flash1_size / sector_size,
                                    4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 7ec0da8..2b72e25 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -2085,7 +2085,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
         exit(1);
     }
     s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
-                    blk_bs(blk_by_legacy_dinfo(dinfo)),
+                    blk_by_legacy_dinfo(dinfo),
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
@@ -2217,7 +2217,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
         exit(1);
     }
     s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
-                    blk_bs(blk_by_legacy_dinfo(dinfo)),
+                    blk_by_legacy_dinfo(dinfo),
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
                     qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
                     qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index 64b9251..820c17a 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -16,7 +16,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/boards.h"
 #include "hw/i2c/i2c.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "exec/address-spaces.h"
 #include "qemu/error-report.h"
 
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 5d684a2..cd3d6ca 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -22,11 +22,9 @@
 #include "hw/devices.h"
 #include "hw/arm/sharpsl.h"
 #include "ui/console.h"
-#include "block/block.h"
 #include "audio/audio.h"
 #include "hw/boards.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
@@ -171,7 +169,7 @@ static int sl_nand_init(SysBusDevice *dev)
 
     s->ctl = 0;
     nand = drive_get(IF_MTD, 0, 0);
-    s->nand = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,
+    s->nand = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL,
                         s->manf_id, s->chip_id);
 
     memory_region_init_io(&s->iomem, OBJECT(s), &sl_ops, s, "sl", 0x40);
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
index abc0f2a..3c59f82 100644
--- a/hw/arm/tosa.c
+++ b/hw/arm/tosa.c
@@ -17,11 +17,10 @@
 #include "hw/devices.h"
 #include "hw/arm/sharpsl.h"
 #include "hw/pcmcia.h"
-#include "block/block.h"
 #include "hw/boards.h"
 #include "hw/i2c/i2c.h"
 #include "hw/ssi.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index c88be6b..3e43c2d 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -16,7 +16,6 @@
 #include "hw/i2c/i2c.h"
 #include "hw/boards.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "hw/block/flash.h"
 
@@ -339,7 +338,7 @@ static void versatile_init(MachineState *machine, int board_id)
     dinfo = drive_get(IF_PFLASH, 0, 0);
     if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
                           VERSATILE_FLASH_SIZE,
-                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           VERSATILE_FLASH_SECT_SIZE,
                           VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
                           4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index a492c22..ad43753 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -31,7 +31,6 @@
 #include "hw/loader.h"
 #include "exec/address-spaces.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "hw/block/flash.h"
 #include "sysemu/device_tree.h"
 #include "qemu/error-report.h"
@@ -490,7 +489,7 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
     DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
 
     if (di && qdev_prop_set_drive(dev, "drive",
-                                  blk_bs(blk_by_legacy_dinfo(di)))) {
+                                  blk_by_legacy_dinfo(di))) {
         abort();
     }
 
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 78e6934..601ff39 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -23,7 +23,6 @@
 #include "hw/boards.h"
 #include "hw/block/flash.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "hw/loader.h"
 #include "hw/ssi.h"
 #include "qemu/error-report.h"
@@ -163,7 +162,7 @@ static void zynq_init(MachineState *machine)
 
     /* AMD */
     pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
-                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           FLASH_SECTOR_SIZE,
                           FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
                           1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
index 9b38a2b..1735547 100644
--- a/hw/arm/z2.c
+++ b/hw/arm/z2.c
@@ -21,7 +21,6 @@
 #include "sysemu/sysemu.h"
 #include "hw/block/flash.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "ui/console.h"
 #include "audio/audio.h"
 #include "exec/address-spaces.h"
@@ -337,7 +336,7 @@ static void z2_init(MachineState *machine)
 
     if (!pflash_cfi01_register(Z2_FLASH_BASE,
                                NULL, "z2.flash0", Z2_FLASH_SIZE,
-                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                               dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                                sector_len, Z2_FLASH_SIZE / sector_len,
                                4, 0, 0, 0, 0, be)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
diff --git a/hw/block/block.c b/hw/block/block.c
index b6a6dc6..0666dd3 100644
--- a/hw/block/block.c
+++ b/hw/block/block.c
@@ -8,6 +8,7 @@
  */
 
 #include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "hw/block/block.h"
 #include "qemu/error-report.h"
 
@@ -17,7 +18,7 @@ void blkconf_serial(BlockConf *conf, char **serial)
 
     if (!*serial) {
         /* try to fall back to value set with legacy -drive serial=... */
-        dinfo = drive_get_by_blockdev(conf->bs);
+        dinfo = blk_legacy_dinfo(conf->blk);
         *serial = g_strdup(dinfo->serial);
     }
 }
@@ -30,7 +31,7 @@ void blkconf_geometry(BlockConf *conf, int *ptrans,
 
     if (!conf->cyls && !conf->heads && !conf->secs) {
         /* try to fall back to value set with legacy -drive cyls=... */
-        dinfo = drive_get_by_blockdev(conf->bs);
+        dinfo = blk_legacy_dinfo(conf->blk);
         conf->cyls  = dinfo->cyls;
         conf->heads = dinfo->heads;
         conf->secs  = dinfo->secs;
@@ -39,7 +40,7 @@ void blkconf_geometry(BlockConf *conf, int *ptrans,
         }
     }
     if (!conf->cyls && !conf->heads && !conf->secs) {
-        hd_geometry_guess(conf->bs,
+        hd_geometry_guess(conf->blk,
                           &conf->cyls, &conf->heads, &conf->secs,
                           ptrans);
     } else if (ptrans && *ptrans == BIOS_ATA_TRANSLATION_AUTO) {
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index af67dc3..ab5df12 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -17,7 +17,7 @@
 #include "qemu/thread.h"
 #include "qemu/error-report.h"
 #include "hw/virtio/dataplane/vring.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "hw/virtio/virtio-blk.h"
 #include "virtio-blk.h"
 #include "block/aio.h"
@@ -94,7 +94,7 @@ static void handle_notify(EventNotifier *e)
     VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
 
     event_notifier_test_and_clear(&s->host_notifier);
-    bdrv_io_plug(s->conf->conf.bs);
+    blk_io_plug(s->conf->conf.blk);
     for (;;) {
         MultiReqBuffer mrb = {
             .num_writes = 0,
@@ -120,7 +120,7 @@ static void handle_notify(EventNotifier *e)
             virtio_blk_handle_request(req, &mrb);
         }
 
-        virtio_submit_multiwrite(s->conf->conf.bs, &mrb);
+        virtio_submit_multiwrite(s->conf->conf.blk, &mrb);
 
         if (likely(ret == -EAGAIN)) { /* vring emptied */
             /* Re-enable guest->host notifies and stop processing the vring.
@@ -133,7 +133,7 @@ static void handle_notify(EventNotifier *e)
             break;
         }
     }
-    bdrv_io_unplug(s->conf->conf.bs);
+    blk_io_unplug(s->conf->conf.blk);
 }
 
 /* Context: QEMU global mutex held */
@@ -163,8 +163,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
     /* If dataplane is (re-)enabled while the guest is running there could be
      * block jobs that can conflict.
      */
-    if (bdrv_op_is_blocked(conf->conf.bs, BLOCK_OP_TYPE_DATAPLANE,
-                           &local_err)) {
+    if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE,
+                          &local_err)) {
         error_report("cannot start dataplane thread: %s",
                       error_get_pretty(local_err));
         error_free(local_err);
@@ -193,9 +193,9 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
     s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
 
     error_setg(&s->blocker, "block device is in use by data plane");
-    bdrv_op_block_all(conf->conf.bs, s->blocker);
-    bdrv_op_unblock(conf->conf.bs, BLOCK_OP_TYPE_RESIZE, s->blocker);
-    bdrv_op_unblock(conf->conf.bs, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
+    blk_op_block_all(conf->conf.blk, s->blocker);
+    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker);
+    blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
 
     *dataplane = s;
 }
@@ -208,7 +208,7 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
     }
 
     virtio_blk_data_plane_stop(s);
-    bdrv_op_unblock_all(s->conf->conf.bs, s->blocker);
+    blk_op_unblock_all(s->conf->conf.blk, s->blocker);
     error_free(s->blocker);
     object_unref(OBJECT(s->iothread));
     qemu_bh_delete(s->bh);
@@ -263,7 +263,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
     s->started = true;
     trace_virtio_blk_data_plane_start(s);
 
-    bdrv_set_aio_context(s->conf->conf.bs, s->ctx);
+    blk_set_aio_context(s->conf->conf.blk, s->ctx);
 
     /* Kick right away to begin processing requests already in vring */
     event_notifier_set(virtio_queue_get_host_notifier(vq));
@@ -309,7 +309,7 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
     aio_set_event_notifier(s->ctx, &s->host_notifier, NULL);
 
     /* Drain and switch bs back to the QEMU main loop */
-    bdrv_set_aio_context(s->conf->conf.bs, qemu_get_aio_context());
+    blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context());
 
     aio_context_release(s->ctx);
 
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 19f215f..4b20339 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -114,7 +114,7 @@ static const FDFormat fd_formats[] = {
     { FDRIVE_DRV_NONE, -1, -1, 0, 0, },
 };
 
-static void pick_geometry(BlockDriverState *bs, int *nb_heads,
+static void pick_geometry(BlockBackend *blk, int *nb_heads,
                           int *max_track, int *last_sect,
                           FDriveType drive_in, FDriveType *drive,
                           FDriveRate *rate)
@@ -123,7 +123,7 @@ static void pick_geometry(BlockDriverState *bs, int *nb_heads,
     uint64_t nb_sectors, size;
     int i, first_match, match;
 
-    bdrv_get_geometry(bs, &nb_sectors);
+    blk_get_geometry(blk, &nb_sectors);
     match = -1;
     first_match = -1;
     for (i = 0; ; i++) {
@@ -176,7 +176,7 @@ typedef enum FDiskFlags {
 
 typedef struct FDrive {
     FDCtrl *fdctrl;
-    BlockDriverState *bs;
+    BlockBackend *blk;
     /* Drive status */
     FDriveType drive;
     uint8_t perpendicular;    /* 2.88 MB access mode    */
@@ -261,7 +261,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
 #endif
         drv->head = head;
         if (drv->track != track) {
-            if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
+            if (drv->blk != NULL && blk_is_inserted(drv->blk)) {
                 drv->media_changed = 0;
             }
             ret = 1;
@@ -270,7 +270,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
         drv->sect = sect;
     }
 
-    if (drv->bs == NULL || !bdrv_is_inserted(drv->bs)) {
+    if (drv->blk == NULL || !blk_is_inserted(drv->blk)) {
         ret = 2;
     }
 
@@ -292,11 +292,11 @@ static void fd_revalidate(FDrive *drv)
     FDriveRate rate;
 
     FLOPPY_DPRINTF("revalidate\n");
-    if (drv->bs != NULL) {
-        ro = bdrv_is_read_only(drv->bs);
-        pick_geometry(drv->bs, &nb_heads, &max_track,
+    if (drv->blk != NULL) {
+        ro = blk_is_read_only(drv->blk);
+        pick_geometry(drv->blk, &nb_heads, &max_track,
                       &last_sect, drv->drive, &drive, &rate);
-        if (!bdrv_is_inserted(drv->bs)) {
+        if (!blk_is_inserted(drv->blk)) {
             FLOPPY_DPRINTF("No disk in drive\n");
         } else {
             FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
@@ -666,7 +666,7 @@ static bool fdrive_media_changed_needed(void *opaque)
 {
     FDrive *drive = opaque;
 
-    return (drive->bs != NULL && drive->media_changed != 1);
+    return (drive->blk != NULL && drive->media_changed != 1);
 }
 
 static const VMStateDescription vmstate_fdrive_media_changed = {
@@ -839,8 +839,9 @@ static void fdctrl_reset(FDCtrl *fdctrl, int do_irq)
     /* Initialise controller */
     fdctrl->sra = 0;
     fdctrl->srb = 0xc0;
-    if (!fdctrl->drives[1].bs)
+    if (!fdctrl->drives[1].blk) {
         fdctrl->sra |= FD_SRA_nDRV2;
+    }
     fdctrl->cur_drv = 0;
     fdctrl->dor = FD_DOR_nRESET;
     fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0;
@@ -1330,7 +1331,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
         status2 = FD_SR2_SNS;
     if (dma_len > fdctrl->data_len)
         dma_len = fdctrl->data_len;
-    if (cur_drv->bs == NULL) {
+    if (cur_drv->blk == NULL) {
         if (fdctrl->data_dir == FD_DIR_WRITE)
             fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
         else
@@ -1351,8 +1352,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
         if (fdctrl->data_dir != FD_DIR_WRITE ||
             len < FD_SECTOR_LEN || rel_pos != 0) {
             /* READ & SCAN commands and realign to a sector for WRITE */
-            if (bdrv_read(cur_drv->bs, fd_sector(cur_drv),
-                          fdctrl->fifo, 1) < 0) {
+            if (blk_read(cur_drv->blk, fd_sector(cur_drv),
+                         fdctrl->fifo, 1) < 0) {
                 FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
                                fd_sector(cur_drv));
                 /* Sure, image size is too small... */
@@ -1379,8 +1380,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
 
             DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
                              fdctrl->data_pos, len);
-            if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
-                           fdctrl->fifo, 1) < 0) {
+            if (blk_write(cur_drv->blk, fd_sector(cur_drv),
+                          fdctrl->fifo, 1) < 0) {
                 FLOPPY_DPRINTF("error writing sector %d\n",
                                fd_sector(cur_drv));
                 fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
@@ -1455,7 +1456,8 @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
                                    fd_sector(cur_drv));
                     return 0;
                 }
-            if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
+            if (blk_read(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1)
+                < 0) {
                 FLOPPY_DPRINTF("error getting sector %d\n",
                                fd_sector(cur_drv));
                 /* Sure, image size is too small... */
@@ -1524,8 +1526,8 @@ static void fdctrl_format_sector(FDCtrl *fdctrl)
         break;
     }
     memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
-    if (cur_drv->bs == NULL ||
-        bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
+    if (cur_drv->blk == NULL ||
+        blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
         FLOPPY_DPRINTF("error formatting sector %d\n", fd_sector(cur_drv));
         fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
     } else {
@@ -1915,7 +1917,8 @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
         if (pos == FD_SECTOR_LEN - 1 ||
             fdctrl->data_pos == fdctrl->data_len) {
             cur_drv = get_cur_drv(fdctrl);
-            if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
+            if (blk_write(cur_drv->blk, fd_sector(cur_drv), fdctrl->fifo, 1)
+                < 0) {
                 FLOPPY_DPRINTF("error writing sector %d\n",
                                fd_sector(cur_drv));
                 return;
@@ -2003,12 +2006,12 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp)
         drive = &fdctrl->drives[i];
         drive->fdctrl = fdctrl;
 
-        if (drive->bs) {
-            if (bdrv_get_on_error(drive->bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
+        if (drive->blk) {
+            if (blk_get_on_error(drive->blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
                 error_setg(errp, "fdc doesn't support drive option werror");
                 return;
             }
-            if (bdrv_get_on_error(drive->bs, 1) != BLOCKDEV_ON_ERROR_REPORT) {
+            if (blk_get_on_error(drive->blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
                 error_setg(errp, "fdc doesn't support drive option rerror");
                 return;
             }
@@ -2016,8 +2019,8 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp)
 
         fd_init(drive);
         fdctrl_change_cb(drive, 0);
-        if (drive->bs) {
-            bdrv_set_dev_ops(drive->bs, &fdctrl_block_ops, drive);
+        if (drive->blk) {
+            blk_set_dev_ops(drive->blk, &fdctrl_block_ops, drive);
         }
     }
 }
@@ -2034,12 +2037,10 @@ ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds)
     dev = DEVICE(isadev);
 
     if (fds[0]) {
-        qdev_prop_set_drive_nofail(dev, "driveA",
-                                   blk_bs(blk_by_legacy_dinfo(fds[0])));
+        qdev_prop_set_drive_nofail(dev, "driveA", blk_by_legacy_dinfo(fds[0]));
     }
     if (fds[1]) {
-        qdev_prop_set_drive_nofail(dev, "driveB",
-                                   blk_bs(blk_by_legacy_dinfo(fds[1])));
+        qdev_prop_set_drive_nofail(dev, "driveB", blk_by_legacy_dinfo(fds[1]));
     }
     qdev_init_nofail(dev);
 
@@ -2059,12 +2060,10 @@ void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
     fdctrl = &sys->state;
     fdctrl->dma_chann = dma_chann; /* FIXME */
     if (fds[0]) {
-        qdev_prop_set_drive_nofail(dev, "driveA",
-                                   blk_bs(blk_by_legacy_dinfo(fds[0])));
+        qdev_prop_set_drive_nofail(dev, "driveA", blk_by_legacy_dinfo(fds[0]));
     }
     if (fds[1]) {
-        qdev_prop_set_drive_nofail(dev, "driveB",
-                                   blk_bs(blk_by_legacy_dinfo(fds[1])));
+        qdev_prop_set_drive_nofail(dev, "driveB", blk_by_legacy_dinfo(fds[1]));
     }
     qdev_init_nofail(dev);
     sbd = SYS_BUS_DEVICE(dev);
@@ -2080,8 +2079,7 @@ void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
 
     dev = qdev_create(NULL, "SUNW,fdtwo");
     if (fds[0]) {
-        qdev_prop_set_drive_nofail(dev, "drive",
-                                   blk_bs(blk_by_legacy_dinfo(fds[0])));
+        qdev_prop_set_drive_nofail(dev, "drive", blk_by_legacy_dinfo(fds[0]));
     }
     qdev_init_nofail(dev);
     sys = SYSBUS_FDC(dev);
@@ -2221,8 +2219,8 @@ static Property isa_fdc_properties[] = {
     DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0),
     DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6),
     DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2),
-    DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs),
-    DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
+    DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].blk),
+    DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].blk),
     DEFINE_PROP_INT32("bootindexA", FDCtrlISABus, bootindexA, -1),
     DEFINE_PROP_INT32("bootindexB", FDCtrlISABus, bootindexB, -1),
     DEFINE_PROP_BIT("check_media_rate", FDCtrlISABus, state.check_media_rate,
@@ -2260,8 +2258,8 @@ static const VMStateDescription vmstate_sysbus_fdc ={
 };
 
 static Property sysbus_fdc_properties[] = {
-    DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].bs),
-    DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].bs),
+    DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].blk),
+    DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -2281,7 +2279,7 @@ static const TypeInfo sysbus_fdc_info = {
 };
 
 static Property sun4m_fdc_properties[] = {
-    DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].bs),
+    DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c
index 6feb4f8..6fcf74d 100644
--- a/hw/block/hd-geometry.c
+++ b/hw/block/hd-geometry.c
@@ -30,7 +30,7 @@
  * THE SOFTWARE.
  */
 
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "hw/block/block.h"
 #include "trace.h"
 
@@ -49,7 +49,7 @@ struct partition {
 
 /* try to guess the disk logical geometry from the MSDOS partition table.
    Return 0 if OK, -1 if could not guess */
-static int guess_disk_lchs(BlockDriverState *bs,
+static int guess_disk_lchs(BlockBackend *blk,
                            int *pcylinders, int *pheads, int *psectors)
 {
     uint8_t buf[BDRV_SECTOR_SIZE];
@@ -58,14 +58,14 @@ static int guess_disk_lchs(BlockDriverState *bs,
     uint32_t nr_sects;
     uint64_t nb_sectors;
 
-    bdrv_get_geometry(bs, &nb_sectors);
+    blk_get_geometry(blk, &nb_sectors);
 
     /**
      * The function will be invoked during startup not only in sync I/O mode,
      * but also in async I/O mode. So the I/O throttling function has to
      * be disabled temporarily here, not permanently.
      */
-    if (bdrv_read_unthrottled(bs, 0, buf, 1) < 0) {
+    if (blk_read_unthrottled(blk, 0, buf, 1) < 0) {
         return -1;
     }
     /* test msdos magic */
@@ -90,20 +90,20 @@ static int guess_disk_lchs(BlockDriverState *bs,
             *pheads = heads;
             *psectors = sectors;
             *pcylinders = cylinders;
-            trace_hd_geometry_lchs_guess(bs, cylinders, heads, sectors);
+            trace_hd_geometry_lchs_guess(blk, cylinders, heads, sectors);
             return 0;
         }
     }
     return -1;
 }
 
-static void guess_chs_for_size(BlockDriverState *bs,
+static void guess_chs_for_size(BlockBackend *blk,
                 uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs)
 {
     uint64_t nb_sectors;
     int cylinders;
 
-    bdrv_get_geometry(bs, &nb_sectors);
+    blk_get_geometry(blk, &nb_sectors);
 
     cylinders = nb_sectors / (16 * 63);
     if (cylinders > 16383) {
@@ -116,21 +116,21 @@ static void guess_chs_for_size(BlockDriverState *bs,
     *psecs = 63;
 }
 
-void hd_geometry_guess(BlockDriverState *bs,
+void hd_geometry_guess(BlockBackend *blk,
                        uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs,
                        int *ptrans)
 {
     int cylinders, heads, secs, translation;
 
-    if (guess_disk_lchs(bs, &cylinders, &heads, &secs) < 0) {
+    if (guess_disk_lchs(blk, &cylinders, &heads, &secs) < 0) {
         /* no LCHS guess: use a standard physical disk geometry  */
-        guess_chs_for_size(bs, pcyls, pheads, psecs);
+        guess_chs_for_size(blk, pcyls, pheads, psecs);
         translation = hd_bios_chs_auto_trans(*pcyls, *pheads, *psecs);
     } else if (heads > 16) {
         /* LCHS guess with heads > 16 means that a BIOS LBA
            translation was active, so a standard physical disk
            geometry is OK */
-        guess_chs_for_size(bs, pcyls, pheads, psecs);
+        guess_chs_for_size(blk, pcyls, pheads, psecs);
         translation = *pcyls * *pheads <= 131072
             ? BIOS_ATA_TRANSLATION_LARGE
             : BIOS_ATA_TRANSLATION_LBA;
@@ -146,7 +146,7 @@ void hd_geometry_guess(BlockDriverState *bs,
     if (ptrans) {
         *ptrans = translation;
     }
-    trace_hd_geometry_guess(bs, *pcyls, *pheads, *psecs, translation);
+    trace_hd_geometry_guess(blk, *pcyls, *pheads, *psecs, translation);
 }
 
 int hd_bios_chs_auto_trans(uint32_t cyls, uint32_t heads, uint32_t secs)
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 78280a8..ff1106b 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -246,7 +246,7 @@ typedef struct Flash {
 
     uint32_t r;
 
-    BlockDriverState *bdrv;
+    BlockBackend *blk;
 
     uint8_t *storage;
     uint32_t size;
@@ -280,7 +280,7 @@ typedef struct M25P80Class {
 #define M25P80_GET_CLASS(obj) \
      OBJECT_GET_CLASS(M25P80Class, (obj), TYPE_M25P80)
 
-static void bdrv_sync_complete(void *opaque, int ret)
+static void blk_sync_complete(void *opaque, int ret)
 {
     /* do nothing. Masters do not directly interact with the backing store,
      * only the working copy so no mutexing required.
@@ -289,20 +289,20 @@ static void bdrv_sync_complete(void *opaque, int ret)
 
 static void flash_sync_page(Flash *s, int page)
 {
-    int bdrv_sector, nb_sectors;
+    int blk_sector, nb_sectors;
     QEMUIOVector iov;
 
-    if (!s->bdrv || bdrv_is_read_only(s->bdrv)) {
+    if (!s->blk || blk_is_read_only(s->blk)) {
         return;
     }
 
-    bdrv_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE;
+    blk_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE;
     nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE);
     qemu_iovec_init(&iov, 1);
-    qemu_iovec_add(&iov, s->storage + bdrv_sector * BDRV_SECTOR_SIZE,
+    qemu_iovec_add(&iov, s->storage + blk_sector * BDRV_SECTOR_SIZE,
                    nb_sectors * BDRV_SECTOR_SIZE);
-    bdrv_aio_writev(s->bdrv, bdrv_sector, &iov, nb_sectors, bdrv_sync_complete,
-                    NULL);
+    blk_aio_writev(s->blk, blk_sector, &iov, nb_sectors, blk_sync_complete,
+                   NULL);
 }
 
 static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
@@ -310,7 +310,7 @@ static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
     int64_t start, end, nb_sectors;
     QEMUIOVector iov;
 
-    if (!s->bdrv || bdrv_is_read_only(s->bdrv)) {
+    if (!s->blk || blk_is_read_only(s->blk)) {
         return;
     }
 
@@ -321,7 +321,7 @@ static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
     qemu_iovec_init(&iov, 1);
     qemu_iovec_add(&iov, s->storage + (start * BDRV_SECTOR_SIZE),
                                         nb_sectors * BDRV_SECTOR_SIZE);
-    bdrv_aio_writev(s->bdrv, start, &iov, nb_sectors, bdrv_sync_complete, NULL);
+    blk_aio_writev(s->blk, start, &iov, nb_sectors, blk_sync_complete, NULL);
 }
 
 static void flash_erase(Flash *s, int offset, FlashCMD cmd)
@@ -621,17 +621,17 @@ static int m25p80_init(SSISlave *ss)
 
     s->size = s->pi->sector_size * s->pi->n_sectors;
     s->dirty_page = -1;
-    s->storage = qemu_blockalign(s->bdrv, s->size);
+    s->storage = blk_blockalign(s->blk, s->size);
 
     dinfo = drive_get_next(IF_MTD);
 
     if (dinfo) {
         DB_PRINT_L(0, "Binding to IF_MTD drive\n");
-        s->bdrv = blk_bs(blk_by_legacy_dinfo(dinfo));
+        s->blk = blk_by_legacy_dinfo(dinfo);
 
         /* FIXME: Move to late init */
-        if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size,
-                                                    BDRV_SECTOR_SIZE))) {
+        if (blk_read(s->blk, 0, s->storage,
+                     DIV_ROUND_UP(s->size, BDRV_SECTOR_SIZE))) {
             fprintf(stderr, "Failed to initialize SPI flash!\n");
             return 1;
         }
diff --git a/hw/block/nand.c b/hw/block/nand.c
index 38eefd4..1882a0c 100644
--- a/hw/block/nand.c
+++ b/hw/block/nand.c
@@ -20,7 +20,7 @@
 
 # include "hw/hw.h"
 # include "hw/block/flash.h"
-# include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "hw/qdev.h"
 #include "qemu/error-report.h"
 
@@ -61,7 +61,7 @@ struct NANDFlashState {
     int size, pages;
     int page_shift, oob_shift, erase_shift, addr_shift;
     uint8_t *storage;
-    BlockDriverState *bdrv;
+    BlockBackend *blk;
     int mem_oob;
 
     uint8_t cle, ale, ce, wp, gnd;
@@ -400,12 +400,12 @@ static void nand_realize(DeviceState *dev, Error **errp)
 
     pagesize = 1 << s->oob_shift;
     s->mem_oob = 1;
-    if (s->bdrv) {
-        if (bdrv_is_read_only(s->bdrv)) {
+    if (s->blk) {
+        if (blk_is_read_only(s->blk)) {
             error_setg(errp, "Can't use a read-only drive");
             return;
         }
-        if (bdrv_getlength(s->bdrv) >=
+        if (blk_getlength(s->blk) >=
                 (s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
             pagesize = 0;
             s->mem_oob = 0;
@@ -424,7 +424,7 @@ static void nand_realize(DeviceState *dev, Error **errp)
 static Property nand_properties[] = {
     DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0),
     DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0),
-    DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv),
+    DEFINE_PROP_DRIVE("drive", NANDFlashState, blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -624,7 +624,7 @@ uint32_t nand_getbuswidth(DeviceState *dev)
     return s->buswidth << 3;
 }
 
-DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
+DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id)
 {
     DeviceState *dev;
 
@@ -634,8 +634,8 @@ DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id)
     dev = DEVICE(object_new(TYPE_NAND));
     qdev_prop_set_uint8(dev, "manufacturer_id", manf_id);
     qdev_prop_set_uint8(dev, "chip_id", chip_id);
-    if (bdrv) {
-        qdev_prop_set_drive_nofail(dev, "drive", bdrv);
+    if (blk) {
+        qdev_prop_set_drive_nofail(dev, "drive", blk);
     }
 
     qdev_init_nofail(dev);
@@ -654,14 +654,14 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
     if (PAGE(s->addr) >= s->pages)
         return;
 
-    if (!s->bdrv) {
+    if (!s->blk) {
         mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) +
                         s->offset, s->io, s->iolen);
     } else if (s->mem_oob) {
         sector = SECTOR(s->addr);
         off = (s->addr & PAGE_MASK) + s->offset;
         soff = SECTOR_OFFSET(s->addr);
-        if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) < 0) {
+        if (blk_read(s->blk, sector, iobuf, PAGE_SECTORS) < 0) {
             printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
             return;
         }
@@ -673,21 +673,21 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
                             MIN(OOB_SIZE, off + s->iolen - PAGE_SIZE));
         }
 
-        if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS) < 0) {
+        if (blk_write(s->blk, sector, iobuf, PAGE_SECTORS) < 0) {
             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
         }
     } else {
         off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
         sector = off >> 9;
         soff = off & 0x1ff;
-        if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) < 0) {
+        if (blk_read(s->blk, sector, iobuf, PAGE_SECTORS + 2) < 0) {
             printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
             return;
         }
 
         mem_and(iobuf + soff, s->io, s->iolen);
 
-        if (bdrv_write(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) < 0) {
+        if (blk_write(s->blk, sector, iobuf, PAGE_SECTORS + 2) < 0) {
             printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
         }
     }
@@ -705,7 +705,7 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
         return;
     }
 
-    if (!s->bdrv) {
+    if (!s->blk) {
         memset(s->storage + PAGE_START(addr),
                         0xff, (PAGE_SIZE + OOB_SIZE) << s->erase_shift);
     } else if (s->mem_oob) {
@@ -714,17 +714,17 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
         i = SECTOR(addr);
         page = SECTOR(addr + (ADDR_SHIFT + s->erase_shift));
         for (; i < page; i ++)
-            if (bdrv_write(s->bdrv, i, iobuf, 1) < 0) {
+            if (blk_write(s->blk, i, iobuf, 1) < 0) {
                 printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
             }
     } else {
         addr = PAGE_START(addr);
         page = addr >> 9;
-        if (bdrv_read(s->bdrv, page, iobuf, 1) < 0) {
+        if (blk_read(s->blk, page, iobuf, 1) < 0) {
             printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
         }
         memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
-        if (bdrv_write(s->bdrv, page, iobuf, 1) < 0) {
+        if (blk_write(s->blk, page, iobuf, 1) < 0) {
             printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
         }
 
@@ -732,18 +732,18 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
         i = (addr & ~0x1ff) + 0x200;
         for (addr += ((PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
                         i < addr; i += 0x200) {
-            if (bdrv_write(s->bdrv, i >> 9, iobuf, 1) < 0) {
+            if (blk_write(s->blk, i >> 9, iobuf, 1) < 0) {
                 printf("%s: write error in sector %" PRIu64 "\n",
                        __func__, i >> 9);
             }
         }
 
         page = i >> 9;
-        if (bdrv_read(s->bdrv, page, iobuf, 1) < 0) {
+        if (blk_read(s->blk, page, iobuf, 1) < 0) {
             printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
         }
         memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
-        if (bdrv_write(s->bdrv, page, iobuf, 1) < 0) {
+        if (blk_write(s->blk, page, iobuf, 1) < 0) {
             printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
         }
     }
@@ -756,9 +756,9 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
         return;
     }
 
-    if (s->bdrv) {
+    if (s->blk) {
         if (s->mem_oob) {
-            if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) < 0) {
+            if (blk_read(s->blk, SECTOR(addr), s->io, PAGE_SECTORS) < 0) {
                 printf("%s: read error in sector %" PRIu64 "\n",
                                 __func__, SECTOR(addr));
             }
@@ -767,8 +767,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
                             OOB_SIZE);
             s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset;
         } else {
-            if (bdrv_read(s->bdrv, PAGE_START(addr) >> 9,
-                                    s->io, (PAGE_SECTORS + 2)) < 0) {
+            if (blk_read(s->blk, PAGE_START(addr) >> 9,
+                         s->io, (PAGE_SECTORS + 2)) < 0) {
                 printf("%s: read error in sector %" PRIu64 "\n",
                                 __func__, PAGE_START(addr) >> 9);
             }
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 04459e5..3ffd69c 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -24,6 +24,7 @@
 #include <hw/hw.h>
 #include <hw/pci/msix.h>
 #include <hw/pci/pci.h>
+#include "sysemu/block-backend.h"
 
 #include "nvme.h"
 
@@ -197,7 +198,7 @@ static void nvme_rw_cb(void *opaque, int ret)
     NvmeCtrl *n = sq->ctrl;
     NvmeCQueue *cq = n->cq[sq->cqid];
 
-    bdrv_acct_done(n->conf.bs, &req->acct);
+    blk_acct_done(n->conf.blk, &req->acct);
     if (!ret) {
         req->status = NVME_SUCCESS;
     } else {
@@ -231,11 +232,11 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, NvmeCmd *cmd,
     }
     assert((nlb << data_shift) == req->qsg.size);
 
-    dma_acct_start(n->conf.bs, &req->acct, &req->qsg, is_write ?
+    dma_acct_start(n->conf.blk, &req->acct, &req->qsg, is_write ?
         BDRV_ACCT_WRITE : BDRV_ACCT_READ);
     req->aiocb = is_write ?
-        dma_bdrv_write(n->conf.bs, &req->qsg, aio_slba, nvme_rw_cb, req) :
-        dma_bdrv_read(n->conf.bs, &req->qsg, aio_slba, nvme_rw_cb, req);
+        dma_blk_write(n->conf.blk, &req->qsg, aio_slba, nvme_rw_cb, req) :
+        dma_blk_read(n->conf.blk, &req->qsg, aio_slba, nvme_rw_cb, req);
 
     return NVME_NO_COMPLETE;
 }
@@ -288,7 +289,7 @@ static uint16_t nvme_del_sq(NvmeCtrl *n, NvmeCmd *cmd)
     while (!QTAILQ_EMPTY(&sq->out_req_list)) {
         req = QTAILQ_FIRST(&sq->out_req_list);
         assert(req->aiocb);
-        bdrv_aio_cancel(req->aiocb);
+        blk_aio_cancel(req->aiocb);
     }
     if (!nvme_check_cqid(n, sq->cqid)) {
         cq = n->cq[sq->cqid];
@@ -563,7 +564,7 @@ static void nvme_clear_ctrl(NvmeCtrl *n)
         }
     }
 
-    bdrv_flush(n->conf.bs);
+    blk_flush(n->conf.blk);
     n->bar.cc = 0;
 }
 
@@ -748,11 +749,11 @@ static int nvme_init(PCIDevice *pci_dev)
     int64_t bs_size;
     uint8_t *pci_conf;
 
-    if (!(n->conf.bs)) {
+    if (!n->conf.blk) {
         return -1;
     }
 
-    bs_size = bdrv_getlength(n->conf.bs);
+    bs_size = blk_getlength(n->conf.blk);
     if (bs_size < 0) {
         return -1;
     }
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
index 5388122..a85861e 100644
--- a/hw/block/onenand.c
+++ b/hw/block/onenand.c
@@ -22,6 +22,7 @@
 #include "hw/hw.h"
 #include "hw/block/flash.h"
 #include "hw/irq.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "exec/memory.h"
 #include "exec/address-spaces.h"
@@ -49,8 +50,8 @@ typedef struct OneNANDState {
     hwaddr base;
     qemu_irq intr;
     qemu_irq rdy;
-    BlockDriverState *bdrv;
-    BlockDriverState *bdrv_cur;
+    BlockBackend *blk;
+    BlockBackend *blk_cur;
     uint8_t *image;
     uint8_t *otp;
     uint8_t *current;
@@ -213,7 +214,7 @@ static void onenand_reset(OneNANDState *s, int cold)
     s->wpstatus = 0x0002;
     s->cycle = 0;
     s->otpmode = 0;
-    s->bdrv_cur = s->bdrv;
+    s->blk_cur = s->blk;
     s->current = s->image;
     s->secs_cur = s->secs;
 
@@ -221,7 +222,7 @@ static void onenand_reset(OneNANDState *s, int cold)
         /* Lock the whole flash */
         memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
 
-        if (s->bdrv_cur && bdrv_read(s->bdrv_cur, 0, s->boot[0], 8) < 0) {
+        if (s->blk_cur && blk_read(s->blk_cur, 0, s->boot[0], 8) < 0) {
             hw_error("%s: Loading the BootRAM failed.\n", __func__);
         }
     }
@@ -237,10 +238,11 @@ static void onenand_system_reset(DeviceState *dev)
 static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
                 void *dest)
 {
-    if (s->bdrv_cur)
-        return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0;
-    else if (sec + secn > s->secs_cur)
+    if (s->blk_cur) {
+        return blk_read(s->blk_cur, sec, dest, secn) < 0;
+    } else if (sec + secn > s->secs_cur) {
         return 1;
+    }
 
     memcpy(dest, s->current + (sec << 9), secn << 9);
 
@@ -256,9 +258,9 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
         uint32_t size = (uint32_t)secn * 512;
         const uint8_t *sp = (const uint8_t *)src;
         uint8_t *dp = 0;
-        if (s->bdrv_cur) {
+        if (s->blk_cur) {
             dp = g_malloc(size);
-            if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
+            if (!dp || blk_read(s->blk_cur, sec, dp, secn) < 0) {
                 result = 1;
             }
         } else {
@@ -273,11 +275,11 @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
             for (i = 0; i < size; i++) {
                 dp[i] &= sp[i];
             }
-            if (s->bdrv_cur) {
-                result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
+            if (s->blk_cur) {
+                result = blk_write(s->blk_cur, sec, dp, secn) < 0;
             }
         }
-        if (dp && s->bdrv_cur) {
+        if (dp && s->blk_cur) {
             g_free(dp);
         }
     }
@@ -290,14 +292,16 @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
 {
     uint8_t buf[512];
 
-    if (s->bdrv_cur) {
-        if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
+    if (s->blk_cur) {
+        if (blk_read(s->blk_cur, s->secs_cur + (sec >> 5), buf, 1) < 0) {
             return 1;
+        }
         memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
-    } else if (sec + secn > s->secs_cur)
+    } else if (sec + secn > s->secs_cur) {
         return 1;
-    else
+    } else {
         memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
+    }
  
     return 0;
 }
@@ -309,11 +313,10 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
     if (secn > 0) {
         const uint8_t *sp = (const uint8_t *)src;
         uint8_t *dp = 0, *dpp = 0;
-        if (s->bdrv_cur) {
+        if (s->blk_cur) {
             dp = g_malloc(512);
-            if (!dp || bdrv_read(s->bdrv_cur,
-                                 s->secs_cur + (sec >> 5),
-                                 dp, 1) < 0) {
+            if (!dp
+                || blk_read(s->blk_cur, s->secs_cur + (sec >> 5), dp, 1) < 0) {
                 result = 1;
             } else {
                 dpp = dp + ((sec & 31) << 4);
@@ -330,9 +333,9 @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
             for (i = 0; i < (secn << 4); i++) {
                 dpp[i] &= sp[i];
             }
-            if (s->bdrv_cur) {
-                result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
-                                    dp, 1) < 0;
+            if (s->blk_cur) {
+                result = blk_write(s->blk_cur, s->secs_cur + (sec >> 5),
+                                   dp, 1) < 0;
             }
         }
         g_free(dp);
@@ -354,16 +357,16 @@ static inline int onenand_erase(OneNANDState *s, int sec, int num)
     }
     memset(blankbuf, 0xff, 512);
     for (; num > 0; num--, sec++) {
-        if (s->bdrv_cur) {
+        if (s->blk_cur) {
             int erasesec = s->secs_cur + (sec >> 5);
-            if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1) < 0) {
+            if (blk_write(s->blk_cur, sec, blankbuf, 1) < 0) {
                 goto fail;
             }
-            if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+            if (blk_read(s->blk_cur, erasesec, tmpbuf, 1) < 0) {
                 goto fail;
             }
             memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
-            if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
+            if (blk_write(s->blk_cur, erasesec, tmpbuf, 1) < 0) {
                 goto fail;
             }
         } else {
@@ -576,7 +579,7 @@ static void onenand_command(OneNANDState *s)
 
     case 0x65:	/* OTP Access */
         s->intstatus |= ONEN_INT;
-        s->bdrv_cur = NULL;
+        s->blk_cur = NULL;
         s->current = s->otp;
         s->secs_cur = 1 << (BLOCK_SHIFT - 9);
         s->addr[ONEN_BUF_BLOCK] = 0;
@@ -776,15 +779,15 @@ static int onenand_initfn(SysBusDevice *sbd)
         ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0;
     memory_region_init_io(&s->iomem, OBJECT(s), &onenand_ops, s, "onenand",
                           0x10000 << s->shift);
-    if (!s->bdrv) {
+    if (!s->blk) {
         s->image = memset(g_malloc(size + (size >> 5)),
                           0xff, size + (size >> 5));
     } else {
-        if (bdrv_is_read_only(s->bdrv)) {
+        if (blk_is_read_only(s->blk)) {
             error_report("Can't use a read-only drive");
             return -1;
         }
-        s->bdrv_cur = s->bdrv;
+        s->blk_cur = s->blk;
     }
     s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
@@ -815,7 +818,7 @@ static Property onenand_properties[] = {
     DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
     DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
     DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
-    DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv),
+    DEFINE_PROP_DRIVE("drive", OneNANDState, blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 593fbc5..ab9fef9 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -38,7 +38,7 @@
 
 #include "hw/hw.h"
 #include "hw/block/flash.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "qemu/timer.h"
 #include "qemu/bitops.h"
 #include "exec/address-spaces.h"
@@ -69,7 +69,7 @@ struct pflash_t {
     SysBusDevice parent_obj;
     /*< public >*/
 
-    BlockDriverState *bs;
+    BlockBackend *blk;
     uint32_t nb_blocs;
     uint64_t sector_len;
     uint8_t bank_width;
@@ -395,13 +395,13 @@ static void pflash_update(pflash_t *pfl, int offset,
                           int size)
 {
     int offset_end;
-    if (pfl->bs) {
+    if (pfl->blk) {
         offset_end = offset + size;
         /* round to sectors */
         offset = offset >> 9;
         offset_end = (offset_end + 511) >> 9;
-        bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9),
-                   offset_end - offset);
+        blk_write(pfl->blk, offset, pfl->storage + (offset << 9),
+                  offset_end - offset);
     }
 }
 
@@ -778,9 +778,9 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
     pfl->storage = memory_region_get_ram_ptr(&pfl->mem);
     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
 
-    if (pfl->bs) {
+    if (pfl->blk) {
         /* read the initial flash content */
-        ret = bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
+        ret = blk_read(pfl->blk, 0, pfl->storage, total_len >> 9);
 
         if (ret < 0) {
             vmstate_unregister_ram(&pfl->mem, DEVICE(pfl));
@@ -789,8 +789,8 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
         }
     }
 
-    if (pfl->bs) {
-        pfl->ro = bdrv_is_read_only(pfl->bs);
+    if (pfl->blk) {
+        pfl->ro = blk_is_read_only(pfl->blk);
     } else {
         pfl->ro = 0;
     }
@@ -892,7 +892,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
 }
 
 static Property pflash_cfi01_properties[] = {
-    DEFINE_PROP_DRIVE("drive", struct pflash_t, bs),
+    DEFINE_PROP_DRIVE("drive", struct pflash_t, blk),
     /* num-blocks is the number of blocks actually visible to the guest,
      * ie the total size of the device divided by the sector length.
      * If we're emulating flash devices wired in parallel the actual
@@ -956,14 +956,14 @@ type_init(pflash_cfi01_register_types)
 pflash_t *pflash_cfi01_register(hwaddr base,
                                 DeviceState *qdev, const char *name,
                                 hwaddr size,
-                                BlockDriverState *bs,
+                                BlockBackend *blk,
                                 uint32_t sector_len, int nb_blocs,
                                 int bank_width, uint16_t id0, uint16_t id1,
                                 uint16_t id2, uint16_t id3, int be)
 {
     DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01);
 
-    if (bs && qdev_prop_set_drive(dev, "drive", bs)) {
+    if (blk && qdev_prop_set_drive(dev, "drive", blk)) {
         abort();
     }
     qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index e196f4d..d372c31 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -38,7 +38,7 @@
 #include "hw/hw.h"
 #include "hw/block/flash.h"
 #include "qemu/timer.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "exec/address-spaces.h"
 #include "qemu/host-utils.h"
 #include "hw/sysbus.h"
@@ -63,7 +63,7 @@ struct pflash_t {
     SysBusDevice parent_obj;
     /*< public >*/
 
-    BlockDriverState *bs;
+    BlockBackend *blk;
     uint32_t sector_len;
     uint32_t nb_blocs;
     uint32_t chip_len;
@@ -249,13 +249,13 @@ static void pflash_update(pflash_t *pfl, int offset,
                           int size)
 {
     int offset_end;
-    if (pfl->bs) {
+    if (pfl->blk) {
         offset_end = offset + size;
         /* round to sectors */
         offset = offset >> 9;
         offset_end = (offset_end + 511) >> 9;
-        bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9),
-                   offset_end - offset);
+        blk_write(pfl->blk, offset, pfl->storage + (offset << 9),
+                  offset_end - offset);
     }
 }
 
@@ -612,9 +612,9 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
     vmstate_register_ram(&pfl->orig_mem, DEVICE(pfl));
     pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem);
     pfl->chip_len = chip_len;
-    if (pfl->bs) {
+    if (pfl->blk) {
         /* read the initial flash content */
-        ret = bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
+        ret = blk_read(pfl->blk, 0, pfl->storage, chip_len >> 9);
         if (ret < 0) {
             vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl));
             error_setg(errp, "failed to read the initial flash content");
@@ -626,8 +626,8 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
     pfl->rom_mode = 1;
     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem);
 
-    if (pfl->bs) {
-        pfl->ro = bdrv_is_read_only(pfl->bs);
+    if (pfl->blk) {
+        pfl->ro = blk_is_read_only(pfl->blk);
     } else {
         pfl->ro = 0;
     }
@@ -716,7 +716,7 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp)
 }
 
 static Property pflash_cfi02_properties[] = {
-    DEFINE_PROP_DRIVE("drive", struct pflash_t, bs),
+    DEFINE_PROP_DRIVE("drive", struct pflash_t, blk),
     DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
     DEFINE_PROP_UINT32("sector-length", struct pflash_t, sector_len, 0),
     DEFINE_PROP_UINT8("width", struct pflash_t, width, 0),
@@ -757,7 +757,7 @@ type_init(pflash_cfi02_register_types)
 pflash_t *pflash_cfi02_register(hwaddr base,
                                 DeviceState *qdev, const char *name,
                                 hwaddr size,
-                                BlockDriverState *bs, uint32_t sector_len,
+                                BlockBackend *blk, uint32_t sector_len,
                                 int nb_blocs, int nb_mappings, int width,
                                 uint16_t id0, uint16_t id1,
                                 uint16_t id2, uint16_t id3,
@@ -766,7 +766,7 @@ pflash_t *pflash_cfi02_register(hwaddr base,
 {
     DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH02);
 
-    if (bs && qdev_prop_set_drive(dev, "drive", bs)) {
+    if (blk && qdev_prop_set_drive(dev, "drive", blk)) {
         abort();
     }
     qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 347f372..a22b3d4 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -16,6 +16,7 @@
 #include "qemu/error-report.h"
 #include "trace.h"
 #include "hw/block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/virtio/virtio-blk.h"
 #ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
@@ -66,7 +67,8 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
 static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
     bool is_read)
 {
-    BlockErrorAction action = bdrv_get_error_action(req->dev->bs, is_read, error);
+    BlockErrorAction action = blk_get_error_action(req->dev->blk,
+                                                   is_read, error);
     VirtIOBlock *s = req->dev;
 
     if (action == BLOCK_ERROR_ACTION_STOP) {
@@ -74,11 +76,11 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
         s->rq = req;
     } else if (action == BLOCK_ERROR_ACTION_REPORT) {
         virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
-        bdrv_acct_done(s->bs, &req->acct);
+        blk_acct_done(s->blk, &req->acct);
         virtio_blk_free_request(req);
     }
 
-    bdrv_error_action(s->bs, action, is_read, error);
+    blk_error_action(s->blk, action, is_read, error);
     return action != BLOCK_ERROR_ACTION_IGNORE;
 }
 
@@ -96,7 +98,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
     }
 
     virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
-    bdrv_acct_done(req->dev->bs, &req->acct);
+    blk_acct_done(req->dev->blk, &req->acct);
     virtio_blk_free_request(req);
 }
 
@@ -111,7 +113,7 @@ static void virtio_blk_flush_complete(void *opaque, int ret)
     }
 
     virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
-    bdrv_acct_done(req->dev->bs, &req->acct);
+    blk_acct_done(req->dev->blk, &req->acct);
     virtio_blk_free_request(req);
 }
 
@@ -211,7 +213,7 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
     hdr.sbp = elem->in_sg[elem->in_num - 3].iov_base;
     hdr.mx_sb_len = elem->in_sg[elem->in_num - 3].iov_len;
 
-    status = bdrv_ioctl(blk->bs, SG_IO, &hdr);
+    status = blk_ioctl(blk->blk, SG_IO, &hdr);
     if (status) {
         status = VIRTIO_BLK_S_UNSUPP;
         goto fail;
@@ -257,7 +259,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
     virtio_blk_free_request(req);
 }
 
-void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
+void virtio_submit_multiwrite(BlockBackend *blk, MultiReqBuffer *mrb)
 {
     int i, ret;
 
@@ -265,7 +267,7 @@ void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
         return;
     }
 
-    ret = bdrv_aio_multiwrite(bs, mrb->blkreq, mrb->num_writes);
+    ret = blk_aio_multiwrite(blk, mrb->blkreq, mrb->num_writes);
     if (ret != 0) {
         for (i = 0; i < mrb->num_writes; i++) {
             if (mrb->blkreq[i].error) {
@@ -279,13 +281,13 @@ void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
 
 static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
 {
-    bdrv_acct_start(req->dev->bs, &req->acct, 0, BDRV_ACCT_FLUSH);
+    blk_acct_start(req->dev->blk, &req->acct, 0, BDRV_ACCT_FLUSH);
 
     /*
      * Make sure all outstanding writes are posted to the backing device.
      */
-    virtio_submit_multiwrite(req->dev->bs, mrb);
-    bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
+    virtio_submit_multiwrite(req->dev->blk, mrb);
+    blk_aio_flush(req->dev->blk, virtio_blk_flush_complete, req);
 }
 
 static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
@@ -300,7 +302,7 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
     if (size % dev->conf.conf.logical_block_size) {
         return false;
     }
-    bdrv_get_geometry(dev->bs, &total_sectors);
+    blk_get_geometry(dev->blk, &total_sectors);
     if (sector > total_sectors || nb_sectors > total_sectors - sector) {
         return false;
     }
@@ -322,10 +324,10 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
         return;
     }
 
-    bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
+    blk_acct_start(req->dev->blk, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);
 
     if (mrb->num_writes == 32) {
-        virtio_submit_multiwrite(req->dev->bs, mrb);
+        virtio_submit_multiwrite(req->dev->blk, mrb);
     }
 
     blkreq = &mrb->blkreq[mrb->num_writes];
@@ -353,10 +355,10 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
         return;
     }
 
-    bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);
-    bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
-                   req->qiov.size / BDRV_SECTOR_SIZE,
-                   virtio_blk_rw_complete, req);
+    blk_acct_start(req->dev->blk, &req->acct, req->qiov.size, BDRV_ACCT_READ);
+    blk_aio_readv(req->dev->blk, sector, &req->qiov,
+                  req->qiov.size / BDRV_SECTOR_SIZE,
+                  virtio_blk_rw_complete, req);
 }
 
 void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
@@ -446,7 +448,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
         virtio_blk_handle_request(req, &mrb);
     }
 
-    virtio_submit_multiwrite(s->bs, &mrb);
+    virtio_submit_multiwrite(s->blk, &mrb);
 
     /*
      * FIXME: Want to check for completions before returning to guest mode,
@@ -474,7 +476,7 @@ static void virtio_blk_dma_restart_bh(void *opaque)
         req = next;
     }
 
-    virtio_submit_multiwrite(s->bs, &mrb);
+    virtio_submit_multiwrite(s->blk, &mrb);
 }
 
 static void virtio_blk_dma_restart_cb(void *opaque, int running,
@@ -487,7 +489,7 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running,
     }
 
     if (!s->bh) {
-        s->bh = aio_bh_new(bdrv_get_aio_context(s->conf.conf.bs),
+        s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk),
                            virtio_blk_dma_restart_bh, s);
         qemu_bh_schedule(s->bh);
     }
@@ -507,8 +509,8 @@ static void virtio_blk_reset(VirtIODevice *vdev)
      * This should cancel pending requests, but can't do nicely until there
      * are per-device request lists.
      */
-    bdrv_drain_all();
-    bdrv_set_enable_write_cache(s->bs, s->original_wce);
+    blk_drain_all();
+    blk_set_enable_write_cache(s->blk, s->original_wce);
 }
 
 /* coalesce internal state, copy to pci i/o region 0
@@ -521,7 +523,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
     uint64_t capacity;
     int blk_size = conf->logical_block_size;
 
-    bdrv_get_geometry(s->bs, &capacity);
+    blk_get_geometry(s->blk, &capacity);
     memset(&blkcfg, 0, sizeof(blkcfg));
     virtio_stq_p(vdev, &blkcfg.capacity, capacity);
     virtio_stl_p(vdev, &blkcfg.seg_max, 128 - 2);
@@ -541,7 +543,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
      * divided by 512 - instead it is the amount of blk_size blocks
      * per track (cylinder).
      */
-    if (bdrv_getlength(s->bs) /  conf->heads / conf->secs % blk_size) {
+    if (blk_getlength(s->blk) /  conf->heads / conf->secs % blk_size) {
         blkcfg.sectors = conf->secs & ~s->sector_mask;
     } else {
         blkcfg.sectors = conf->secs;
@@ -549,7 +551,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
     blkcfg.size_max = 0;
     blkcfg.physical_block_exp = get_physical_block_exp(&s->conf.conf);
     blkcfg.alignment_offset = 0;
-    blkcfg.wce = bdrv_enable_write_cache(s->bs);
+    blkcfg.wce = blk_enable_write_cache(s->blk);
     memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
 }
 
@@ -560,9 +562,9 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
 
     memcpy(&blkcfg, config, sizeof(blkcfg));
 
-    aio_context_acquire(bdrv_get_aio_context(s->bs));
-    bdrv_set_enable_write_cache(s->bs, blkcfg.wce != 0);
-    aio_context_release(bdrv_get_aio_context(s->bs));
+    aio_context_acquire(blk_get_aio_context(s->blk));
+    blk_set_enable_write_cache(s->blk, blkcfg.wce != 0);
+    aio_context_release(blk_get_aio_context(s->blk));
 }
 
 static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
@@ -578,11 +580,12 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
     if (s->conf.config_wce) {
         features |= (1 << VIRTIO_BLK_F_CONFIG_WCE);
     }
-    if (bdrv_enable_write_cache(s->bs))
+    if (blk_enable_write_cache(s->blk)) {
         features |= (1 << VIRTIO_BLK_F_WCE);
-
-    if (bdrv_is_read_only(s->bs))
+    }
+    if (blk_is_read_only(s->blk)) {
         features |= 1 << VIRTIO_BLK_F_RO;
+    }
 
     return features;
 }
@@ -618,13 +621,13 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
      *     Guest writes 1 to the WCE configuration field (writeback mode)
      *     Guest sets DRIVER_OK bit in status field
      *
-     * s->bs would erroneously be placed in writethrough mode.
+     * s->blk would erroneously be placed in writethrough mode.
      */
     if (!(features & (1 << VIRTIO_BLK_F_CONFIG_WCE))) {
-        aio_context_acquire(bdrv_get_aio_context(s->bs));
-        bdrv_set_enable_write_cache(s->bs,
-                                    !!(features & (1 << VIRTIO_BLK_F_WCE)));
-        aio_context_release(bdrv_get_aio_context(s->bs));
+        aio_context_acquire(blk_get_aio_context(s->blk));
+        blk_set_enable_write_cache(s->blk,
+                                   !!(features & (1 << VIRTIO_BLK_F_WCE)));
+        aio_context_release(blk_get_aio_context(s->blk));
     }
 }
 
@@ -714,7 +717,7 @@ static void virtio_blk_migration_state_changed(Notifier *notifier, void *data)
         if (s->dataplane) {
             return;
         }
-        bdrv_drain_all(); /* complete in-flight non-dataplane requests */
+        blk_drain_all(); /* complete in-flight non-dataplane requests */
         virtio_blk_data_plane_create(VIRTIO_DEVICE(s), &s->conf,
                                      &s->dataplane, &err);
         if (err != NULL) {
@@ -733,17 +736,17 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
     Error *err = NULL;
     static int virtio_blk_id;
 
-    if (!conf->conf.bs) {
+    if (!conf->conf.blk) {
         error_setg(errp, "drive property not set");
         return;
     }
-    if (!bdrv_is_inserted(conf->conf.bs)) {
+    if (!blk_is_inserted(conf->conf.blk)) {
         error_setg(errp, "Device needs media, but drive is empty");
         return;
     }
 
     blkconf_serial(&conf->conf, &conf->serial);
-    s->original_wce = bdrv_enable_write_cache(conf->conf.bs);
+    s->original_wce = blk_enable_write_cache(conf->conf.blk);
     blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, &err);
     if (err) {
         error_propagate(errp, err);
@@ -753,7 +756,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
     virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
                 sizeof(struct virtio_blk_config));
 
-    s->bs = conf->conf.bs;
+    s->blk = conf->conf.blk;
     s->rq = NULL;
     s->sector_mask = (s->conf.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1;
 
@@ -773,10 +776,10 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
     s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
     register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                     virtio_blk_save, virtio_blk_load, s);
-    bdrv_set_dev_ops(s->bs, &virtio_block_ops, s);
-    bdrv_set_guest_block_size(s->bs, s->conf.conf.logical_block_size);
+    blk_set_dev_ops(s->blk, &virtio_block_ops, s);
+    blk_set_guest_block_size(s->blk, s->conf.conf.logical_block_size);
 
-    bdrv_iostatus_enable(s->bs);
+    blk_iostatus_enable(s->blk);
 
     add_boot_device_path(s->conf.conf.bootindex, dev, "/disk@0,0");
 }
@@ -793,7 +796,7 @@ static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
 #endif
     qemu_del_vm_change_state_handler(s->change);
     unregister_savevm(dev, "virtio-blk", s);
-    blockdev_mark_auto_del(s->bs);
+    blockdev_mark_auto_del(s->blk);
     virtio_cleanup(vdev);
 }
 
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index b571bbe..ad9a1fc 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -123,7 +123,7 @@ struct XenBlkDev {
 
     /* qemu block driver */
     DriveInfo           *dinfo;
-    BlockDriverState    *bs;
+    BlockBackend        *blk;
     QEMUBH              *bh;
 };
 
@@ -480,7 +480,7 @@ static void qemu_aio_complete(void *opaque, int ret)
     if (ioreq->postsync) {
         ioreq->postsync = 0;
         ioreq->aio_inflight++;
-        bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq);
+        blk_aio_flush(ioreq->blkdev->blk, qemu_aio_complete, ioreq);
         return;
     }
 
@@ -494,7 +494,7 @@ static void qemu_aio_complete(void *opaque, int ret)
             break;
         }
     case BLKIF_OP_READ:
-        bdrv_acct_done(ioreq->blkdev->bs, &ioreq->acct);
+        blk_acct_done(ioreq->blkdev->blk, &ioreq->acct);
         break;
     case BLKIF_OP_DISCARD:
     default:
@@ -513,35 +513,37 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
 
     ioreq->aio_inflight++;
     if (ioreq->presync) {
-        bdrv_aio_flush(ioreq->blkdev->bs, qemu_aio_complete, ioreq);
+        blk_aio_flush(ioreq->blkdev->blk, qemu_aio_complete, ioreq);
         return 0;
     }
 
     switch (ioreq->req.operation) {
     case BLKIF_OP_READ:
-        bdrv_acct_start(blkdev->bs, &ioreq->acct, ioreq->v.size, BDRV_ACCT_READ);
+        blk_acct_start(blkdev->blk, &ioreq->acct, ioreq->v.size,
+                       BDRV_ACCT_READ);
         ioreq->aio_inflight++;
-        bdrv_aio_readv(blkdev->bs, ioreq->start / BLOCK_SIZE,
+        blk_aio_readv(blkdev->blk, ioreq->start / BLOCK_SIZE,
+                      &ioreq->v, ioreq->v.size / BLOCK_SIZE,
+                      qemu_aio_complete, ioreq);
+        break;
+    case BLKIF_OP_WRITE:
+    case BLKIF_OP_FLUSH_DISKCACHE:
+        if (!ioreq->req.nr_segments) {
+            break;
+        }
+
+        blk_acct_start(blkdev->blk, &ioreq->acct, ioreq->v.size,
+                       BDRV_ACCT_WRITE);
+        ioreq->aio_inflight++;
+        blk_aio_writev(blkdev->blk, ioreq->start / BLOCK_SIZE,
                        &ioreq->v, ioreq->v.size / BLOCK_SIZE,
                        qemu_aio_complete, ioreq);
         break;
-    case BLKIF_OP_WRITE:
-    case BLKIF_OP_FLUSH_DISKCACHE:
-        if (!ioreq->req.nr_segments) {
-            break;
-        }
-
-        bdrv_acct_start(blkdev->bs, &ioreq->acct, ioreq->v.size, BDRV_ACCT_WRITE);
-        ioreq->aio_inflight++;
-        bdrv_aio_writev(blkdev->bs, ioreq->start / BLOCK_SIZE,
-                        &ioreq->v, ioreq->v.size / BLOCK_SIZE,
-                        qemu_aio_complete, ioreq);
-        break;
     case BLKIF_OP_DISCARD:
     {
         struct blkif_request_discard *discard_req = (void *)&ioreq->req;
         ioreq->aio_inflight++;
-        bdrv_aio_discard(blkdev->bs,
+        blk_aio_discard(blkdev->blk,
                         discard_req->sector_number, discard_req->nr_sectors,
                         qemu_aio_complete, ioreq);
         break;
@@ -855,6 +857,7 @@ static int blk_connect(struct XenDevice *xendev)
         Error *local_err = NULL;
         BlockBackend *blk;
         BlockDriver *drv;
+        BlockDriverState *bs;
 
         /* setup via xenbus -> create new block driver instance */
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
@@ -862,39 +865,39 @@ static int blk_connect(struct XenDevice *xendev)
         if (!blk) {
             return -1;
         }
-        blkdev->bs = blk_bs(blk);
+        blkdev->blk = blk;
 
+        bs = blk_bs(blk);
         drv = bdrv_find_whitelisted_format(blkdev->fileproto, readonly);
-        if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
+        if (bdrv_open(&bs, blkdev->filename, NULL, NULL, qflags,
                       drv, &local_err) != 0) {
             xen_be_printf(&blkdev->xendev, 0, "error: %s\n",
                           error_get_pretty(local_err));
             error_free(local_err);
             blk_unref(blk);
-            blkdev->bs = NULL;
+            blkdev->blk = NULL;
             return -1;
         }
+        assert(bs == blk_bs(blk));
     } else {
         /* setup via qemu cmdline -> already setup for us */
         xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n");
-        blkdev->bs = blk_bs(blk_by_legacy_dinfo(blkdev->dinfo));
-        if (bdrv_is_read_only(blkdev->bs) && !readonly) {
+        blkdev->blk = blk_by_legacy_dinfo(blkdev->dinfo);
+        if (blk_is_read_only(blkdev->blk) && !readonly) {
             xen_be_printf(&blkdev->xendev, 0, "Unexpected read-only drive");
-            blkdev->bs = NULL;
+            blkdev->blk = NULL;
             return -1;
         }
-        /* blkdev->bs is not create by us, we get a reference
-         * so we can bdrv_unref() unconditionally */
-        /* Except we don't bdrv_unref() anymore, we blk_unref().
-         * Conditionally, because we can't easily blk_ref() here.
-         * TODO Clean this up! */
+        /* blkdev->blk is not create by us, we get a reference
+         * so we can blk_unref() unconditionally */
+        blk_ref(blkdev->blk);
     }
-    bdrv_attach_dev_nofail(blkdev->bs, blkdev);
-    blkdev->file_size = bdrv_getlength(blkdev->bs);
+    blk_attach_dev_nofail(blkdev->blk, blkdev);
+    blkdev->file_size = blk_getlength(blkdev->blk);
     if (blkdev->file_size < 0) {
-        xen_be_printf(&blkdev->xendev, 1, "bdrv_getlength: %d (%s) | drv %s\n",
+        xen_be_printf(&blkdev->xendev, 1, "blk_getlength: %d (%s) | drv %s\n",
                       (int)blkdev->file_size, strerror(-blkdev->file_size),
-                      bdrv_get_format_name(blkdev->bs) ?: "-");
+                      bdrv_get_format_name(blk_bs(blkdev->blk)) ?: "-");
         blkdev->file_size = 0;
     }
 
@@ -985,12 +988,10 @@ static void blk_disconnect(struct XenDevice *xendev)
 {
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
 
-    if (blkdev->bs) {
-        bdrv_detach_dev(blkdev->bs, blkdev);
-        if (!blkdev->dinfo) {
-            blk_unref(blk_by_name(blkdev->dev));
-        }
-        blkdev->bs = NULL;
+    if (blkdev->blk) {
+        blk_detach_dev(blkdev->blk, blkdev);
+        blk_unref(blkdev->blk);
+        blkdev->blk = NULL;
     }
     xen_be_unbind_evtchn(&blkdev->xendev);
 
@@ -1006,7 +1007,7 @@ static int blk_free(struct XenDevice *xendev)
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
     struct ioreq *ioreq;
 
-    if (blkdev->bs || blkdev->sring) {
+    if (blkdev->blk || blkdev->sring) {
         blk_disconnect(xendev);
     }
 
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index ae0900f..f77b22a 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -13,6 +13,7 @@
 #include "net/net.h"
 #include "hw/qdev.h"
 #include "qapi/qmp/qerror.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/block/block.h"
 #include "net/hub.h"
@@ -68,16 +69,16 @@ static void set_pointer(Object *obj, Visitor *v, Property *prop,
 
 static int parse_drive(DeviceState *dev, const char *str, void **ptr)
 {
-    BlockDriverState *bs;
+    BlockBackend *blk;
 
-    bs = bdrv_find(str);
-    if (bs == NULL) {
+    blk = blk_by_name(str);
+    if (!blk) {
         return -ENOENT;
     }
-    if (bdrv_attach_dev(bs, dev) < 0) {
+    if (blk_attach_dev(blk, dev) < 0) {
         return -EEXIST;
     }
-    *ptr = bs;
+    *ptr = blk;
     return 0;
 }
 
@@ -85,17 +86,17 @@ static void release_drive(Object *obj, const char *name, void *opaque)
 {
     DeviceState *dev = DEVICE(obj);
     Property *prop = opaque;
-    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
+    BlockBackend **ptr = qdev_get_prop_ptr(dev, prop);
 
     if (*ptr) {
-        bdrv_detach_dev(*ptr, dev);
+        blk_detach_dev(*ptr, dev);
         blockdev_auto_del(*ptr);
     }
 }
 
 static char *print_drive(void *ptr)
 {
-    return g_strdup(bdrv_get_device_name(ptr));
+    return g_strdup(blk_name(ptr));
 }
 
 static void get_drive(Object *obj, Visitor *v, void *opaque,
@@ -335,12 +336,11 @@ PropertyInfo qdev_prop_vlan = {
 };
 
 int qdev_prop_set_drive(DeviceState *dev, const char *name,
-                        BlockDriverState *value)
+                        BlockBackend *value)
 {
     Error *err = NULL;
-    const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
-    object_property_set_str(OBJECT(dev), bdrv_name,
-                            name, &err);
+    object_property_set_str(OBJECT(dev),
+                            value ? blk_name(value) : "", name, &err);
     if (err) {
         qerror_report_err(err);
         error_free(err);
@@ -350,7 +350,7 @@ int qdev_prop_set_drive(DeviceState *dev, const char *name,
 }
 
 void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name,
-                                BlockDriverState *value)
+                                BlockBackend *value)
 {
     if (qdev_prop_set_drive(dev, name, value) < 0) {
         exit(1);
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 3d12560..931a48c 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -1,7 +1,7 @@
 #include "net/net.h"
 #include "hw/qdev.h"
 #include "qapi/qmp/qerror.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "hw/block/block.h"
 #include "net/hub.h"
 #include "qapi/visitor.h"
diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c
index 280722d..f43de34 100644
--- a/hw/cris/axis_dev88.c
+++ b/hw/cris/axis_dev88.c
@@ -31,7 +31,6 @@
 #include "elf.h"
 #include "boot.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "sysemu/qtest.h"
 
@@ -283,7 +282,7 @@ void axisdev88_init(MachineState *machine)
 
       /* Attach a NAND flash to CS1.  */
     nand = drive_get(IF_MTD, 0, 0);
-    nand_state.nand = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,
+    nand_state.nand = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL,
                                 NAND_MFR_STMICRO, 0x39);
     memory_region_init_io(&nand_state.iomem, NULL, &nand_ops, &nand_state,
                           "nand", 0x05000000);
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
index 62d6663..b89415a 100644
--- a/hw/display/tc6393xb.c
+++ b/hw/display/tc6393xb.c
@@ -577,7 +577,7 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
     s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);
 
     nand = drive_get(IF_MTD, 0, 0);
-    s->flash = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,
+    s->flash = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL,
                          NAND_MFR_TOSHIBA, 0x76);
 
     memory_region_init_io(&s->iomem, NULL, &tc6393xb_ops, s, "tc6393xb", 0x10000);
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index b6c9b61..aadf4bc 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -44,7 +44,7 @@
 #include "sysemu/kvm.h"
 #include "kvm_i386.h"
 #include "hw/xen/xen.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "hw/block/block.h"
 #include "ui/qemu-spice.h"
 #include "exec/memory.h"
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 103d756..000b34a 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -41,7 +41,7 @@
 #include "hw/sysbus.h"
 #include "hw/cpu/icc_bus.h"
 #include "sysemu/arch_init.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "hw/i2c/smbus.h"
 #include "hw/xen/xen.h"
 #include "exec/memory.h"
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 6cd264a..efe256c 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -24,7 +24,6 @@
  */
 
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "qemu/error-report.h"
 #include "hw/sysbus.h"
 #include "hw/hw.h"
@@ -103,7 +102,7 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
 {
     int unit;
     DriveInfo *pflash_drv;
-    BlockDriverState *bdrv;
+    BlockBackend *blk;
     int64_t size;
     char *fatal_errmsg = NULL;
     hwaddr phys_addr = 0x100000000ULL;
@@ -119,8 +118,8 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
          (unit < FLASH_MAP_UNIT_MAX &&
           (pflash_drv = drive_get(IF_PFLASH, 0, unit)) != NULL);
          ++unit) {
-        bdrv = blk_bs(blk_by_legacy_dinfo(pflash_drv));
-        size = bdrv_getlength(bdrv);
+        blk = blk_by_legacy_dinfo(pflash_drv);
+        size = blk_getlength(blk);
         if (size < 0) {
             fatal_errmsg = g_strdup_printf("failed to get backing file size");
         } else if (size == 0) {
@@ -156,7 +155,7 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
         /* pflash_cfi01_register() creates a deep copy of the name */
         snprintf(name, sizeof name, "system.flash%d", unit);
         system_flash = pflash_cfi01_register(phys_addr, NULL /* qdev */, name,
-                                             size, bdrv, sector_size,
+                                             size, blk, sector_size,
                                              size >> sector_bits,
                                              1      /* width */,
                                              0x0000 /* id0 */,
diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c
index 8bb18b4..28b324a 100644
--- a/hw/i386/xen/xen_platform.c
+++ b/hw/i386/xen/xen_platform.c
@@ -34,6 +34,7 @@
 #include "hw/xen/xen_backend.h"
 #include "trace.h"
 #include "exec/address-spaces.h"
+#include "sysemu/block-backend.h"
 
 #include <xenguest.h>
 
@@ -132,8 +133,8 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
            devices, and bit 2 the non-primary-master IDE devices. */
         if (val & UNPLUG_ALL_IDE_DISKS) {
             DPRINTF("unplug disks\n");
-            bdrv_drain_all();
-            bdrv_flush_all();
+            blk_drain_all();
+            blk_flush_all();
             pci_unplug_disks(pci_dev->bus);
         }
         if (val & UNPLUG_ALL_NICS) {
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 97c997c..2ca8dfe 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -28,6 +28,7 @@
 #include <hw/sysbus.h>
 
 #include "monitor/monitor.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/dma.h"
 #include "internal.h"
 #include <hw/ide/pci.h>
@@ -85,7 +86,7 @@ static uint32_t  ahci_port_read(AHCIState *s, int port, int offset)
         val = pr->sig;
         break;
     case PORT_SCR_STAT:
-        if (s->dev[port].port.ifs[0].bs) {
+        if (s->dev[port].port.ifs[0].blk) {
             val = SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP |
                   SATA_SCR_SSTATUS_SPD_GEN1 | SATA_SCR_SSTATUS_IPM_ACTIVE;
         } else {
@@ -501,7 +502,7 @@ static void ahci_reset_port(AHCIState *s, int port)
     d->init_d2h_sent = false;
 
     ide_state = &s->dev[port].port.ifs[0];
-    if (!ide_state->bs) {
+    if (!ide_state->blk) {
         return;
     }
 
@@ -513,11 +514,11 @@ static void ahci_reset_port(AHCIState *s, int port)
         }
 
         if (ncq_tfs->aiocb) {
-            bdrv_aio_cancel(ncq_tfs->aiocb);
+            blk_aio_cancel(ncq_tfs->aiocb);
             ncq_tfs->aiocb = NULL;
         }
 
-        /* Maybe we just finished the request thanks to bdrv_aio_cancel() */
+        /* Maybe we just finished the request thanks to blk_aio_cancel() */
         if (!ncq_tfs->used) {
             continue;
         }
@@ -527,7 +528,7 @@ static void ahci_reset_port(AHCIState *s, int port)
     }
 
     s->dev[port].port_state = STATE_RUN;
-    if (!ide_state->bs) {
+    if (!ide_state->blk) {
         s->dev[port].port_regs.sig = 0;
         ide_state->status = SEEK_STAT | WRERR_STAT;
     } else if (ide_state->drive_kind == IDE_CD) {
@@ -809,7 +810,7 @@ static void ncq_cb(void *opaque, int ret)
     DPRINTF(ncq_tfs->drive->port_no, "NCQ transfer tag %d finished\n",
             ncq_tfs->tag);
 
-    bdrv_acct_done(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct);
+    blk_acct_done(ncq_tfs->drive->port.ifs[0].blk, &ncq_tfs->acct);
     qemu_sglist_destroy(&ncq_tfs->sglist);
     ncq_tfs->used = 0;
 }
@@ -859,11 +860,11 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
             DPRINTF(port, "tag %d aio read %"PRId64"\n",
                     ncq_tfs->tag, ncq_tfs->lba);
 
-            dma_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
+            dma_acct_start(ncq_tfs->drive->port.ifs[0].blk, &ncq_tfs->acct,
                            &ncq_tfs->sglist, BDRV_ACCT_READ);
-            ncq_tfs->aiocb = dma_bdrv_read(ncq_tfs->drive->port.ifs[0].bs,
-                                           &ncq_tfs->sglist, ncq_tfs->lba,
-                                           ncq_cb, ncq_tfs);
+            ncq_tfs->aiocb = dma_blk_read(ncq_tfs->drive->port.ifs[0].blk,
+                                          &ncq_tfs->sglist, ncq_tfs->lba,
+                                          ncq_cb, ncq_tfs);
             break;
         case WRITE_FPDMA_QUEUED:
             DPRINTF(port, "NCQ writing %d sectors to LBA %"PRId64", tag %d\n",
@@ -872,11 +873,11 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis,
             DPRINTF(port, "tag %d aio write %"PRId64"\n",
                     ncq_tfs->tag, ncq_tfs->lba);
 
-            dma_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct,
+            dma_acct_start(ncq_tfs->drive->port.ifs[0].blk, &ncq_tfs->acct,
                            &ncq_tfs->sglist, BDRV_ACCT_WRITE);
-            ncq_tfs->aiocb = dma_bdrv_write(ncq_tfs->drive->port.ifs[0].bs,
-                                            &ncq_tfs->sglist, ncq_tfs->lba,
-                                            ncq_cb, ncq_tfs);
+            ncq_tfs->aiocb = dma_blk_write(ncq_tfs->drive->port.ifs[0].blk,
+                                           &ncq_tfs->sglist, ncq_tfs->lba,
+                                           ncq_cb, ncq_tfs);
             break;
         default:
             DPRINTF(port, "error: tried to process non-NCQ command as NCQ\n");
@@ -925,7 +926,7 @@ static int handle_cmd(AHCIState *s, int port, int slot)
     /* The device we are working for */
     ide_state = &s->dev[port].port.ifs[0];
 
-    if (!ide_state->bs) {
+    if (!ide_state->blk) {
         DPRINTF(port, "error: guest accessed unused port");
         goto out;
     }
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 3d92b52..7364b9f 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -25,6 +25,7 @@
 
 #include "hw/ide/internal.h"
 #include "hw/scsi/scsi.h"
+#include "sysemu/block-backend.h"
 
 static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
 
@@ -110,14 +111,14 @@ static int cd_read_sector(IDEState *s, int lba, uint8_t *buf, int sector_size)
 
     switch(sector_size) {
     case 2048:
-        bdrv_acct_start(s->bs, &s->acct, 4 * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
-        ret = bdrv_read(s->bs, (int64_t)lba << 2, buf, 4);
-        bdrv_acct_done(s->bs, &s->acct);
+        blk_acct_start(s->blk, &s->acct, 4 * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
+        ret = blk_read(s->blk, (int64_t)lba << 2, buf, 4);
+        blk_acct_done(s->blk, &s->acct);
         break;
     case 2352:
-        bdrv_acct_start(s->bs, &s->acct, 4 * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
-        ret = bdrv_read(s->bs, (int64_t)lba << 2, buf + 16, 4);
-        bdrv_acct_done(s->bs, &s->acct);
+        blk_acct_start(s->blk, &s->acct, 4 * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
+        ret = blk_read(s->blk, (int64_t)lba << 2, buf + 16, 4);
+        blk_acct_done(s->blk, &s->acct);
         if (ret < 0)
             return ret;
         cd_data_to_raw(buf, lba);
@@ -253,7 +254,7 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
     s->io_buffer_index = 0;
 
     if (s->atapi_dma) {
-        bdrv_acct_start(s->bs, &s->acct, size, BDRV_ACCT_READ);
+        blk_acct_start(s->blk, &s->acct, size, BDRV_ACCT_READ);
         s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
         ide_start_dma(s, ide_atapi_cmd_read_dma_cb);
     } else {
@@ -348,13 +349,13 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
     s->bus->dma->iov.iov_len = n * 4 * 512;
     qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
 
-    s->bus->dma->aiocb = bdrv_aio_readv(s->bs, (int64_t)s->lba << 2,
+    s->bus->dma->aiocb = blk_aio_readv(s->blk, (int64_t)s->lba << 2,
                                        &s->bus->dma->qiov, n * 4,
                                        ide_atapi_cmd_read_dma_cb, s);
     return;
 
 eot:
-    bdrv_acct_done(s->bs, &s->acct);
+    blk_acct_done(s->blk, &s->acct);
     ide_set_inactive(s, false);
 }
 
@@ -369,7 +370,7 @@ static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
     s->io_buffer_size = 0;
     s->cd_sector_size = sector_size;
 
-    bdrv_acct_start(s->bs, &s->acct, s->packet_transfer_size, BDRV_ACCT_READ);
+    blk_acct_start(s->blk, &s->acct, s->packet_transfer_size, BDRV_ACCT_READ);
 
     /* XXX: check if BUSY_STAT should be set */
     s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
@@ -501,7 +502,7 @@ static unsigned int event_status_media(IDEState *s,
     media_status = 0;
     if (s->tray_open) {
         media_status = MS_TRAY_OPEN;
-    } else if (bdrv_is_inserted(s->bs)) {
+    } else if (blk_is_inserted(s->blk)) {
         media_status = MS_MEDIA_PRESENT;
     }
 
@@ -797,7 +798,7 @@ static void cmd_test_unit_ready(IDEState *s, uint8_t *buf)
 static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf)
 {
     s->tray_locked = buf[4] & 1;
-    bdrv_lock_medium(s->bs, buf[4] & 1);
+    blk_lock_medium(s->blk, buf[4] & 1);
     ide_atapi_cmd_ok(s);
 }
 
@@ -881,14 +882,14 @@ static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
 
     if (loej) {
         if (!start && !s->tray_open && s->tray_locked) {
-            sense = bdrv_is_inserted(s->bs)
+            sense = blk_is_inserted(s->blk)
                 ? NOT_READY : ILLEGAL_REQUEST;
             ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED);
             return;
         }
 
         if (s->tray_open != !start) {
-            bdrv_eject(s->bs, !start);
+            blk_eject(s->blk, !start);
             s->tray_open = !start;
         }
     }
@@ -1122,7 +1123,7 @@ void ide_atapi_cmd(IDEState *s)
      * states rely on this behavior.
      */
     if (!(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA) &&
-        !s->tray_open && bdrv_is_inserted(s->bs) && s->cdrom_changed) {
+        !s->tray_open && blk_is_inserted(s->blk) && s->cdrom_changed) {
 
         if (s->cdrom_changed == 1) {
             ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
@@ -1137,7 +1138,7 @@ void ide_atapi_cmd(IDEState *s)
 
     /* Report a Not Ready condition if appropriate for the command */
     if ((atapi_cmd_table[s->io_buffer[0]].flags & CHECK_READY) &&
-        (!media_present(s) || !bdrv_is_inserted(s->bs)))
+        (!media_present(s) || !blk_is_inserted(s->blk)))
     {
         ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
         return;
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 91048f2..c8b0322 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -26,7 +26,7 @@
 #include <hw/i386/pc.h>
 #include <hw/pci/pci.h>
 #include <hw/isa/isa.h>
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 36df217..fe12145 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -31,7 +31,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 #include "hw/block/block.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 
 #include <hw/ide/internal.h>
 
@@ -158,10 +158,11 @@ static void ide_identify(IDEState *s)
         put_le16(p + 84, (1 << 14) | 0);
     }
     /* 14 = NOP supported, 5=WCACHE enabled, 0=SMART feature set enabled */
-    if (bdrv_enable_write_cache(s->bs))
-         put_le16(p + 85, (1 << 14) | (1 << 5) | 1);
-    else
-         put_le16(p + 85, (1 << 14) | 1);
+    if (blk_enable_write_cache(s->blk)) {
+        put_le16(p + 85, (1 << 14) | (1 << 5) | 1);
+    } else {
+        put_le16(p + 85, (1 << 14) | 1);
+    }
     /* 13=flush_cache_ext,12=flush_cache,10=lba48 */
     put_le16(p + 86, (1 << 13) | (1 <<12) | (1 << 10));
     /* 14=set to 1, 8=has WWN, 1=SMART self test, 0=SMART error logging */
@@ -350,7 +351,7 @@ static void ide_set_signature(IDEState *s)
     if (s->drive_kind == IDE_CD) {
         s->lcyl = 0x14;
         s->hcyl = 0xeb;
-    } else if (s->bs) {
+    } else if (s->blk) {
         s->lcyl = 0;
         s->hcyl = 0;
     } else {
@@ -372,7 +373,7 @@ static void trim_aio_cancel(BlockAIOCB *acb)
 {
     TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
 
-    /* Exit the loop in case bdrv_aio_cancel calls ide_issue_trim_cb again.  */
+    /* Exit the loop in case blk_aio_cancel calls ide_issue_trim_cb again.  */
     iocb->j = iocb->qiov->niov - 1;
     iocb->i = (iocb->qiov->iov[iocb->j].iov_len / 8) - 1;
 
@@ -381,7 +382,7 @@ static void trim_aio_cancel(BlockAIOCB *acb)
     iocb->bh = NULL;
 
     if (iocb->aiocb) {
-        bdrv_aio_cancel(iocb->aiocb);
+        blk_aio_cancel(iocb->aiocb);
     }
     qemu_aio_release(iocb);
 }
@@ -440,13 +441,13 @@ static void ide_issue_trim_cb(void *opaque, int ret)
     }
 }
 
-BlockAIOCB *ide_issue_trim(BlockDriverState *bs,
+BlockAIOCB *ide_issue_trim(BlockBackend *blk,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockCompletionFunc *cb, void *opaque)
 {
     TrimAIOCB *iocb;
 
-    iocb = qemu_aio_get(&trim_aiocb_info, bs, cb, opaque);
+    iocb = blk_aio_get(&trim_aiocb_info, blk, cb, opaque);
     iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
     iocb->ret = 0;
     iocb->qiov = qiov;
@@ -553,7 +554,7 @@ static bool ide_sect_range_ok(IDEState *s,
 {
     uint64_t total_sectors;
 
-    bdrv_get_geometry(s->bs, &total_sectors);
+    blk_get_geometry(s->blk, &total_sectors);
     if (sector > total_sectors || nb_sectors > total_sectors - sector) {
         return false;
     }
@@ -568,7 +569,7 @@ static void ide_sector_read_cb(void *opaque, int ret)
     s->pio_aiocb = NULL;
     s->status &= ~BUSY_STAT;
 
-    bdrv_acct_done(s->bs, &s->acct);
+    blk_acct_done(s->blk, &s->acct);
     if (ret != 0) {
         if (ide_handle_rw_error(s, -ret, IDE_RETRY_PIO |
                                 IDE_RETRY_READ)) {
@@ -624,9 +625,9 @@ void ide_sector_read(IDEState *s)
     s->iov.iov_len  = n * BDRV_SECTOR_SIZE;
     qemu_iovec_init_external(&s->qiov, &s->iov, 1);
 
-    bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
-    s->pio_aiocb = bdrv_aio_readv(s->bs, sector_num, &s->qiov, n,
-                                  ide_sector_read_cb, s);
+    blk_acct_start(s->blk, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
+    s->pio_aiocb = blk_aio_readv(s->blk, sector_num, &s->qiov, n,
+                                 ide_sector_read_cb, s);
 }
 
 static void dma_buf_commit(IDEState *s)
@@ -653,7 +654,7 @@ void ide_dma_error(IDEState *s)
 static int ide_handle_rw_error(IDEState *s, int error, int op)
 {
     bool is_read = (op & IDE_RETRY_READ) != 0;
-    BlockErrorAction action = bdrv_get_error_action(s->bs, is_read, error);
+    BlockErrorAction action = blk_get_error_action(s->blk, is_read, error);
 
     if (action == BLOCK_ERROR_ACTION_STOP) {
         s->bus->dma->ops->set_unit(s->bus->dma, s->unit);
@@ -666,7 +667,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
             ide_rw_error(s);
         }
     }
-    bdrv_error_action(s->bs, action, is_read, error);
+    blk_error_action(s->blk, action, is_read, error);
     return action != BLOCK_ERROR_ACTION_IGNORE;
 }
 
@@ -739,24 +740,24 @@ void ide_dma_cb(void *opaque, int ret)
 
     switch (s->dma_cmd) {
     case IDE_DMA_READ:
-        s->bus->dma->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
+        s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, sector_num,
+                                          ide_dma_cb, s);
+        break;
+    case IDE_DMA_WRITE:
+        s->bus->dma->aiocb = dma_blk_write(s->blk, &s->sg, sector_num,
                                            ide_dma_cb, s);
         break;
-    case IDE_DMA_WRITE:
-        s->bus->dma->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
-                                            ide_dma_cb, s);
-        break;
     case IDE_DMA_TRIM:
-        s->bus->dma->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
-                                         ide_issue_trim, ide_dma_cb, s,
-                                         DMA_DIRECTION_TO_DEVICE);
+        s->bus->dma->aiocb = dma_blk_io(s->blk, &s->sg, sector_num,
+                                        ide_issue_trim, ide_dma_cb, s,
+                                        DMA_DIRECTION_TO_DEVICE);
         break;
     }
     return;
 
 eot:
     if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
-        bdrv_acct_done(s->bs, &s->acct);
+        blk_acct_done(s->blk, &s->acct);
     }
     ide_set_inactive(s, stay_active);
 }
@@ -770,12 +771,12 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
 
     switch (dma_cmd) {
     case IDE_DMA_READ:
-        bdrv_acct_start(s->bs, &s->acct, s->nsector * BDRV_SECTOR_SIZE,
-                        BDRV_ACCT_READ);
+        blk_acct_start(s->blk, &s->acct, s->nsector * BDRV_SECTOR_SIZE,
+                       BDRV_ACCT_READ);
         break;
     case IDE_DMA_WRITE:
-        bdrv_acct_start(s->bs, &s->acct, s->nsector * BDRV_SECTOR_SIZE,
-                        BDRV_ACCT_WRITE);
+        blk_acct_start(s->blk, &s->acct, s->nsector * BDRV_SECTOR_SIZE,
+                       BDRV_ACCT_WRITE);
         break;
     default:
         break;
@@ -802,7 +803,7 @@ static void ide_sector_write_cb(void *opaque, int ret)
     IDEState *s = opaque;
     int n;
 
-    bdrv_acct_done(s->bs, &s->acct);
+    blk_acct_done(s->blk, &s->acct);
 
     s->pio_aiocb = NULL;
     s->status &= ~BUSY_STAT;
@@ -869,9 +870,9 @@ void ide_sector_write(IDEState *s)
     s->iov.iov_len  = n * BDRV_SECTOR_SIZE;
     qemu_iovec_init_external(&s->qiov, &s->iov, 1);
 
-    bdrv_acct_start(s->bs, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
-    s->pio_aiocb = bdrv_aio_writev(s->bs, sector_num, &s->qiov, n,
-                                   ide_sector_write_cb, s);
+    blk_acct_start(s->blk, &s->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
+    s->pio_aiocb = blk_aio_writev(s->blk, sector_num, &s->qiov, n,
+                                  ide_sector_write_cb, s);
 }
 
 static void ide_flush_cb(void *opaque, int ret)
@@ -887,8 +888,8 @@ static void ide_flush_cb(void *opaque, int ret)
         }
     }
 
-    if (s->bs) {
-        bdrv_acct_done(s->bs, &s->acct);
+    if (s->blk) {
+        blk_acct_done(s->blk, &s->acct);
     }
     s->status = READY_STAT | SEEK_STAT;
     ide_cmd_done(s);
@@ -897,14 +898,14 @@ static void ide_flush_cb(void *opaque, int ret)
 
 void ide_flush_cache(IDEState *s)
 {
-    if (s->bs == NULL) {
+    if (s->blk == NULL) {
         ide_flush_cb(s, 0);
         return;
     }
 
     s->status |= BUSY_STAT;
-    bdrv_acct_start(s->bs, &s->acct, 0, BDRV_ACCT_FLUSH);
-    s->pio_aiocb = bdrv_aio_flush(s->bs, ide_flush_cb, s);
+    blk_acct_start(s->blk, &s->acct, 0, BDRV_ACCT_FLUSH);
+    s->pio_aiocb = blk_aio_flush(s->blk, ide_flush_cb, s);
 }
 
 static void ide_cfata_metadata_inquiry(IDEState *s)
@@ -967,7 +968,7 @@ static void ide_cd_change_cb(void *opaque, bool load)
     uint64_t nb_sectors;
 
     s->tray_open = !load;
-    bdrv_get_geometry(s->bs, &nb_sectors);
+    blk_get_geometry(s->blk, &nb_sectors);
     s->nb_sectors = nb_sectors;
 
     /*
@@ -1101,7 +1102,7 @@ static bool cmd_data_set_management(IDEState *s, uint8_t cmd)
 {
     switch (s->feature) {
     case DSM_TRIM:
-        if (s->bs) {
+        if (s->blk) {
             ide_sector_start_dma(s, IDE_DMA_TRIM);
             return false;
         }
@@ -1114,7 +1115,7 @@ static bool cmd_data_set_management(IDEState *s, uint8_t cmd)
 
 static bool cmd_identify(IDEState *s, uint8_t cmd)
 {
-    if (s->bs && s->drive_kind != IDE_CD) {
+    if (s->blk && s->drive_kind != IDE_CD) {
         if (s->drive_kind != IDE_CFATA) {
             ide_identify(s);
         } else {
@@ -1164,7 +1165,7 @@ static bool cmd_read_multiple(IDEState *s, uint8_t cmd)
 {
     bool lba48 = (cmd == WIN_MULTREAD_EXT);
 
-    if (!s->bs || !s->mult_sectors) {
+    if (!s->blk || !s->mult_sectors) {
         ide_abort_command(s);
         return true;
     }
@@ -1180,7 +1181,7 @@ static bool cmd_write_multiple(IDEState *s, uint8_t cmd)
     bool lba48 = (cmd == WIN_MULTWRITE_EXT);
     int n;
 
-    if (!s->bs || !s->mult_sectors) {
+    if (!s->blk || !s->mult_sectors) {
         ide_abort_command(s);
         return true;
     }
@@ -1208,7 +1209,7 @@ static bool cmd_read_pio(IDEState *s, uint8_t cmd)
         return true;
     }
 
-    if (!s->bs) {
+    if (!s->blk) {
         ide_abort_command(s);
         return true;
     }
@@ -1224,7 +1225,7 @@ static bool cmd_write_pio(IDEState *s, uint8_t cmd)
 {
     bool lba48 = (cmd == WIN_WRITE_EXT);
 
-    if (!s->bs) {
+    if (!s->blk) {
         ide_abort_command(s);
         return true;
     }
@@ -1244,7 +1245,7 @@ static bool cmd_read_dma(IDEState *s, uint8_t cmd)
 {
     bool lba48 = (cmd == WIN_READDMA_EXT);
 
-    if (!s->bs) {
+    if (!s->blk) {
         ide_abort_command(s);
         return true;
     }
@@ -1259,7 +1260,7 @@ static bool cmd_write_dma(IDEState *s, uint8_t cmd)
 {
     bool lba48 = (cmd == WIN_WRITEDMA_EXT);
 
-    if (!s->bs) {
+    if (!s->blk) {
         ide_abort_command(s);
         return true;
     }
@@ -1310,7 +1311,7 @@ static bool cmd_set_features(IDEState *s, uint8_t cmd)
 {
     uint16_t *identify_data;
 
-    if (!s->bs) {
+    if (!s->blk) {
         ide_abort_command(s);
         return true;
     }
@@ -1318,12 +1319,12 @@ static bool cmd_set_features(IDEState *s, uint8_t cmd)
     /* XXX: valid for CDROM ? */
     switch (s->feature) {
     case 0x02: /* write cache enable */
-        bdrv_set_enable_write_cache(s->bs, true);
+        blk_set_enable_write_cache(s->blk, true);
         identify_data = (uint16_t *)s->identify_data;
         put_le16(identify_data + 85, (1 << 14) | (1 << 5) | 1);
         return true;
     case 0x82: /* write cache disable */
-        bdrv_set_enable_write_cache(s->bs, false);
+        blk_set_enable_write_cache(s->blk, false);
         identify_data = (uint16_t *)s->identify_data;
         put_le16(identify_data + 85, (1 << 14) | 1);
         ide_flush_cache(s);
@@ -1790,8 +1791,9 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val)
 #endif
     s = idebus_active_if(bus);
     /* ignore commands to non existent slave */
-    if (s != bus->ifs && !s->bs)
+    if (s != bus->ifs && !s->blk) {
         return;
+    }
 
     /* Only DEVICE RESET is allowed while BSY or/and DRQ are set */
     if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET)
@@ -1836,59 +1838,66 @@ uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
         ret = 0xff;
         break;
     case 1:
-        if ((!bus->ifs[0].bs && !bus->ifs[1].bs) ||
-            (s != bus->ifs && !s->bs))
+        if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
+            (s != bus->ifs && !s->blk)) {
             ret = 0;
-        else if (!hob)
+        } else if (!hob) {
             ret = s->error;
-	else
+        } else {
 	    ret = s->hob_feature;
+        }
         break;
     case 2:
-        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
+        if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
             ret = 0;
-        else if (!hob)
+        } else if (!hob) {
             ret = s->nsector & 0xff;
-	else
+        } else {
 	    ret = s->hob_nsector;
+        }
         break;
     case 3:
-        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
+        if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
             ret = 0;
-        else if (!hob)
+        } else if (!hob) {
             ret = s->sector;
-	else
+        } else {
 	    ret = s->hob_sector;
+        }
         break;
     case 4:
-        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
+        if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
             ret = 0;
-        else if (!hob)
+        } else if (!hob) {
             ret = s->lcyl;
-	else
+        } else {
 	    ret = s->hob_lcyl;
+        }
         break;
     case 5:
-        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
+        if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
             ret = 0;
-        else if (!hob)
+        } else if (!hob) {
             ret = s->hcyl;
-	else
+        } else {
 	    ret = s->hob_hcyl;
+        }
         break;
     case 6:
-        if (!bus->ifs[0].bs && !bus->ifs[1].bs)
+        if (!bus->ifs[0].blk && !bus->ifs[1].blk) {
             ret = 0;
-        else
+        } else {
             ret = s->select;
+        }
         break;
     default:
     case 7:
-        if ((!bus->ifs[0].bs && !bus->ifs[1].bs) ||
-            (s != bus->ifs && !s->bs))
+        if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
+            (s != bus->ifs && !s->blk)) {
             ret = 0;
-        else
+        } else {
             ret = s->status;
+        }
         qemu_irq_lower(bus->irq);
         break;
     }
@@ -1904,11 +1913,12 @@ uint32_t ide_status_read(void *opaque, uint32_t addr)
     IDEState *s = idebus_active_if(bus);
     int ret;
 
-    if ((!bus->ifs[0].bs && !bus->ifs[1].bs) ||
-        (s != bus->ifs && !s->bs))
+    if ((!bus->ifs[0].blk && !bus->ifs[1].blk) ||
+        (s != bus->ifs && !s->blk)) {
         ret = 0;
-    else
+    } else {
         ret = s->status;
+    }
 #ifdef DEBUG_IDE
     printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
 #endif
@@ -2069,7 +2079,7 @@ static void ide_reset(IDEState *s)
 #endif
 
     if (s->pio_aiocb) {
-        bdrv_aio_cancel(s->pio_aiocb);
+        blk_aio_cancel(s->pio_aiocb);
         s->pio_aiocb = NULL;
     }
 
@@ -2133,7 +2143,7 @@ void ide_bus_reset(IDEBus *bus)
 #ifdef DEBUG_AIO
         printf("aio_cancel\n");
 #endif
-        bdrv_aio_cancel(bus->dma->aiocb);
+        blk_aio_cancel(bus->dma->aiocb);
         bus->dma->aiocb = NULL;
     }
 
@@ -2162,7 +2172,7 @@ static void ide_resize_cb(void *opaque)
         return;
     }
 
-    bdrv_get_geometry(s->bs, &nb_sectors);
+    blk_get_geometry(s->blk, &nb_sectors);
     s->nb_sectors = nb_sectors;
 
     /* Update the identify data buffer. */
@@ -2186,7 +2196,7 @@ static const BlockDevOps ide_hd_block_ops = {
     .resize_cb = ide_resize_cb,
 };
 
-int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
+int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
                    const char *version, const char *serial, const char *model,
                    uint64_t wwn,
                    uint32_t cylinders, uint32_t heads, uint32_t secs,
@@ -2194,10 +2204,10 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
 {
     uint64_t nb_sectors;
 
-    s->bs = bs;
+    s->blk = blk;
     s->drive_kind = kind;
 
-    bdrv_get_geometry(bs, &nb_sectors);
+    blk_get_geometry(blk, &nb_sectors);
     s->cylinders = cylinders;
     s->heads = heads;
     s->sectors = secs;
@@ -2211,18 +2221,18 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
     s->smart_errors = 0;
     s->smart_selftest_count = 0;
     if (kind == IDE_CD) {
-        bdrv_set_dev_ops(bs, &ide_cd_block_ops, s);
-        bdrv_set_guest_block_size(bs, 2048);
+        blk_set_dev_ops(blk, &ide_cd_block_ops, s);
+        blk_set_guest_block_size(blk, 2048);
     } else {
-        if (!bdrv_is_inserted(s->bs)) {
+        if (!blk_is_inserted(s->blk)) {
             error_report("Device needs media, but drive is empty");
             return -1;
         }
-        if (bdrv_is_read_only(bs)) {
+        if (blk_is_read_only(blk)) {
             error_report("Can't use a read-only drive");
             return -1;
         }
-        bdrv_set_dev_ops(bs, &ide_hd_block_ops, s);
+        blk_set_dev_ops(blk, &ide_hd_block_ops, s);
     }
     if (serial) {
         pstrcpy(s->drive_serial_str, sizeof(s->drive_serial_str), serial);
@@ -2253,7 +2263,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
     }
 
     ide_reset(s);
-    bdrv_iostatus_enable(bs);
+    blk_iostatus_enable(blk);
     return 0;
 }
 
@@ -2270,7 +2280,7 @@ static void ide_init1(IDEBus *bus, int unit)
     s->io_buffer = qemu_memalign(2048, s->io_buffer_total_len);
     memset(s->io_buffer, 0, s->io_buffer_total_len);
 
-    s->smart_selftest_data = qemu_blockalign(s->bs, 512);
+    s->smart_selftest_data = blk_blockalign(s->blk, 512);
     memset(s->smart_selftest_data, 0, 512);
 
     s->sector_write_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
@@ -2365,7 +2375,7 @@ static int ide_drive_post_load(void *opaque, int version_id)
     IDEState *s = opaque;
 
     if (s->identify_set) {
-        bdrv_set_enable_write_cache(s->bs, !!(s->identify_data[85] & (1 << 5)));
+        blk_set_enable_write_cache(s->blk, !!(s->identify_data[85] & (1 << 5)));
     }
     return 0;
 }
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index a2f1639..6351363 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -65,7 +65,7 @@
 #include <hw/i386/pc.h>
 #include <hw/pci/pci.h>
 #include <hw/isa/isa.h>
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/dma.h"
 
 #include <hw/ide/pci.h>
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 9314c80..68ac610 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -373,7 +373,7 @@ struct IDEState {
 
     /* set for lba48 access */
     uint8_t lba48;
-    BlockDriverState *bs;
+    BlockBackend *blk;
     char version[9];
     /* ATAPI specific */
     struct unreported_events events;
@@ -537,7 +537,7 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
 void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
 uint32_t ide_data_readl(void *opaque, uint32_t addr);
 
-int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind,
+int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind,
                    const char *version, const char *serial, const char *model,
                    uint64_t wwn,
                    uint32_t cylinders, uint32_t heads, uint32_t secs,
@@ -555,7 +555,7 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
                         EndTransferFunc *end_transfer_func);
 void ide_transfer_stop(IDEState *s);
 void ide_set_inactive(IDEState *s, bool more);
-BlockAIOCB *ide_issue_trim(BlockDriverState *bs,
+BlockAIOCB *ide_issue_trim(BlockBackend *blk,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockCompletionFunc *cb, void *opaque);
 
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 4cbcb1c..b084162 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -25,7 +25,7 @@
 #include <hw/hw.h>
 #include <hw/i386/pc.h>
 #include <hw/isa/isa.h>
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/dma.h"
 
 #include <hw/ide/internal.h>
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 371e172..ca8e834 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -25,7 +25,7 @@
 #include "hw/hw.h"
 #include "hw/ppc/mac.h"
 #include "hw/ppc/mac_dbdma.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/dma.h"
 
 #include <hw/ide/internal.h>
@@ -134,7 +134,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
         MACIO_DPRINTF("precopying unaligned %d bytes to %#" HWADDR_PRIx "\n",
                       unaligned, io->addr + io->len - unaligned);
 
-        bdrv_read(s->bs, sector_num + nsector, io->remainder, 1);
+        blk_read(s->blk, sector_num + nsector, io->remainder, 1);
         cpu_physical_memory_write(io->addr + io->len - unaligned,
                                   io->remainder, unaligned);
 
@@ -164,14 +164,14 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
                   (s->lba << 2) + (s->io_buffer_index >> 9),
                   s->packet_transfer_size, s->dma_cmd);
 
-    m->aiocb = dma_bdrv_read(s->bs, &s->sg,
-                             (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),
-                             pmac_ide_atapi_transfer_cb, io);
+    m->aiocb = dma_blk_read(s->blk, &s->sg,
+                            (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),
+                            pmac_ide_atapi_transfer_cb, io);
     return;
 
 done:
     MACIO_DPRINTF("done DMA\n");
-    bdrv_acct_done(s->bs, &s->acct);
+    blk_acct_done(s->blk, &s->acct);
     io->dma_end(opaque);
 }
 
@@ -254,8 +254,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
             qemu_iovec_reset(&io->iov);
             qemu_iovec_add(&io->iov, io->remainder, 0x200);
 
-            m->aiocb = bdrv_aio_writev(s->bs, sector_num - 1, &io->iov, 1,
-                                       pmac_ide_transfer_cb, io);
+            m->aiocb = blk_aio_writev(s->blk, sector_num - 1, &io->iov, 1,
+                                      pmac_ide_transfer_cb, io);
         }
     }
 
@@ -294,8 +294,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
             qemu_iovec_reset(&io->iov);
             qemu_iovec_add(&io->iov, io->remainder, 0x200);
 
-            m->aiocb = bdrv_aio_readv(s->bs, sector_num + nsector, &io->iov, 1,
-                                      pmac_ide_transfer_cb, io);
+            m->aiocb = blk_aio_readv(s->blk, sector_num + nsector, &io->iov, 1,
+                                     pmac_ide_transfer_cb, io);
             break;
         case IDE_DMA_WRITE:
             /* cache the contents in our io struct */
@@ -333,17 +333,17 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
 
     switch (s->dma_cmd) {
     case IDE_DMA_READ:
-        m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
+        m->aiocb = dma_blk_read(s->blk, &s->sg, sector_num,
+                                pmac_ide_transfer_cb, io);
+        break;
+    case IDE_DMA_WRITE:
+        m->aiocb = dma_blk_write(s->blk, &s->sg, sector_num,
                                  pmac_ide_transfer_cb, io);
         break;
-    case IDE_DMA_WRITE:
-        m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
-                                  pmac_ide_transfer_cb, io);
-        break;
     case IDE_DMA_TRIM:
-        m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
-                               ide_issue_trim, pmac_ide_transfer_cb, io,
-                               DMA_DIRECTION_TO_DEVICE);
+        m->aiocb = dma_blk_io(s->blk, &s->sg, sector_num,
+                              ide_issue_trim, pmac_ide_transfer_cb, io,
+                              DMA_DIRECTION_TO_DEVICE);
         break;
     }
 
@@ -352,7 +352,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
 
 done:
     if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
-        bdrv_acct_done(s->bs, &s->acct);
+        blk_acct_done(s->blk, &s->acct);
     }
     io->dma_end(io);
 }
@@ -370,8 +370,8 @@ static void pmac_ide_transfer(DBDMA_io *io)
         /* Handle non-block ATAPI DMA transfers */
         if (s->lba == -1) {
             s->io_buffer_size = MIN(io->len, s->packet_transfer_size);
-            bdrv_acct_start(s->bs, &s->acct, s->io_buffer_size,
-                            BDRV_ACCT_READ);
+            blk_acct_start(s->blk, &s->acct, s->io_buffer_size,
+                           BDRV_ACCT_READ);
             MACIO_DPRINTF("non-block ATAPI DMA transfer size: %d\n",
                           s->io_buffer_size);
 
@@ -382,22 +382,22 @@ static void pmac_ide_transfer(DBDMA_io *io)
             m->dma_active = false;
 
             MACIO_DPRINTF("end of non-block ATAPI DMA transfer\n");
-            bdrv_acct_done(s->bs, &s->acct);
+            blk_acct_done(s->blk, &s->acct);
             io->dma_end(io);
             return;
         }
 
-        bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ);
+        blk_acct_start(s->blk, &s->acct, io->len, BDRV_ACCT_READ);
         pmac_ide_atapi_transfer_cb(io, 0);
         return;
     }
 
     switch (s->dma_cmd) {
     case IDE_DMA_READ:
-        bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ);
+        blk_acct_start(s->blk, &s->acct, io->len, BDRV_ACCT_READ);
         break;
     case IDE_DMA_WRITE:
-        bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_WRITE);
+        blk_acct_start(s->blk, &s->acct, io->len, BDRV_ACCT_WRITE);
         break;
     default:
         break;
@@ -412,7 +412,7 @@ static void pmac_ide_flush(DBDMA_io *io)
     MACIOIDEState *m = io->opaque;
 
     if (m->aiocb) {
-        bdrv_drain_all();
+        blk_drain_all();
     }
 }
 
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index 15671b8..ed85185 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -25,7 +25,7 @@
 #include <hw/hw.h>
 #include <hw/i386/pc.h>
 #include <hw/pcmcia.h>
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/dma.h"
 
 #include <hw/ide/internal.h>
@@ -247,7 +247,7 @@ static uint16_t md_common_read(PCMCIACardState *card, uint32_t at)
         return ide_ioport_read(&s->bus, 0x1);
     case 0xe:	/* Alternate Status */
         ifs = idebus_active_if(&s->bus);
-        if (ifs->bs) {
+        if (ifs->blk) {
             return ifs->status;
         } else {
             return 0;
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index 01c1d0e..5703be1 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -24,7 +24,7 @@
  */
 #include "hw/hw.h"
 #include "hw/sysbus.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/dma.h"
 
 #include <hw/ide/internal.h>
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 6ff1c58..2dad50e 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -26,7 +26,7 @@
 #include <hw/i386/pc.h>
 #include <hw/pci/pci.h>
 #include <hw/isa/isa.h>
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/dma.h"
 
 #include <hw/ide/pci.h>
@@ -302,7 +302,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val)
              * aio operation with preadv/pwritev.
              */
             if (bm->bus->dma->aiocb) {
-                bdrv_drain_all();
+                blk_drain_all();
                 assert(bm->bus->dma->aiocb == NULL);
             }
             bm->status &= ~BM_STATUS_DMAING;
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index c6c256f..61958c6 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -28,7 +28,6 @@
 #include <hw/pci/pci.h>
 #include <hw/isa/isa.h>
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 
@@ -179,12 +178,12 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
     for (; i < 3; i++) {
         di = drive_get_by_index(IF_IDE, i);
         if (di != NULL && !di->media_cd) {
-            BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(di));
-            DeviceState *ds = bdrv_get_attached_dev(bs);
+            BlockBackend *blk = blk_by_legacy_dinfo(di);
+            DeviceState *ds = blk_get_attached_dev(blk);
             if (ds) {
-                bdrv_detach_dev(bs, ds);
+                blk_detach_dev(blk, ds);
             }
-            pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
+            pci_ide->bus[di->bus].ifs[di->unit].blk = NULL;
             drive_del(di);
         }
     }
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 75e8eb3..4818334 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -72,7 +72,7 @@ static int ide_qdev_init(DeviceState *qdev)
     IDEDeviceClass *dc = IDE_DEVICE_GET_CLASS(dev);
     IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
 
-    if (!dev->conf.bs) {
+    if (!dev->conf.blk) {
         error_report("No drive specified");
         goto err;
     }
@@ -117,8 +117,7 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
 
     dev = qdev_create(&bus->qbus, drive->media_cd ? "ide-cd" : "ide-hd");
     qdev_prop_set_uint32(dev, "unit", unit);
-    qdev_prop_set_drive_nofail(dev, "drive",
-                               blk_bs(blk_by_legacy_dinfo(drive)));
+    qdev_prop_set_drive_nofail(dev, "drive", blk_by_legacy_dinfo(drive));
     qdev_init_nofail(dev);
     return DO_UPCAST(IDEDevice, qdev, dev);
 }
@@ -128,7 +127,7 @@ int ide_get_geometry(BusState *bus, int unit,
 {
     IDEState *s = &DO_UPCAST(IDEBus, qbus, bus)->ifs[unit];
 
-    if (s->drive_kind != IDE_HD || !s->bs) {
+    if (s->drive_kind != IDE_HD || !s->blk) {
         return -1;
     }
 
@@ -173,7 +172,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
         }
     }
 
-    if (ide_init_drive(s, dev->conf.bs, kind,
+    if (ide_init_drive(s, dev->conf.blk, kind,
                        dev->version, dev->serial, dev->model, dev->wwn,
                        dev->conf.cyls, dev->conf.heads, dev->conf.secs,
                        dev->chs_trans) < 0) {
@@ -205,7 +204,7 @@ static int ide_cd_initfn(IDEDevice *dev)
 
 static int ide_drive_initfn(IDEDevice *dev)
 {
-    DriveInfo *dinfo = drive_get_by_blockdev(dev->conf.bs);
+    DriveInfo *dinfo = blk_legacy_dinfo(dev->conf.blk);
 
     return ide_dev_initfn(dev, dinfo->media_cd ? IDE_CD : IDE_HD);
 }
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 89d27b4..4d8089d 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -27,7 +27,7 @@
 #include <hw/i386/pc.h>
 #include <hw/pci/pci.h>
 #include <hw/isa/isa.h>
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/dma.h"
 
diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c
index b691a0c..40a1106 100644
--- a/hw/isa/pc87312.c
+++ b/hw/isa/pc87312.c
@@ -322,12 +322,12 @@ static void pc87312_realize(DeviceState *dev, Error **errp)
         drive = drive_get(IF_FLOPPY, 0, 0);
         if (drive != NULL) {
             qdev_prop_set_drive_nofail(d, "driveA",
-                                       blk_bs(blk_by_legacy_dinfo(drive)));
+                                       blk_by_legacy_dinfo(drive));
         }
         drive = drive_get(IF_FLOPPY, 0, 1);
         if (drive != NULL) {
             qdev_prop_set_drive_nofail(d, "driveB",
-                                       blk_bs(blk_by_legacy_dinfo(drive)));
+                                       blk_by_legacy_dinfo(drive));
         }
         qdev_init_nofail(d);
         s->fdc.dev = isa;
diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
index 17c5610..08e4ce3 100644
--- a/hw/lm32/lm32_boards.c
+++ b/hw/lm32/lm32_boards.c
@@ -24,7 +24,6 @@
 #include "hw/boards.h"
 #include "hw/loader.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "elf.h"
 #include "lm32_hwsetup.h"
 #include "lm32.h"
@@ -119,7 +118,7 @@ static void lm32_evr_init(MachineState *machine)
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
     pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
-                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           flash_sector_size, flash_size / flash_sector_size,
                           1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
 
@@ -221,7 +220,7 @@ static void lm32_uclinux_init(MachineState *machine)
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Spansion S29NS128P */
     pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
-                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           flash_sector_size, flash_size / flash_sector_size,
                           1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
 
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 904b9c0..2589568 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -27,7 +27,6 @@
 #include "hw/loader.h"
 #include "elf.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "milkymist-hw.h"
 #include "lm32.h"
 #include "exec/address-spaces.h"
@@ -126,7 +125,7 @@ milkymist_init(MachineState *machine)
     dinfo = drive_get(IF_PFLASH, 0, 0);
     /* Numonyx JS28F256J3F105 */
     pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
-                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           flash_sector_size, flash_size / flash_sector_size,
                           2, 0x00, 0x89, 0x00, 0x1d, 1);
 
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 2974791..12acea7 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -33,7 +33,6 @@
 #include "hw/devices.h"
 #include "hw/boards.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "hw/char/serial.h"
 #include "exec/address-spaces.h"
 #include "hw/ssi.h"
@@ -113,7 +112,7 @@ petalogix_ml605_init(MachineState *machine)
      * 10th paremeter 0 means little-endian */
     pflash_cfi01_register(FLASH_BASEADDR,
                           NULL, "petalogix_ml605.flash", FLASH_SIZE,
-                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           (64 * 1024), FLASH_SIZE >> 16,
                           2, 0x89, 0x18, 0x0000, 0x0, 0);
 
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index a69301f..8c90c56 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -31,7 +31,6 @@
 #include "hw/devices.h"
 #include "hw/boards.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
 #include "boot.h"
@@ -93,7 +92,7 @@ petalogix_s3adsp1800_init(MachineState *machine)
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(FLASH_BASEADDR,
                           NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
-                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           (64 * 1024), FLASH_SIZE >> 16,
                           1, 0x89, 0x18, 0x0000, 0x0, 1);
 
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index f7533ed..fc0e008 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -25,7 +25,7 @@
 #include "net/net.h"
 #include "hw/boards.h"
 #include "hw/i2c/smbus.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "hw/block/flash.h"
 #include "hw/mips/mips.h"
 #include "hw/mips/cpudevs.h"
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index c113a80..5b24e45 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -39,7 +39,7 @@
 #include "hw/timer/mc146818rtc.h"
 #include "hw/timer/i8254.h"
 #include "hw/audio/pcspk.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "hw/sysbus.h"
 #include "exec/address-spaces.h"
 #include "sysemu/qtest.h"
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 9f84ad6..dc4b364 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -29,7 +29,7 @@
 #include "net/net.h"
 #include "hw/boards.h"
 #include "hw/i2c/smbus.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "hw/block/flash.h"
 #include "hw/mips/mips.h"
 #include "hw/mips/cpudevs.h"
@@ -1032,12 +1032,12 @@ void mips_malta_init(MachineState *machine)
         printf("Register parallel flash %d size " TARGET_FMT_lx " at "
                "addr %08llx '%s' %x\n",
                fl_idx, bios_size, FLASH_ADDRESS,
-               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
+               blk_name(dinfo->bdrv), fl_sectors);
     }
 #endif
     fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
                                BIOS_SIZE,
-                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                               dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                                65536, fl_sectors,
                                4, 0x0000, 0x0000, 0x0000, 0x0000, be);
     bios = pflash_cfi01_get_memory(fl);
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index 6fd69b9..b23ed06 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -25,7 +25,6 @@
 #include "hw/timer/mc146818rtc.h"
 #include "hw/timer/i8254.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 #include "sysemu/qtest.h"
 
@@ -241,7 +240,7 @@ void mips_r4k_init(MachineState *machine)
     } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
         uint32_t mips_rom = 0x00400000;
         if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
-                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                   blk_by_legacy_dinfo(dinfo),
                                    sector_len, mips_rom / sector_len,
                                    4, 0, 0, 0, 0, be)) {
             fprintf(stderr, "qemu: Error registering flash memory.\n");
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
index 6a72ef4..10b5b2e 100644
--- a/hw/nvram/spapr_nvram.c
+++ b/hw/nvram/spapr_nvram.c
@@ -24,6 +24,7 @@
 
 #include <libfdt.h>
 
+#include "sysemu/block-backend.h"
 #include "sysemu/device_tree.h"
 #include "hw/sysbus.h"
 #include "hw/ppc/spapr.h"
@@ -33,7 +34,7 @@ typedef struct sPAPRNVRAM {
     VIOsPAPRDevice sdev;
     uint32_t size;
     uint8_t *buf;
-    BlockDriverState *drive;
+    BlockBackend *blk;
 } sPAPRNVRAM;
 
 #define TYPE_VIO_SPAPR_NVRAM "spapr-nvram"
@@ -77,8 +78,8 @@ static void rtas_nvram_fetch(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     }
 
     membuf = cpu_physical_memory_map(buffer, &len, 1);
-    if (nvram->drive) {
-        alen = bdrv_pread(nvram->drive, offset, membuf, len);
+    if (nvram->blk) {
+        alen = blk_pread(nvram->blk, offset, membuf, len);
     } else {
         assert(nvram->buf);
 
@@ -122,8 +123,8 @@ static void rtas_nvram_store(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     }
 
     membuf = cpu_physical_memory_map(buffer, &len, 0);
-    if (nvram->drive) {
-        alen = bdrv_pwrite(nvram->drive, offset, membuf, len);
+    if (nvram->blk) {
+        alen = blk_pwrite(nvram->blk, offset, membuf, len);
     } else {
         assert(nvram->buf);
 
@@ -140,8 +141,8 @@ static int spapr_nvram_init(VIOsPAPRDevice *dev)
 {
     sPAPRNVRAM *nvram = VIO_SPAPR_NVRAM(dev);
 
-    if (nvram->drive) {
-        nvram->size = bdrv_getlength(nvram->drive);
+    if (nvram->blk) {
+        nvram->size = blk_getlength(nvram->blk);
     } else {
         nvram->size = DEFAULT_NVRAM_SIZE;
         nvram->buf = g_malloc0(nvram->size);
@@ -168,7 +169,7 @@ static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
 
 static Property spapr_nvram_properties[] = {
     DEFINE_SPAPR_PROPERTIES(sPAPRNVRAM, sdev),
-    DEFINE_PROP_DRIVE("drive", sPAPRNVRAM, drive),
+    DEFINE_PROP_DRIVE("drive", sPAPRNVRAM, blk),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c
index e4d51de..23c80ca 100644
--- a/hw/pci/pci-hotplug-old.c
+++ b/hw/pci/pci-hotplug-old.c
@@ -34,7 +34,6 @@
 #include "hw/virtio/virtio-blk.h"
 #include "qemu/config-file.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "qapi/error.h"
 
 static int pci_read_devaddr(Monitor *mon, const char *addr,
@@ -128,7 +127,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
     dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
     dinfo->bus = scsibus->busnr;
     scsidev = scsi_bus_legacy_add_drive(scsibus,
-                                        blk_bs(blk_by_legacy_dinfo(dinfo)),
+                                        blk_by_legacy_dinfo(dinfo),
                                         dinfo->unit, false, -1, NULL, NULL);
     if (!scsidev) {
         return -1;
@@ -250,7 +249,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
         }
         dev = pci_create(bus, devfn, "virtio-blk-pci");
         if (qdev_prop_set_drive(&dev->qdev, "drive",
-                                blk_bs(blk_by_legacy_dinfo(dinfo))) < 0) {
+                                blk_by_legacy_dinfo(dinfo)) < 0) {
             object_unparent(OBJECT(dev));
             dev = NULL;
             break;
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 8453bfa..77d4416 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -65,7 +65,7 @@
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
 #include "hw/usb.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "exec/address-spaces.h"
 #include "hw/sysbus.h"
 
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 630a9f9..8fce5e9 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -40,7 +40,7 @@
 #include "elf.h"
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "exec/address-spaces.h"
 
 #define MAX_IDE_BUS 2
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 7ff5ee5..371893b 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -28,7 +28,7 @@
 #include "hw/block/flash.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/qtest.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "hw/boards.h"
 #include "qemu/log.h"
 #include "qemu/error-report.h"
@@ -226,19 +226,19 @@ static void ref405ep_init(MachineState *machine)
 #ifdef USE_FLASH_BIOS
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
-        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
+        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
 
-        bios_size = bdrv_getlength(bs);
+        bios_size = blk_getlength(blk);
         fl_sectors = (bios_size + 65535) >> 16;
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size %lx"
                " at addr %lx '%s' %d\n",
                fl_idx, bios_size, -bios_size,
-               bdrv_get_device_name(bs), fl_sectors);
+               blk_name(blk), fl_sectors);
 #endif
         pflash_cfi02_register((uint32_t)(-bios_size),
                               NULL, "ef405ep.bios", bios_size,
-                              bs, 65536, fl_sectors, 1,
+                              blk, 65536, fl_sectors, 1,
                               2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
         fl_idx++;
@@ -550,9 +550,9 @@ static void taihu_405ep_init(MachineState *machine)
 #if defined(USE_FLASH_BIOS)
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
-        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
+        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
 
-        bios_size = bdrv_getlength(bs);
+        bios_size = blk_getlength(blk);
         /* XXX: should check that size is 2MB */
         //        bios_size = 2 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
@@ -560,11 +560,11 @@ static void taihu_405ep_init(MachineState *machine)
         printf("Register parallel flash %d size %lx"
                " at addr %lx '%s' %d\n",
                fl_idx, bios_size, -bios_size,
-               bdrv_get_device_name(bs), fl_sectors);
+               blk_name(blk), fl_sectors);
 #endif
         pflash_cfi02_register((uint32_t)(-bios_size),
                               NULL, "taihu_405ep.bios", bios_size,
-                              bs, 65536, fl_sectors, 1,
+                              blk, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
         fl_idx++;
@@ -598,9 +598,9 @@ static void taihu_405ep_init(MachineState *machine)
     /* Register Linux flash */
     dinfo = drive_get(IF_PFLASH, 0, fl_idx);
     if (dinfo) {
-        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
+        BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
 
-        bios_size = bdrv_getlength(bs);
+        bios_size = blk_getlength(blk);
         /* XXX: should check that size is 32MB */
         bios_size = 32 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
@@ -608,10 +608,10 @@ static void taihu_405ep_init(MachineState *machine)
         printf("Register parallel flash %d size %lx"
                " at addr " TARGET_FMT_lx " '%s'\n",
                fl_idx, bios_size, (target_ulong)0xfc000000,
-               bdrv_get_device_name(bs));
+               blk_name(blk));
 #endif
         pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
-                              bs, 65536, fl_sectors, 1,
+                              blk, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
                               1);
         fl_idx++;
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index f0ef1af..37c582b 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -38,7 +38,7 @@
 #include "hw/loader.h"
 #include "hw/timer/mc146818rtc.h"
 #include "hw/isa/pc87312.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/arch_init.h"
 #include "sysemu/qtest.h"
 #include "exec/address-spaces.h"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a577812..78fb927 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -30,7 +30,6 @@
 #include "elf.h"
 #include "net/net.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "sysemu/cpus.h"
 #include "sysemu/kvm.h"
 #include "kvm_ppc.h"
@@ -926,8 +925,7 @@ static void spapr_create_nvram(sPAPREnvironment *spapr)
     DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
 
     if (dinfo) {
-        qdev_prop_set_drive_nofail(dev, "drive",
-                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
+        qdev_prop_set_drive_nofail(dev, "drive", blk_by_legacy_dinfo(dinfo));
     }
 
     qdev_init_nofail(dev);
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index a0ce447..6ebd5be 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -40,7 +40,6 @@
 #include "ppc405.h"
 
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "qapi/qmp/qerror.h"
 
 #define EPAPR_MAGIC    (0x45504150)
@@ -228,7 +227,7 @@ static void virtex_init(MachineState *machine)
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi01_register(PFLASH_BASEADDR, NULL, "virtex.flash", FLASH_SIZE,
-                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           (64 * 1024), FLASH_SIZE >> 16,
                           1, 0x89, 0x18, 0x0000, 0x0, 1);
 
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 6b6fb61..81cf22a 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -18,7 +18,7 @@
  */
 
 #include "hw/hw.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/sysemu.h"
 #include "hw/boards.h"
 #include "monitor/monitor.h"
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index 4ca52b7..df0fdaf 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -22,7 +22,7 @@
  */
 
 #include "hw/hw.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "net/net.h"
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 33a1d86..6339f82 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -10,7 +10,7 @@
  */
 
 #include "hw/hw.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/sysemu.h"
 #include "net/net.h"
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index eedc992..36a04f3 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -21,6 +21,7 @@
 #include "hw/hw.h"
 #include "hw/pci/pci.h"
 #include "sysemu/dma.h"
+#include "sysemu/block-backend.h"
 #include "hw/pci/msi.h"
 #include "hw/pci/msix.h"
 #include "qemu/iov.h"
@@ -976,7 +977,6 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
 {
     struct mfi_pd_info *info = cmd->iov_buf;
     size_t dcmd_size = sizeof(struct mfi_pd_info);
-    BlockConf *conf = &sdev->conf;
     uint64_t pd_size;
     uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (lun & 0xFF);
     uint8_t cmdbuf[6];
@@ -1037,7 +1037,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
     info->ref.v.device_id = cpu_to_le16(sdev_id);
     info->state.ddf.pd_type = cpu_to_le16(MFI_PD_DDF_TYPE_IN_VD|
                                           MFI_PD_DDF_TYPE_INTF_SAS);
-    bdrv_get_geometry(conf->bs, &pd_size);
+    blk_get_geometry(sdev->conf.blk, &pd_size);
     info->raw_size = cpu_to_le64(pd_size);
     info->non_coerced_size = cpu_to_le64(pd_size);
     info->coerced_size = cpu_to_le64(pd_size);
@@ -1100,13 +1100,12 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
     }
     QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
         SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
-        BlockConf *conf = &sdev->conf;
 
         if (num_ld_disks >= max_ld_disks) {
             break;
         }
         /* Logical device size is in blocks */
-        bdrv_get_geometry(conf->bs, &ld_size);
+        blk_get_geometry(sdev->conf.blk, &ld_size);
         info.ld_list[num_ld_disks].ld.v.target_id = sdev->id;
         info.ld_list[num_ld_disks].ld.v.lun_id = sdev->lun;
         info.ld_list[num_ld_disks].state = MFI_LD_STATE_OPTIMAL;
@@ -1144,7 +1143,6 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
     uint8_t cdb[6];
     SCSIRequest *req;
     ssize_t len, resid;
-    BlockConf *conf = &sdev->conf;
     uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (lun & 0xFF);
     uint64_t ld_size;
 
@@ -1177,7 +1175,7 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun,
     info->ld_config.params.num_drives = 1;
     info->ld_config.params.is_consistent = 1;
     /* Logical device size is in blocks */
-    bdrv_get_geometry(conf->bs, &ld_size);
+    blk_get_geometry(sdev->conf.blk, &ld_size);
     info->size = cpu_to_le64(ld_size);
     memset(info->ld_config.span, 0, sizeof(info->ld_config.span));
     info->ld_config.span[0].start_block = 0;
@@ -1261,7 +1259,6 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
 
     QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
         SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
-        BlockConf *conf = &sdev->conf;
         uint16_t sdev_id = ((sdev->id & 0xFF) >> 8) | (sdev->lun & 0xFF);
         struct mfi_array *array;
         struct mfi_ld_config *ld;
@@ -1269,7 +1266,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd)
         int i;
 
         array = (struct mfi_array *)(data + array_offset);
-        bdrv_get_geometry(conf->bs, &pd_size);
+        blk_get_geometry(sdev->conf.blk, &pd_size);
         array->size = cpu_to_le64(pd_size);
         array->num_drives = 1;
         array->array_ref = cpu_to_le16(sdev_id);
@@ -1340,7 +1337,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd)
 
 static int megasas_cache_flush(MegasasState *s, MegasasCmd *cmd)
 {
-    bdrv_drain_all();
+    blk_drain_all();
     return MFI_STAT_OK;
 }
 
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index f5156ae..869d616 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -220,7 +220,7 @@ static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)
 }
 
 /* handle legacy '-drive if=scsi,...' cmd line args */
-SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
+SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
                                       int unit, bool removable, int bootindex,
                                       const char *serial, Error **errp)
 {
@@ -228,7 +228,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
     DeviceState *dev;
     Error *err = NULL;
 
-    driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk";
+    driver = blk_is_sg(blk) ? "scsi-generic" : "scsi-disk";
     dev = qdev_create(&bus->qbus, driver);
     qdev_prop_set_uint32(dev, "scsi-id", unit);
     if (bootindex >= 0) {
@@ -240,7 +240,7 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
     if (serial && object_property_find(OBJECT(dev), "serial", NULL)) {
         qdev_prop_set_string(dev, "serial", serial);
     }
-    if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) {
+    if (qdev_prop_set_drive(dev, "drive", blk) < 0) {
         error_setg(errp, "Setting drive property failed");
         object_unparent(OBJECT(dev));
         return NULL;
@@ -268,7 +268,7 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp)
             continue;
         }
         qemu_opts_loc_restore(dinfo->opts);
-        scsi_bus_legacy_add_drive(bus, blk_bs(blk_by_legacy_dinfo(dinfo)),
+        scsi_bus_legacy_add_drive(bus, blk_by_legacy_dinfo(dinfo),
                                   unit, false, -1, NULL, &err);
         if (err != NULL) {
             error_report("%s", error_get_pretty(err));
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index e34a544..768c1ad 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -33,6 +33,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
 #include "hw/scsi/scsi.h"
 #include "block/scsi.h"
 #include "sysemu/sysemu.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 #include "hw/block/block.h"
 #include "sysemu/dma.h"
@@ -112,11 +113,11 @@ static void scsi_cancel_io(SCSIRequest *req)
 
     DPRINTF("Cancel tag=0x%x\n", req->tag);
     if (r->req.aiocb) {
-        bdrv_aio_cancel(r->req.aiocb);
+        blk_aio_cancel(r->req.aiocb);
 
         /* This reference was left in by scsi_*_data.  We take ownership of
          * it the moment scsi_req_cancel is called, independent of whether
-         * bdrv_aio_cancel completes the request or not.  */
+         * blk_aio_cancel completes the request or not.  */
         scsi_req_unref(&r->req);
     }
     r->req.aiocb = NULL;
@@ -128,7 +129,7 @@ static uint32_t scsi_init_iovec(SCSIDiskReq *r, size_t size)
 
     if (!r->iov.iov_base) {
         r->buflen = size;
-        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
+        r->iov.iov_base = blk_blockalign(s->qdev.conf.blk, r->buflen);
     }
     r->iov.iov_len = MIN(r->sector_count * 512, r->buflen);
     qemu_iovec_init_external(&r->qiov, &r->iov, 1);
@@ -183,7 +184,7 @@ static void scsi_aio_complete(void *opaque, int ret)
 
     assert(r->req.aiocb != NULL);
     r->req.aiocb = NULL;
-    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    blk_acct_done(s->qdev.conf.blk, &r->acct);
     if (r->req.io_canceled) {
         goto done;
     }
@@ -237,8 +238,8 @@ static void scsi_write_do_fua(SCSIDiskReq *r)
     }
 
     if (scsi_is_cmd_fua(&r->req.cmd)) {
-        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
-        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
+        blk_acct_start(s->qdev.conf.blk, &r->acct, 0, BDRV_ACCT_FLUSH);
+        r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r);
         return;
     }
 
@@ -257,7 +258,7 @@ static void scsi_dma_complete_noio(void *opaque, int ret)
 
     if (r->req.aiocb != NULL) {
         r->req.aiocb = NULL;
-        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+        blk_acct_done(s->qdev.conf.blk, &r->acct);
     }
     if (r->req.io_canceled) {
         goto done;
@@ -300,7 +301,7 @@ static void scsi_read_complete(void * opaque, int ret)
 
     assert(r->req.aiocb != NULL);
     r->req.aiocb = NULL;
-    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    blk_acct_done(s->qdev.conf.blk, &r->acct);
     if (r->req.io_canceled) {
         goto done;
     }
@@ -333,7 +334,7 @@ static void scsi_do_read(void *opaque, int ret)
 
     if (r->req.aiocb != NULL) {
         r->req.aiocb = NULL;
-        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+        blk_acct_done(s->qdev.conf.blk, &r->acct);
     }
     if (r->req.io_canceled) {
         goto done;
@@ -349,15 +350,16 @@ static void scsi_do_read(void *opaque, int ret)
     scsi_req_ref(&r->req);
 
     if (r->req.sg) {
-        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_READ);
+        dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BDRV_ACCT_READ);
         r->req.resid -= r->req.sg->size;
-        r->req.aiocb = dma_bdrv_read(s->qdev.conf.bs, r->req.sg, r->sector,
-                                     scsi_dma_complete, r);
+        r->req.aiocb = dma_blk_read(s->qdev.conf.blk, r->req.sg, r->sector,
+                                    scsi_dma_complete, r);
     } else {
         n = scsi_init_iovec(r, SCSI_DMA_BUF_SIZE);
-        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_READ);
-        r->req.aiocb = bdrv_aio_readv(s->qdev.conf.bs, r->sector, &r->qiov, n,
-                                      scsi_read_complete, r);
+        blk_acct_start(s->qdev.conf.blk, &r->acct, n * BDRV_SECTOR_SIZE,
+                       BDRV_ACCT_READ);
+        r->req.aiocb = blk_aio_readv(s->qdev.conf.blk, r->sector, &r->qiov, n,
+                                     scsi_read_complete, r);
     }
 
 done:
@@ -399,8 +401,8 @@ static void scsi_read_data(SCSIRequest *req)
     first = !r->started;
     r->started = true;
     if (first && scsi_is_cmd_fua(&r->req.cmd)) {
-        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
-        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_do_read, r);
+        blk_acct_start(s->qdev.conf.blk, &r->acct, 0, BDRV_ACCT_FLUSH);
+        r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_do_read, r);
     } else {
         scsi_do_read(r, 0);
     }
@@ -417,7 +419,8 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
 {
     bool is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV);
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
-    BlockErrorAction action = bdrv_get_error_action(s->qdev.conf.bs, is_read, error);
+    BlockErrorAction action = blk_get_error_action(s->qdev.conf.blk,
+                                                   is_read, error);
 
     if (action == BLOCK_ERROR_ACTION_REPORT) {
         switch (error) {
@@ -438,7 +441,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
             break;
         }
     }
-    bdrv_error_action(s->qdev.conf.bs, action, is_read, error);
+    blk_error_action(s->qdev.conf.blk, action, is_read, error);
     if (action == BLOCK_ERROR_ACTION_STOP) {
         scsi_req_retry(&r->req);
     }
@@ -453,7 +456,7 @@ static void scsi_write_complete(void * opaque, int ret)
 
     if (r->req.aiocb != NULL) {
         r->req.aiocb = NULL;
-        bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+        blk_acct_done(s->qdev.conf.blk, &r->acct);
     }
     if (r->req.io_canceled) {
         goto done;
@@ -522,15 +525,16 @@ static void scsi_write_data(SCSIRequest *req)
     }
 
     if (r->req.sg) {
-        dma_acct_start(s->qdev.conf.bs, &r->acct, r->req.sg, BDRV_ACCT_WRITE);
+        dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BDRV_ACCT_WRITE);
         r->req.resid -= r->req.sg->size;
-        r->req.aiocb = dma_bdrv_write(s->qdev.conf.bs, r->req.sg, r->sector,
-                                      scsi_dma_complete, r);
+        r->req.aiocb = dma_blk_write(s->qdev.conf.blk, r->req.sg, r->sector,
+                                     scsi_dma_complete, r);
     } else {
         n = r->qiov.size / 512;
-        bdrv_acct_start(s->qdev.conf.bs, &r->acct, n * BDRV_SECTOR_SIZE, BDRV_ACCT_WRITE);
-        r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, r->sector, &r->qiov, n,
-                                       scsi_write_complete, r);
+        blk_acct_start(s->qdev.conf.blk, &r->acct, n * BDRV_SECTOR_SIZE,
+                       BDRV_ACCT_WRITE);
+        r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, r->sector, &r->qiov, n,
+                                      scsi_write_complete, r);
     }
 }
 
@@ -597,7 +601,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
 
         case 0x83: /* Device identification page, mandatory */
         {
-            const char *str = s->serial ?: bdrv_get_device_name(s->qdev.conf.bs);
+            const char *str = s->serial ?: blk_name(s->qdev.conf.blk);
             int max_len = s->serial ? 20 : 255 - 8;
             int id_len = strlen(str);
 
@@ -758,10 +762,10 @@ static inline bool media_is_dvd(SCSIDiskState *s)
     if (s->qdev.type != TYPE_ROM) {
         return false;
     }
-    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
+    if (!blk_is_inserted(s->qdev.conf.blk)) {
         return false;
     }
-    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
+    blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
     return nb_sectors > CD_MAX_SECTORS;
 }
 
@@ -771,10 +775,10 @@ static inline bool media_is_cd(SCSIDiskState *s)
     if (s->qdev.type != TYPE_ROM) {
         return false;
     }
-    if (!bdrv_is_inserted(s->qdev.conf.bs)) {
+    if (!blk_is_inserted(s->qdev.conf.blk)) {
         return false;
     }
-    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
+    blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
     return nb_sectors <= CD_MAX_SECTORS;
 }
 
@@ -835,7 +839,7 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
     }
 
     if (format != 0xff) {
-        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
+        if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) {
             scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
             return -1;
         }
@@ -857,7 +861,7 @@ static int scsi_read_dvd_structure(SCSIDiskState *s, SCSIDiskReq *r,
         if (layer != 0) {
             goto fail;
         }
-        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
+        blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
 
         outbuf[4] = 1;   /* DVD-ROM, part version 1 */
         outbuf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
@@ -912,7 +916,7 @@ static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
     media_status = 0;
     if (s->tray_open) {
         media_status = MS_TRAY_OPEN;
-    } else if (bdrv_is_inserted(s->qdev.conf.bs)) {
+    } else if (blk_is_inserted(s->qdev.conf.blk)) {
         media_status = MS_MEDIA_PRESENT;
     }
 
@@ -1110,7 +1114,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
     case MODE_PAGE_CACHING:
         length = 0x12;
         if (page_control == 1 || /* Changeable Values */
-            bdrv_enable_write_cache(s->qdev.conf.bs)) {
+            blk_enable_write_cache(s->qdev.conf.blk)) {
             p[0] = 4; /* WCE */
         }
         break;
@@ -1191,7 +1195,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
 
     if (s->qdev.type == TYPE_DISK) {
         dev_specific_param = s->features & (1 << SCSI_DISK_F_DPOFUA) ? 0x10 : 0;
-        if (bdrv_is_read_only(s->qdev.conf.bs)) {
+        if (blk_is_read_only(s->qdev.conf.blk)) {
             dev_specific_param |= 0x80; /* Readonly.  */
         }
     } else {
@@ -1213,7 +1217,7 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
         p += 8;
     }
 
-    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
+    blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
     if (!dbd && nb_sectors) {
         if (r->req.cmd.buf[0] == MODE_SENSE) {
             outbuf[3] = 8; /* Block descriptor length  */
@@ -1276,7 +1280,7 @@ static int scsi_disk_emulate_read_toc(SCSIRequest *req, uint8_t *outbuf)
     msf = req->cmd.buf[1] & 2;
     format = req->cmd.buf[2] & 0xf;
     start_track = req->cmd.buf[6];
-    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
+    blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
     DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
     nb_sectors /= s->qdev.blocksize / 512;
     switch (format) {
@@ -1316,14 +1320,14 @@ static int scsi_disk_emulate_start_stop(SCSIDiskReq *r)
     if ((s->features & (1 << SCSI_DISK_F_REMOVABLE)) && loej) {
         if (!start && !s->tray_open && s->tray_locked) {
             scsi_check_condition(r,
-                                 bdrv_is_inserted(s->qdev.conf.bs)
+                                 blk_is_inserted(s->qdev.conf.blk)
                                  ? SENSE_CODE(ILLEGAL_REQ_REMOVAL_PREVENTED)
                                  : SENSE_CODE(NOT_READY_REMOVAL_PREVENTED));
             return -1;
         }
 
         if (s->tray_open != !start) {
-            bdrv_eject(s->qdev.conf.bs, !start);
+            blk_eject(s->qdev.conf.blk, !start);
             s->tray_open = !start;
         }
     }
@@ -1390,7 +1394,7 @@ static void scsi_disk_apply_mode_select(SCSIDiskState *s, int page, uint8_t *p)
 {
     switch (page) {
     case MODE_PAGE_CACHING:
-        bdrv_set_enable_write_cache(s->qdev.conf.bs, (p[0] & 4) != 0);
+        blk_set_enable_write_cache(s->qdev.conf.blk, (p[0] & 4) != 0);
         break;
 
     default:
@@ -1493,11 +1497,11 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf)
             return;
         }
     }
-    if (!bdrv_enable_write_cache(s->qdev.conf.bs)) {
+    if (!blk_enable_write_cache(s->qdev.conf.blk)) {
         /* The request is used as the AIO opaque value, so add a ref.  */
         scsi_req_ref(&r->req);
-        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
-        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
+        blk_acct_start(s->qdev.conf.blk, &r->acct, 0, BDRV_ACCT_FLUSH);
+        r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r);
         return;
     }
 
@@ -1565,10 +1569,10 @@ static void scsi_unmap_complete(void *opaque, int ret)
             goto done;
         }
 
-        r->req.aiocb = bdrv_aio_discard(s->qdev.conf.bs,
-                                        sector_num * (s->qdev.blocksize / 512),
-                                        nb_sectors * (s->qdev.blocksize / 512),
-                                        scsi_unmap_complete, data);
+        r->req.aiocb = blk_aio_discard(s->qdev.conf.blk,
+                                       sector_num * (s->qdev.blocksize / 512),
+                                       nb_sectors * (s->qdev.blocksize / 512),
+                                       scsi_unmap_complete, data);
         data->count--;
         data->inbuf += 16;
         return;
@@ -1608,7 +1612,7 @@ static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
         goto invalid_param_len;
     }
 
-    if (bdrv_is_read_only(s->qdev.conf.bs)) {
+    if (blk_is_read_only(s->qdev.conf.blk)) {
         scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
         return;
     }
@@ -1647,7 +1651,7 @@ static void scsi_write_same_complete(void *opaque, int ret)
 
     assert(r->req.aiocb != NULL);
     r->req.aiocb = NULL;
-    bdrv_acct_done(s->qdev.conf.bs, &r->acct);
+    blk_acct_done(s->qdev.conf.blk, &r->acct);
     if (r->req.io_canceled) {
         goto done;
     }
@@ -1662,10 +1666,11 @@ static void scsi_write_same_complete(void *opaque, int ret)
     data->sector += data->iov.iov_len / 512;
     data->iov.iov_len = MIN(data->nb_sectors * 512, data->iov.iov_len);
     if (data->iov.iov_len) {
-        bdrv_acct_start(s->qdev.conf.bs, &r->acct, data->iov.iov_len, BDRV_ACCT_WRITE);
-        r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, data->sector,
-                                       &data->qiov, data->iov.iov_len / 512,
-                                       scsi_write_same_complete, data);
+        blk_acct_start(s->qdev.conf.blk, &r->acct, data->iov.iov_len,
+                       BDRV_ACCT_WRITE);
+        r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector,
+                                      &data->qiov, data->iov.iov_len / 512,
+                                      scsi_write_same_complete, data);
         return;
     }
 
@@ -1694,7 +1699,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
         return;
     }
 
-    if (bdrv_is_read_only(s->qdev.conf.bs)) {
+    if (blk_is_read_only(s->qdev.conf.blk)) {
         scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
         return;
     }
@@ -1708,12 +1713,12 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
 
         /* The request is used as the AIO opaque value, so add a ref.  */
         scsi_req_ref(&r->req);
-        bdrv_acct_start(s->qdev.conf.bs, &r->acct, nb_sectors * s->qdev.blocksize,
-                        BDRV_ACCT_WRITE);
-        r->req.aiocb = bdrv_aio_write_zeroes(s->qdev.conf.bs,
-                                             r->req.cmd.lba * (s->qdev.blocksize / 512),
-                                             nb_sectors * (s->qdev.blocksize / 512),
-                                             flags, scsi_aio_complete, r);
+        blk_acct_start(s->qdev.conf.blk, &r->acct,
+                       nb_sectors * s->qdev.blocksize, BDRV_ACCT_WRITE);
+        r->req.aiocb = blk_aio_write_zeroes(s->qdev.conf.blk,
+                                r->req.cmd.lba * (s->qdev.blocksize / 512),
+                                nb_sectors * (s->qdev.blocksize / 512),
+                                flags, scsi_aio_complete, r);
         return;
     }
 
@@ -1722,7 +1727,8 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
     data->sector = r->req.cmd.lba * (s->qdev.blocksize / 512);
     data->nb_sectors = nb_sectors * (s->qdev.blocksize / 512);
     data->iov.iov_len = MIN(data->nb_sectors * 512, SCSI_WRITE_SAME_MAX);
-    data->iov.iov_base = buf = qemu_blockalign(s->qdev.conf.bs, data->iov.iov_len);
+    data->iov.iov_base = buf = blk_blockalign(s->qdev.conf.blk,
+                                              data->iov.iov_len);
     qemu_iovec_init_external(&data->qiov, &data->iov, 1);
 
     for (i = 0; i < data->iov.iov_len; i += s->qdev.blocksize) {
@@ -1730,10 +1736,11 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
     }
 
     scsi_req_ref(&r->req);
-    bdrv_acct_start(s->qdev.conf.bs, &r->acct, data->iov.iov_len, BDRV_ACCT_WRITE);
-    r->req.aiocb = bdrv_aio_writev(s->qdev.conf.bs, data->sector,
-                                   &data->qiov, data->iov.iov_len / 512,
-                                   scsi_write_same_complete, data);
+    blk_acct_start(s->qdev.conf.blk, &r->acct, data->iov.iov_len,
+                   BDRV_ACCT_WRITE);
+    r->req.aiocb = blk_aio_writev(s->qdev.conf.blk, data->sector,
+                                  &data->qiov, data->iov.iov_len / 512,
+                                  scsi_write_same_complete, data);
 }
 
 static void scsi_disk_emulate_write_data(SCSIRequest *req)
@@ -1802,7 +1809,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
         break;
 
     default:
-        if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
+        if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) {
             scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
             return 0;
         }
@@ -1823,7 +1830,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
     r->buflen = MAX(4096, req->cmd.xfer);
 
     if (!r->iov.iov_base) {
-        r->iov.iov_base = qemu_blockalign(s->qdev.conf.bs, r->buflen);
+        r->iov.iov_base = blk_blockalign(s->qdev.conf.blk, r->buflen);
     }
 
     buflen = req->cmd.xfer;
@@ -1831,7 +1838,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
     memset(outbuf, 0, r->buflen);
     switch (req->cmd.buf[0]) {
     case TEST_UNIT_READY:
-        assert(!s->tray_open && bdrv_is_inserted(s->qdev.conf.bs));
+        assert(!s->tray_open && blk_is_inserted(s->qdev.conf.blk));
         break;
     case INQUIRY:
         buflen = scsi_disk_emulate_inquiry(req, outbuf);
@@ -1879,12 +1886,12 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
         break;
     case ALLOW_MEDIUM_REMOVAL:
         s->tray_locked = req->cmd.buf[4] & 1;
-        bdrv_lock_medium(s->qdev.conf.bs, req->cmd.buf[4] & 1);
+        blk_lock_medium(s->qdev.conf.blk, req->cmd.buf[4] & 1);
         break;
     case READ_CAPACITY_10:
         /* The normal LEN field for this command is zero.  */
         memset(outbuf, 0, 8);
-        bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
+        blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
         if (!nb_sectors) {
             scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
             return 0;
@@ -1953,7 +1960,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
         if ((req->cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) {
             DPRINTF("SAI READ CAPACITY(16)\n");
             memset(outbuf, 0, req->cmd.xfer);
-            bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
+            blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
             if (!nb_sectors) {
                 scsi_check_condition(r, SENSE_CODE(LUN_NOT_READY));
                 return 0;
@@ -1994,8 +2001,8 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
     case SYNCHRONIZE_CACHE:
         /* The request is used as the AIO opaque value, so add a ref.  */
         scsi_req_ref(&r->req);
-        bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH);
-        r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_aio_complete, r);
+        blk_acct_start(s->qdev.conf.blk, &r->acct, 0, BDRV_ACCT_FLUSH);
+        r->req.aiocb = blk_aio_flush(s->qdev.conf.blk, scsi_aio_complete, r);
         return 0;
     case SEEK_10:
         DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
@@ -2069,7 +2076,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
 
     command = buf[0];
 
-    if (s->tray_open || !bdrv_is_inserted(s->qdev.conf.bs)) {
+    if (s->tray_open || !blk_is_inserted(s->qdev.conf.blk)) {
         scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
         return 0;
     }
@@ -2097,7 +2104,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
     case WRITE_VERIFY_10:
     case WRITE_VERIFY_12:
     case WRITE_VERIFY_16:
-        if (bdrv_is_read_only(s->qdev.conf.bs)) {
+        if (blk_is_read_only(s->qdev.conf.blk)) {
             scsi_check_condition(r, SENSE_CODE(WRITE_PROTECTED));
             return 0;
         }
@@ -2140,7 +2147,7 @@ static void scsi_disk_reset(DeviceState *dev)
 
     scsi_device_purge_requests(&s->qdev, SENSE_CODE(RESET));
 
-    bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
+    blk_get_geometry(s->qdev.conf.blk, &nb_sectors);
     nb_sectors /= s->qdev.blocksize / 512;
     if (nb_sectors) {
         nb_sectors--;
@@ -2156,7 +2163,7 @@ static void scsi_unrealize(SCSIDevice *dev, Error **errp)
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
 
     scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
-    blockdev_mark_auto_del(s->qdev.conf.bs);
+    blockdev_mark_auto_del(s->qdev.conf.blk);
 }
 
 static void scsi_disk_resize_cb(void *opaque)
@@ -2239,13 +2246,13 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
     SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
     Error *err = NULL;
 
-    if (!s->qdev.conf.bs) {
+    if (!s->qdev.conf.blk) {
         error_setg(errp, "drive property not set");
         return;
     }
 
     if (!(s->features & (1 << SCSI_DISK_F_REMOVABLE)) &&
-        !bdrv_is_inserted(s->qdev.conf.bs)) {
+        !blk_is_inserted(s->qdev.conf.blk)) {
         error_setg(errp, "Device needs media, but drive is empty");
         return;
     }
@@ -2271,20 +2278,20 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
         s->vendor = g_strdup("QEMU");
     }
 
-    if (bdrv_is_sg(s->qdev.conf.bs)) {
+    if (blk_is_sg(s->qdev.conf.blk)) {
         error_setg(errp, "unwanted /dev/sg*");
         return;
     }
 
     if ((s->features & (1 << SCSI_DISK_F_REMOVABLE)) &&
             !(s->features & (1 << SCSI_DISK_F_NO_REMOVABLE_DEVOPS))) {
-        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_removable_block_ops, s);
+        blk_set_dev_ops(s->qdev.conf.blk, &scsi_disk_removable_block_ops, s);
     } else {
-        bdrv_set_dev_ops(s->qdev.conf.bs, &scsi_disk_block_ops, s);
+        blk_set_dev_ops(s->qdev.conf.blk, &scsi_disk_block_ops, s);
     }
-    bdrv_set_guest_block_size(s->qdev.conf.bs, s->qdev.blocksize);
+    blk_set_guest_block_size(s->qdev.conf.blk, s->qdev.blocksize);
 
-    bdrv_iostatus_enable(s->qdev.conf.bs);
+    blk_iostatus_enable(s->qdev.conf.blk);
     add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
 }
 
@@ -2316,14 +2323,14 @@ static void scsi_disk_realize(SCSIDevice *dev, Error **errp)
     DriveInfo *dinfo;
     Error *local_err = NULL;
 
-    if (!dev->conf.bs) {
+    if (!dev->conf.blk) {
         scsi_realize(dev, &local_err);
         assert(local_err);
         error_propagate(errp, local_err);
         return;
     }
 
-    dinfo = drive_get_by_blockdev(dev->conf.bs);
+    dinfo = blk_legacy_dinfo(dev->conf.blk);
     if (dinfo->media_cd) {
         scsi_cd_realize(dev, errp);
     } else {
@@ -2425,7 +2432,6 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
 #ifdef __linux__
 static int get_device_type(SCSIDiskState *s)
 {
-    BlockDriverState *bdrv = s->qdev.conf.bs;
     uint8_t cmd[16];
     uint8_t buf[36];
     uint8_t sensebuf[8];
@@ -2448,7 +2454,7 @@ static int get_device_type(SCSIDiskState *s)
     io_header.sbp = sensebuf;
     io_header.timeout = 6000; /* XXX */
 
-    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
+    ret = blk_ioctl(s->qdev.conf.blk, SG_IO, &io_header);
     if (ret < 0 || io_header.driver_status || io_header.host_status) {
         return -1;
     }
@@ -2465,13 +2471,13 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp)
     int sg_version;
     int rc;
 
-    if (!s->qdev.conf.bs) {
+    if (!s->qdev.conf.blk) {
         error_setg(errp, "drive property not set");
         return;
     }
 
     /* check we are using a driver managing SG_IO (version 3 and after) */
-    rc = bdrv_ioctl(s->qdev.conf.bs, SG_GET_VERSION_NUM, &sg_version);
+    rc = blk_ioctl(s->qdev.conf.blk, SG_GET_VERSION_NUM, &sg_version);
     if (rc < 0) {
         error_setg(errp, "cannot get SG_IO version number: %s.  "
                      "Is this a SCSI device?",
@@ -2530,7 +2536,7 @@ static bool scsi_block_is_passthrough(SCSIDiskState *s, uint8_t *buf)
          * ones (such as WRITE SAME or EXTENDED COPY, etc.).  So, without
          * O_DIRECT everything must go through SG_IO.
          */
-        if (!(bdrv_get_flags(s->qdev.conf.bs) & BDRV_O_NOCACHE)) {
+        if (!(blk_get_flags(s->qdev.conf.blk) & BDRV_O_NOCACHE)) {
             break;
         }
 
@@ -2679,7 +2685,7 @@ static const TypeInfo scsi_cd_info = {
 
 #ifdef __linux__
 static Property scsi_block_properties[] = {
-    DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.bs),
+    DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk),
     DEFINE_PROP_INT32("bootindex", SCSIDiskState, qdev.conf.bootindex, -1),
     DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
index 5301886..ff2f920 100644
--- a/hw/scsi/scsi-generic.c
+++ b/hw/scsi/scsi-generic.c
@@ -14,6 +14,7 @@
 #include "qemu-common.h"
 #include "qemu/error-report.h"
 #include "hw/scsi/scsi.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 
 #ifdef __linux__
@@ -145,17 +146,17 @@ static void scsi_cancel_io(SCSIRequest *req)
 
     DPRINTF("Cancel tag=0x%x\n", req->tag);
     if (r->req.aiocb) {
-        bdrv_aio_cancel(r->req.aiocb);
+        blk_aio_cancel(r->req.aiocb);
 
         /* This reference was left in by scsi_*_data.  We take ownership of
-         * it independent of whether bdrv_aio_cancel completes the request
+         * it independent of whether blk_aio_cancel completes the request
          * or not.  */
         scsi_req_unref(&r->req);
     }
     r->req.aiocb = NULL;
 }
 
-static int execute_command(BlockDriverState *bdrv,
+static int execute_command(BlockBackend *blk,
                            SCSIGenericReq *r, int direction,
                            BlockCompletionFunc *complete)
 {
@@ -171,7 +172,7 @@ static int execute_command(BlockDriverState *bdrv,
     r->io_header.usr_ptr = r;
     r->io_header.flags |= SG_FLAG_DIRECT_IO;
 
-    r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r);
+    r->req.aiocb = blk_aio_ioctl(blk, SG_IO, &r->io_header, complete, r);
     if (r->req.aiocb == NULL) {
         return -EIO;
     }
@@ -208,7 +209,7 @@ static void scsi_read_complete(void * opaque, int ret)
             s->blocksize = ldl_be_p(&r->buf[8]);
             s->max_lba = ldq_be_p(&r->buf[0]);
         }
-        bdrv_set_guest_block_size(s->conf.bs, s->blocksize);
+        blk_set_guest_block_size(s->conf.blk, s->blocksize);
 
         scsi_req_data(&r->req, len);
         if (!r->req.io_canceled) {
@@ -233,7 +234,8 @@ static void scsi_read_data(SCSIRequest *req)
         return;
     }
 
-    ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete);
+    ret = execute_command(s->conf.blk, r, SG_DXFER_FROM_DEV,
+                          scsi_read_complete);
     if (ret < 0) {
         scsi_command_complete(r, ret);
     }
@@ -278,7 +280,7 @@ static void scsi_write_data(SCSIRequest *req)
 
     /* The request is used as the AIO opaque value, so add a ref.  */
     scsi_req_ref(&r->req);
-    ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete);
+    ret = execute_command(s->conf.blk, r, SG_DXFER_TO_DEV, scsi_write_complete);
     if (ret < 0) {
         scsi_command_complete(r, ret);
     }
@@ -320,7 +322,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
         r->buf = NULL;
         /* The request is used as the AIO opaque value, so add a ref.  */
         scsi_req_ref(&r->req);
-        ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete);
+        ret = execute_command(s->conf.blk, r, SG_DXFER_NONE,
+                              scsi_command_complete);
         if (ret < 0) {
             scsi_command_complete(r, ret);
             return 0;
@@ -345,7 +348,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
     }
 }
 
-static int get_stream_blocksize(BlockDriverState *bdrv)
+static int get_stream_blocksize(BlockBackend *blk)
 {
     uint8_t cmd[6];
     uint8_t buf[12];
@@ -369,7 +372,7 @@ static int get_stream_blocksize(BlockDriverState *bdrv)
     io_header.sbp = sensebuf;
     io_header.timeout = 6000; /* XXX */
 
-    ret = bdrv_ioctl(bdrv, SG_IO, &io_header);
+    ret = blk_ioctl(blk, SG_IO, &io_header);
     if (ret < 0 || io_header.driver_status || io_header.host_status) {
         return -1;
     }
@@ -386,7 +389,7 @@ static void scsi_generic_reset(DeviceState *dev)
 static void scsi_unrealize(SCSIDevice *s, Error **errp)
 {
     scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
-    blockdev_mark_auto_del(s->conf.bs);
+    blockdev_mark_auto_del(s->conf.blk);
 }
 
 static void scsi_generic_realize(SCSIDevice *s, Error **errp)
@@ -395,22 +398,22 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
     int sg_version;
     struct sg_scsi_id scsiid;
 
-    if (!s->conf.bs) {
+    if (!s->conf.blk) {
         error_setg(errp, "drive property not set");
         return;
     }
 
-    if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
+    if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
         error_setg(errp, "Device doesn't support drive option werror");
         return;
     }
-    if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) {
+    if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
         error_setg(errp, "Device doesn't support drive option rerror");
         return;
     }
 
     /* check we are using a driver managing SG_IO (version 3 and after */
-    rc = bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version);
+    rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
     if (rc < 0) {
         error_setg(errp, "cannot get SG_IO version number: %s.  "
                          "Is this a SCSI device?",
@@ -423,7 +426,7 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
     }
 
     /* get LUN of the /dev/sg? */
-    if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) {
+    if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
         error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
         return;
     }
@@ -437,7 +440,7 @@ static void scsi_generic_realize(SCSIDevice *s, Error **errp)
 
     switch (s->type) {
     case TYPE_TAPE:
-        s->blocksize = get_stream_blocksize(s->conf.bs);
+        s->blocksize = get_stream_blocksize(s->conf.blk);
         if (s->blocksize == -1) {
             s->blocksize = 0;
         }
@@ -481,7 +484,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
 }
 
 static Property scsi_generic_properties[] = {
-    DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs),
+    DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.blk),
     DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1),
     DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 501aa3a..9661eaf 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -253,16 +253,16 @@ static int milkymist_memcard_init(SysBusDevice *dev)
 {
     MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
     DriveInfo *dinfo;
-    BlockDriverState *bs;
+    BlockBackend *blk;
 
     dinfo = drive_get_next(IF_SD);
-    bs = dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL;
-    s->card = sd_init(bs, false);
+    blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
+    s->card = sd_init(blk, false);
     if (s->card == NULL) {
         return -1;
     }
 
-    s->enabled = bs && bdrv_is_inserted(bs);
+    s->enabled = blk && blk_is_inserted(blk);
 
     memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s,
             "milkymist-memcard", R_MAX * 4);
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index 6c92149..86c477d 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -574,7 +574,7 @@ static void omap_mmc_cover_cb(void *opaque, int line, int level)
 
 struct omap_mmc_s *omap_mmc_init(hwaddr base,
                 MemoryRegion *sysmem,
-                BlockDriverState *bd,
+                BlockBackend *blk,
                 qemu_irq irq, qemu_irq dma[], omap_clk clk)
 {
     struct omap_mmc_s *s = (struct omap_mmc_s *)
@@ -592,7 +592,7 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base,
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     /* Instantiate the storage */
-    s->card = sd_init(bd, false);
+    s->card = sd_init(blk, false);
     if (s->card == NULL) {
         exit(1);
     }
@@ -601,7 +601,7 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base,
 }
 
 struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
-                BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
+                BlockBackend *blk, qemu_irq irq, qemu_irq dma[],
                 omap_clk fclk, omap_clk iclk)
 {
     struct omap_mmc_s *s = (struct omap_mmc_s *)
@@ -620,7 +620,7 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
     omap_l4_attach(ta, 0, &s->iomem);
 
     /* Instantiate the storage */
-    s->card = sd_init(bd, false);
+    s->card = sd_init(blk, false);
     if (s->card == NULL) {
         exit(1);
     }
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 0501d40..e704b6e 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -491,7 +491,7 @@ static int pl181_init(SysBusDevice *sbd)
     sysbus_init_irq(sbd, &s->irq[1]);
     qdev_init_gpio_out(dev, s->cardstatus, 2);
     dinfo = drive_get_next(IF_SD);
-    s->card = sd_init(dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL, false);
+    s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
     if (s->card == NULL) {
         return -1;
     }
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index b9d8b1a..ac3ab39 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -523,7 +523,7 @@ static int pxa2xx_mmci_load(QEMUFile *f, void *opaque, int version_id)
 
 PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
                 hwaddr base,
-                BlockDriverState *bd, qemu_irq irq,
+                BlockBackend *blk, qemu_irq irq,
                 qemu_irq rx_dma, qemu_irq tx_dma)
 {
     PXA2xxMMCIState *s;
@@ -538,7 +538,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
     memory_region_add_subregion(sysmem, base, &s->iomem);
 
     /* Instantiate the actual storage */
-    s->card = sd_init(bd, false);
+    s->card = sd_init(blk, false);
     if (s->card == NULL) {
         exit(1);
     }
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 5efe8c1..f955265 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -30,7 +30,7 @@
  */
 
 #include "hw/hw.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "hw/sd.h"
 #include "qemu/bitmap.h"
 
@@ -110,7 +110,7 @@ struct SDState {
     uint8_t data[512];
     qemu_irq readonly_cb;
     qemu_irq inserted_cb;
-    BlockDriverState *bdrv;
+    BlockBackend *blk;
     uint8_t *buf;
 
     bool enable;
@@ -389,13 +389,13 @@ static inline uint64_t sd_addr_to_wpnum(uint64_t addr)
     return addr >> (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT);
 }
 
-static void sd_reset(SDState *sd, BlockDriverState *bdrv)
+static void sd_reset(SDState *sd, BlockBackend *blk)
 {
     uint64_t size;
     uint64_t sect;
 
-    if (bdrv) {
-        bdrv_get_geometry(bdrv, &sect);
+    if (blk) {
+        blk_get_geometry(blk, &sect);
     } else {
         sect = 0;
     }
@@ -412,11 +412,11 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
     sd_set_cardstatus(sd);
     sd_set_sdstatus(sd);
 
-    sd->bdrv = bdrv;
+    sd->blk = blk;
 
     if (sd->wp_groups)
         g_free(sd->wp_groups);
-    sd->wp_switch = bdrv ? bdrv_is_read_only(bdrv) : false;
+    sd->wp_switch = blk ? blk_is_read_only(blk) : false;
     sd->wpgrps_size = sect;
     sd->wp_groups = bitmap_new(sd->wpgrps_size);
     memset(sd->function_group, 0, sizeof(sd->function_group));
@@ -432,9 +432,9 @@ static void sd_cardchange(void *opaque, bool load)
 {
     SDState *sd = opaque;
 
-    qemu_set_irq(sd->inserted_cb, bdrv_is_inserted(sd->bdrv));
-    if (bdrv_is_inserted(sd->bdrv)) {
-        sd_reset(sd, sd->bdrv);
+    qemu_set_irq(sd->inserted_cb, blk_is_inserted(sd->blk));
+    if (blk_is_inserted(sd->blk)) {
+        sd_reset(sd, sd->blk);
         qemu_set_irq(sd->readonly_cb, sd->wp_switch);
     }
 }
@@ -479,23 +479,23 @@ static const VMStateDescription sd_vmstate = {
    whether card should be in SSI or MMC/SD mode.  It is also up to the
    board to ensure that ssi transfers only occur when the chip select
    is asserted.  */
-SDState *sd_init(BlockDriverState *bs, bool is_spi)
+SDState *sd_init(BlockBackend *blk, bool is_spi)
 {
     SDState *sd;
 
-    if (bs && bdrv_is_read_only(bs)) {
+    if (blk && blk_is_read_only(blk)) {
         fprintf(stderr, "sd_init: Cannot use read-only drive\n");
         return NULL;
     }
 
     sd = (SDState *) g_malloc0(sizeof(SDState));
-    sd->buf = qemu_blockalign(bs, 512);
+    sd->buf = blk_blockalign(blk, 512);
     sd->spi = is_spi;
     sd->enable = true;
-    sd_reset(sd, bs);
-    if (sd->bdrv) {
-        bdrv_attach_dev_nofail(sd->bdrv, sd);
-        bdrv_set_dev_ops(sd->bdrv, &sd_block_ops, sd);
+    sd_reset(sd, blk);
+    if (sd->blk) {
+        blk_attach_dev_nofail(sd->blk, sd);
+        blk_set_dev_ops(sd->blk, &sd_block_ops, sd);
     }
     vmstate_register(NULL, -1, &sd_vmstate, sd);
     return sd;
@@ -505,8 +505,8 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert)
 {
     sd->readonly_cb = readonly;
     sd->inserted_cb = insert;
-    qemu_set_irq(readonly, sd->bdrv ? bdrv_is_read_only(sd->bdrv) : 0);
-    qemu_set_irq(insert, sd->bdrv ? bdrv_is_inserted(sd->bdrv) : 0);
+    qemu_set_irq(readonly, sd->blk ? blk_is_read_only(sd->blk) : 0);
+    qemu_set_irq(insert, sd->blk ? blk_is_inserted(sd->blk) : 0);
 }
 
 static void sd_erase(SDState *sd)
@@ -680,7 +680,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
 
         default:
             sd->state = sd_idle_state;
-            sd_reset(sd, sd->bdrv);
+            sd_reset(sd, sd->blk);
             return sd->spi ? sd_r1 : sd_r0;
         }
         break;
@@ -1347,7 +1347,7 @@ int sd_do_command(SDState *sd, SDRequest *req,
     sd_rsp_type_t rtype;
     int rsplen;
 
-    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) {
+    if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable) {
         return 0;
     }
 
@@ -1456,7 +1456,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
 
     DPRINTF("sd_blk_read: addr = 0x%08llx, len = %d\n",
             (unsigned long long) addr, len);
-    if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) < 0) {
+    if (!sd->blk || blk_read(sd->blk, addr >> 9, sd->buf, 1) < 0) {
         fprintf(stderr, "sd_blk_read: read error on host side\n");
         return;
     }
@@ -1464,7 +1464,7 @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
     if (end > (addr & ~511) + 512) {
         memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511));
 
-        if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) < 0) {
+        if (blk_read(sd->blk, end >> 9, sd->buf, 1) < 0) {
             fprintf(stderr, "sd_blk_read: read error on host side\n");
             return;
         }
@@ -1478,29 +1478,29 @@ static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
     uint64_t end = addr + len;
 
     if ((addr & 511) || len < 512)
-        if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) < 0) {
+        if (!sd->blk || blk_read(sd->blk, addr >> 9, sd->buf, 1) < 0) {
             fprintf(stderr, "sd_blk_write: read error on host side\n");
             return;
         }
 
     if (end > (addr & ~511) + 512) {
         memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511));
-        if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) < 0) {
+        if (blk_write(sd->blk, addr >> 9, sd->buf, 1) < 0) {
             fprintf(stderr, "sd_blk_write: write error on host side\n");
             return;
         }
 
-        if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) < 0) {
+        if (blk_read(sd->blk, end >> 9, sd->buf, 1) < 0) {
             fprintf(stderr, "sd_blk_write: read error on host side\n");
             return;
         }
         memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511);
-        if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) < 0) {
+        if (blk_write(sd->blk, end >> 9, sd->buf, 1) < 0) {
             fprintf(stderr, "sd_blk_write: write error on host side\n");
         }
     } else {
         memcpy(sd->buf + (addr & 511), sd->data, len);
-        if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) < 0) {
+        if (!sd->blk || blk_write(sd->blk, addr >> 9, sd->buf, 1) < 0) {
             fprintf(stderr, "sd_blk_write: write error on host side\n");
         }
     }
@@ -1515,7 +1515,7 @@ void sd_write_data(SDState *sd, uint8_t value)
 {
     int i;
 
-    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable)
+    if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable)
         return;
 
     if (sd->state != sd_receivingdata_state) {
@@ -1641,7 +1641,7 @@ uint8_t sd_read_data(SDState *sd)
     uint8_t ret;
     int io_len;
 
-    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable)
+    if (!sd->blk || !blk_is_inserted(sd->blk) || !sd->enable)
         return 0x00;
 
     if (sd->state != sd_sendingdata_state) {
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 0b7d754..b380050 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1166,7 +1166,7 @@ static void sdhci_initfn(Object *obj)
     DriveInfo *di;
 
     di = drive_get_next(IF_SD);
-    s->card = sd_init(di ? blk_bs(blk_by_legacy_dinfo(di)) : NULL, false);
+    s->card = sd_init(di ? blk_by_legacy_dinfo(di) : NULL, false);
     if (s->card == NULL) {
         exit(1);
     }
diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
index 6ae99e4..a71fbca 100644
--- a/hw/sd/ssi-sd.c
+++ b/hw/sd/ssi-sd.c
@@ -256,7 +256,7 @@ static int ssi_sd_init(SSISlave *d)
 
     s->mode = SSI_SD_CMD;
     dinfo = drive_get_next(IF_SD);
-    s->sd = sd_init(dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL, true);
+    s->sd = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, true);
     if (s->sd == NULL) {
         return -1;
     }
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index d652619..890a8eb 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -37,7 +37,6 @@
 #include "hw/usb.h"
 #include "hw/block/flash.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "exec/address-spaces.h"
 
 #define FLASH_BASE 0x00000000
@@ -291,7 +290,7 @@ static void r2d_init(MachineState *machine)
     /* onboard flash memory */
     dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
-                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
+                          dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
                           (16 * 1024), FLASH_SIZE >> 16,
                           1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
                           0x555, 0x2aa, 0);
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 67e3663..b6bc916 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -40,7 +40,7 @@
 #include "hw/empty_slot.h"
 #include "hw/loader.h"
 #include "elf.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "trace.h"
 
 /*
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index b9f3bee..6aa1bd4 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -38,7 +38,7 @@
 #include "hw/ide.h"
 #include "hw/loader.h"
 #include "elf.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "exec/address-spaces.h"
 
 //#define DEBUG_IRQ
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index 82747ee..c0e7cd7 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -21,7 +21,7 @@
 
 #include "sysemu/tpm_backend.h"
 #include "tpm_int.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 #include "exec/address-spaces.h"
 #include "hw/hw.h"
 #include "hw/i386/pc.h"
diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c
index f412e27..dde1f6f 100644
--- a/hw/tricore/tricore_testboard.c
+++ b/hw/tricore/tricore_testboard.c
@@ -24,7 +24,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/boards.h"
 #include "hw/loader.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "exec/address-spaces.h"
 #include "hw/block/flash.h"
 #include "elf.h"
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 525f657..8f0aada 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -594,11 +594,11 @@ static const struct SCSIBusInfo usb_msd_scsi_info_bot = {
 static int usb_msd_initfn_storage(USBDevice *dev)
 {
     MSDState *s = DO_UPCAST(MSDState, dev, dev);
-    BlockDriverState *bs = s->conf.bs;
+    BlockBackend *blk = s->conf.blk;
     SCSIDevice *scsi_dev;
     Error *err = NULL;
 
-    if (!bs) {
+    if (!blk) {
         error_report("drive property not set");
         return -1;
     }
@@ -614,14 +614,14 @@ static int usb_msd_initfn_storage(USBDevice *dev)
      *
      * The hack is probably a bad idea.
      */
-    bdrv_detach_dev(bs, &s->dev.qdev);
-    s->conf.bs = NULL;
+    blk_detach_dev(blk, &s->dev.qdev);
+    s->conf.blk = NULL;
 
     usb_desc_create_serial(dev);
     usb_desc_init(dev);
     scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
                  &usb_msd_scsi_info_storage, NULL);
-    scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
+    scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
                                          s->conf.bootindex, dev->serial,
                                          &err);
     if (!scsi_dev) {
@@ -630,9 +630,10 @@ static int usb_msd_initfn_storage(USBDevice *dev)
     s->bus.qbus.allow_hotplug = 0;
     usb_msd_handle_reset(dev);
 
-    if (bdrv_key_required(bs)) {
+    if (bdrv_key_required(blk_bs(blk))) {
         if (cur_mon) {
-            monitor_read_bdrv_key_start(cur_mon, bs, usb_msd_password_cb, s);
+            monitor_read_bdrv_key_start(cur_mon, blk_bs(blk),
+                                        usb_msd_password_cb, s);
             s->dev.auto_attach = 0;
         } else {
             autostart = 0;
@@ -704,7 +705,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
         return NULL;
     }
     if (qdev_prop_set_drive(&dev->qdev, "drive",
-                            blk_bs(blk_by_legacy_dinfo(dinfo))) < 0) {
+                            blk_by_legacy_dinfo(dinfo)) < 0) {
         object_unparent(OBJECT(dev));
         return NULL;
     }
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index ddb5da1..28ddc73 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -29,7 +29,7 @@
 #include "hw/pci/msix.h"
 #include "hw/loader.h"
 #include "sysemu/kvm.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 #include "virtio-pci.h"
 #include "qemu/range.h"
 #include "hw/virtio/virtio-bus.h"
diff --git a/hw/xen/xen_devconfig.c b/hw/xen/xen_devconfig.c
index fa998ef..e138dbb 100644
--- a/hw/xen/xen_devconfig.c
+++ b/hw/xen/xen_devconfig.c
@@ -1,4 +1,5 @@
 #include "hw/xen/xen_backend.h"
+#include "sysemu/block-backend.h"
 #include "sysemu/blockdev.h"
 
 /* ------------------------------------------------------------- */
diff --git a/hw/xenpv/xen_machine_pv.c b/hw/xenpv/xen_machine_pv.c
index 3150064..2e545d2 100644
--- a/hw/xenpv/xen_machine_pv.c
+++ b/hw/xenpv/xen_machine_pv.c
@@ -26,7 +26,7 @@
 #include "hw/boards.h"
 #include "hw/xen/xen_backend.h"
 #include "xen_domainbuild.h"
-#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
 
 static void xen_init_pv(MachineState *machine)
 {
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index 7c4719e..a11bf68 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -36,7 +36,6 @@
 #include "hw/sysbus.h"
 #include "hw/block/flash.h"
 #include "sysemu/block-backend.h"
-#include "sysemu/blockdev.h"
 #include "sysemu/char.h"
 #include "sysemu/device_tree.h"
 #include "qemu/error-report.h"
@@ -230,7 +229,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
     if (dinfo) {
         flash = pflash_cfi01_register(board->flash_base,
                 NULL, "lx60.io.flash", board->flash_size,
-                blk_bs(blk_by_legacy_dinfo(dinfo)),
+                blk_by_legacy_dinfo(dinfo),
                 board->flash_sector_size,
                 board->flash_size / board->flash_sector_size,
                 4, 0x0000, 0x0000, 0x0000, 0x0000, be);
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
index b9655ee..0ad5fb8 100644
--- a/include/hw/arm/omap.h
+++ b/include/hw/arm/omap.h
@@ -755,10 +755,10 @@ void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip);
 struct omap_mmc_s;
 struct omap_mmc_s *omap_mmc_init(hwaddr base,
                 MemoryRegion *sysmem,
-                BlockDriverState *bd,
+                BlockBackend *blk,
                 qemu_irq irq, qemu_irq dma[], omap_clk clk);
 struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta,
-                BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
+                BlockBackend *blk, qemu_irq irq, qemu_irq dma[],
                 omap_clk fclk, omap_clk iclk);
 void omap_mmc_reset(struct omap_mmc_s *s);
 void omap_mmc_handlers(struct omap_mmc_s *s, qemu_irq ro, qemu_irq cover);
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
index c507906..259b852 100644
--- a/include/hw/arm/pxa.h
+++ b/include/hw/arm/pxa.h
@@ -87,7 +87,7 @@ void pxa2xx_lcdc_oritentation(void *opaque, int angle);
 typedef struct PXA2xxMMCIState PXA2xxMMCIState;
 PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
                 hwaddr base,
-                BlockDriverState *bd, qemu_irq irq,
+                BlockBackend *blk, qemu_irq irq,
                 qemu_irq rx_dma, qemu_irq tx_dma);
 void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
                 qemu_irq coverswitch);
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
index 3a01488..c128589 100644
--- a/include/hw/block/block.h
+++ b/include/hw/block/block.h
@@ -17,7 +17,7 @@
 /* Configuration */
 
 typedef struct BlockConf {
-    BlockDriverState *bs;
+    BlockBackend *blk;
     uint16_t physical_block_size;
     uint16_t logical_block_size;
     uint16_t min_io_size;
@@ -42,7 +42,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
 }
 
 #define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \
-    DEFINE_PROP_DRIVE("drive", _state, _conf.bs),                       \
+    DEFINE_PROP_DRIVE("drive", _state, _conf.blk),                      \
     DEFINE_PROP_BLOCKSIZE("logical_block_size", _state,                 \
                           _conf.logical_block_size, 512),               \
     DEFINE_PROP_BLOCKSIZE("physical_block_size", _state,                \
@@ -67,7 +67,7 @@ void blkconf_geometry(BlockConf *conf, int *trans,
 
 /* Hard disk geometry */
 
-void hd_geometry_guess(BlockDriverState *bs,
+void hd_geometry_guess(BlockBackend *blk,
                        uint32_t *pcyls, uint32_t *pheads, uint32_t *psecs,
                        int *ptrans);
 int hd_bios_chs_auto_trans(uint32_t cyls, uint32_t heads, uint32_t secs);
diff --git a/include/hw/block/flash.h b/include/hw/block/flash.h
index 920d759..50ccbbc 100644
--- a/include/hw/block/flash.h
+++ b/include/hw/block/flash.h
@@ -11,7 +11,7 @@ typedef struct pflash_t pflash_t;
 pflash_t *pflash_cfi01_register(hwaddr base,
                                 DeviceState *qdev, const char *name,
                                 hwaddr size,
-                                BlockDriverState *bs,
+                                BlockBackend *blk,
                                 uint32_t sector_len, int nb_blocs, int width,
                                 uint16_t id0, uint16_t id1,
                                 uint16_t id2, uint16_t id3, int be);
@@ -20,7 +20,7 @@ pflash_t *pflash_cfi01_register(hwaddr base,
 pflash_t *pflash_cfi02_register(hwaddr base,
                                 DeviceState *qdev, const char *name,
                                 hwaddr size,
-                                BlockDriverState *bs, uint32_t sector_len,
+                                BlockBackend *blk, uint32_t sector_len,
                                 int nb_blocs, int nb_mappings, int width,
                                 uint16_t id0, uint16_t id1,
                                 uint16_t id2, uint16_t id3,
@@ -30,7 +30,7 @@ pflash_t *pflash_cfi02_register(hwaddr base,
 MemoryRegion *pflash_cfi01_get_memory(pflash_t *fl);
 
 /* nand.c */
-DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id);
+DeviceState *nand_init(BlockBackend *blk, int manf_id, int chip_id);
 void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale,
                   uint8_t ce, uint8_t wp, uint8_t gnd);
 void nand_getpins(DeviceState *dev, int *rb);
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 77fe3a1..e560647 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -141,7 +141,7 @@ extern PropertyInfo qdev_prop_arraylen;
 #define DEFINE_PROP_VLAN(_n, _s, _f)             \
     DEFINE_PROP(_n, _s, _f, qdev_prop_vlan, NICPeers)
 #define DEFINE_PROP_DRIVE(_n, _s, _f) \
-    DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockDriverState *)
+    DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockBackend *)
 #define DEFINE_PROP_MACADDR(_n, _s, _f)         \
     DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
 #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \
@@ -168,8 +168,10 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
 void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
 void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
 void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
-int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value) QEMU_WARN_UNUSED_RESULT;
-void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value);
+int qdev_prop_set_drive(DeviceState *dev, const char *name,
+                        BlockBackend *value) QEMU_WARN_UNUSED_RESULT;
+void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name,
+                                BlockBackend *value);
 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
 void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
 /* FIXME: Remove opaque pointer properties.  */
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index e3e27cb..444e450 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -2,7 +2,7 @@
 #define QEMU_HW_SCSI_H
 
 #include "hw/qdev.h"
-#include "block/block.h"
+#include "qemu/typedefs.h"
 #include "hw/block/block.h"
 #include "sysemu/sysemu.h"
 
@@ -167,7 +167,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
     return DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus);
 }
 
-SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
+SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
                                       int unit, bool removable, int bootindex,
                                       const char *serial, Error **errp);
 void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp);
diff --git a/include/hw/sd.h b/include/hw/sd.h
index d9b97e4..79adb5b 100644
--- a/include/hw/sd.h
+++ b/include/hw/sd.h
@@ -68,7 +68,7 @@ typedef struct {
 
 typedef struct SDState SDState;
 
-SDState *sd_init(BlockDriverState *bs, bool is_spi);
+SDState *sd_init(BlockBackend *bs, bool is_spi);
 int sd_do_command(SDState *sd, SDRequest *req,
                   uint8_t *response);
 void sd_write_data(SDState *sd, uint8_t value);
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index b30237f..f1b46e7 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -17,7 +17,7 @@
 #include "hw/virtio/virtio.h"
 #include "hw/block/block.h"
 #include "sysemu/iothread.h"
-#include "block/block.h"
+#include "sysemu/block-backend.h"
 
 #define TYPE_VIRTIO_BLK "virtio-blk-device"
 #define VIRTIO_BLK(obj) \
@@ -120,7 +120,7 @@ struct VirtIOBlockDataPlane;
 struct VirtIOBlockReq;
 typedef struct VirtIOBlock {
     VirtIODevice parent_obj;
-    BlockDriverState *bs;
+    BlockBackend *blk;
     VirtQueue *vq;
     void *rq;
     QEMUBH *bh;
@@ -160,6 +160,6 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
 
 void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb);
 
-void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb);
+void virtio_submit_multiwrite(BlockBackend *blk, MultiReqBuffer *mrb);
 
 #endif
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 198da2e..8b3f352 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -37,6 +37,7 @@ typedef struct HCIInfo HCIInfo;
 typedef struct AudioState AudioState;
 typedef struct BlockBackend BlockBackend;
 typedef struct BlockDriverState BlockDriverState;
+typedef struct BlockBackend BlockBackend;
 typedef struct DriveInfo DriveInfo;
 typedef struct DisplayState DisplayState;
 typedef struct DisplayChangeListener DisplayChangeListener;
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 539b96f..73f9325 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -16,10 +16,20 @@
 #include "qemu/typedefs.h"
 #include "qapi/error.h"
 
+/*
+ * TODO Have to include block/block.h for a bunch of block layer
+ * types.  Unfortunately, this pulls in the whole BlockDriverState
+ * API, which we don't want used by many BlockBackend users.  Some of
+ * the types belong here, and the rest should be split into a common
+ * header and one for the BlockDriverState API.
+ */
+#include "block/block.h"
+
 BlockBackend *blk_new(const char *name, Error **errp);
 BlockBackend *blk_new_with_bs(const char *name, Error **errp);
 void blk_ref(BlockBackend *blk);
 void blk_unref(BlockBackend *blk);
+void blk_make_anon(BlockBackend *blk);
 const char *blk_name(BlockBackend *blk);
 BlockBackend *blk_by_name(const char *name);
 BlockBackend *blk_next(BlockBackend *blk);
@@ -28,4 +38,72 @@ void blk_attach_bs(BlockBackend *blk, BlockDriverState *bs);
 BlockDriverState *blk_detach_bs(BlockBackend *blk);
 BlockDriverState *blk_bs(BlockBackend *blk);
 
+void blk_iostatus_enable(BlockBackend *blk);
+int blk_attach_dev(BlockBackend *blk, void *dev);
+void blk_attach_dev_nofail(BlockBackend *blk, void *dev);
+void blk_detach_dev(BlockBackend *blk, void *dev);
+void *blk_get_attached_dev(BlockBackend *blk);
+void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque);
+int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
+             int nb_sectors);
+int blk_read_unthrottled(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
+                         int nb_sectors);
+int blk_write(BlockBackend *blk, int64_t sector_num, const uint8_t *buf,
+              int nb_sectors);
+BlockAIOCB *blk_aio_write_zeroes(BlockBackend *blk, int64_t sector_num,
+                                 int nb_sectors, BdrvRequestFlags flags,
+                                 BlockCompletionFunc *cb, void *opaque);
+int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int count);
+int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count);
+int64_t blk_getlength(BlockBackend *blk);
+void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr);
+BlockAIOCB *blk_aio_readv(BlockBackend *blk, int64_t sector_num,
+                          QEMUIOVector *iov, int nb_sectors,
+                          BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num,
+                           QEMUIOVector *iov, int nb_sectors,
+                           BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *blk_aio_flush(BlockBackend *blk,
+                          BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *blk_aio_discard(BlockBackend *blk,
+                            int64_t sector_num, int nb_sectors,
+                            BlockCompletionFunc *cb, void *opaque);
+void blk_aio_cancel(BlockAIOCB *acb);
+int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs);
+int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
+BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
+                          BlockCompletionFunc *cb, void *opaque);
+int blk_flush(BlockBackend *blk);
+int blk_flush_all(void);
+void blk_drain_all(void);
+BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read);
+BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
+                                      int error);
+void blk_error_action(BlockBackend *blk, BlockErrorAction action,
+                      bool is_read, int error);
+int blk_is_read_only(BlockBackend *blk);
+int blk_is_sg(BlockBackend *blk);
+int blk_enable_write_cache(BlockBackend *blk);
+void blk_set_enable_write_cache(BlockBackend *blk, bool wce);
+int blk_is_inserted(BlockBackend *blk);
+void blk_lock_medium(BlockBackend *blk, bool locked);
+void blk_eject(BlockBackend *blk, bool eject_flag);
+int blk_get_flags(BlockBackend *blk);
+void blk_set_guest_block_size(BlockBackend *blk, int align);
+void *blk_blockalign(BlockBackend *blk, size_t size);
+bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp);
+void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason);
+void blk_op_block_all(BlockBackend *blk, Error *reason);
+void blk_op_unblock_all(BlockBackend *blk, Error *reason);
+void blk_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
+                    int64_t bytes, enum BlockAcctType type);
+void blk_acct_done(BlockBackend *blk, BlockAcctCookie *cookie);
+AioContext *blk_get_aio_context(BlockBackend *blk);
+void blk_set_aio_context(BlockBackend *blk, AioContext *new_context);
+void blk_io_plug(BlockBackend *blk);
+void blk_io_unplug(BlockBackend *blk);
+
+void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
+                  BlockCompletionFunc *cb, void *opaque);
+
 #endif
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 75f6ac6..f66b89a 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -14,8 +14,8 @@
 #include "qapi/error.h"
 #include "qemu/queue.h"
 
-void blockdev_mark_auto_del(BlockDriverState *bs);
-void blockdev_auto_del(BlockDriverState *bs);
+void blockdev_mark_auto_del(BlockBackend *blk);
+void blockdev_auto_del(BlockBackend *blk);
 
 typedef enum {
     IF_DEFAULT = -1,            /* for use with drive_add() only */
@@ -52,7 +52,6 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
 DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
 int drive_get_max_bus(BlockInterfaceType type);
 DriveInfo *drive_get_next(BlockInterfaceType type);
-DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
 
 QemuOpts *drive_def(const char *optstr);
 QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index 464f9f7..ca055d4 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -196,24 +196,24 @@ void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
 void qemu_sglist_destroy(QEMUSGList *qsg);
 #endif
 
-typedef BlockAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
-                              QEMUIOVector *iov, int nb_sectors,
-                              BlockCompletionFunc *cb, void *opaque);
+typedef BlockAIOCB *DMAIOFunc(BlockBackend *blk, int64_t sector_num,
+                                 QEMUIOVector *iov, int nb_sectors,
+                                 BlockCompletionFunc *cb, void *opaque);
 
-BlockAIOCB *dma_bdrv_io(BlockDriverState *bs,
-                        QEMUSGList *sg, uint64_t sector_num,
-                        DMAIOFunc *io_func, BlockCompletionFunc *cb,
-                        void *opaque, DMADirection dir);
-BlockAIOCB *dma_bdrv_read(BlockDriverState *bs,
+BlockAIOCB *dma_blk_io(BlockBackend *blk,
+                       QEMUSGList *sg, uint64_t sector_num,
+                       DMAIOFunc *io_func, BlockCompletionFunc *cb,
+                       void *opaque, DMADirection dir);
+BlockAIOCB *dma_blk_read(BlockBackend *blk,
+                         QEMUSGList *sg, uint64_t sector,
+                         BlockCompletionFunc *cb, void *opaque);
+BlockAIOCB *dma_blk_write(BlockBackend *blk,
                           QEMUSGList *sg, uint64_t sector,
                           BlockCompletionFunc *cb, void *opaque);
-BlockAIOCB *dma_bdrv_write(BlockDriverState *bs,
-                           QEMUSGList *sg, uint64_t sector,
-                           BlockCompletionFunc *cb, void *opaque);
 uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
 uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
 
-void dma_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie,
+void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
                     QEMUSGList *sg, enum BlockAcctType type);
 
 #endif
diff --git a/trace-events b/trace-events
index 03ac5d2..4891e77 100644
--- a/trace-events
+++ b/trace-events
@@ -196,8 +196,8 @@ fw_cfg_add_file_dupe(void *s, char *name) "%p %s"
 fw_cfg_add_file(void *s, int index, char *name, size_t len) "%p #%d: %s (%zd bytes)"
 
 # hw/block/hd-geometry.c
-hd_geometry_lchs_guess(void *bs, int cyls, int heads, int secs) "bs %p LCHS %d %d %d"
-hd_geometry_guess(void *bs, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "bs %p CHS %u %u %u trans %d"
+hd_geometry_lchs_guess(void *blk, int cyls, int heads, int secs) "blk %p LCHS %d %d %d"
+hd_geometry_guess(void *blk, uint32_t cyls, uint32_t heads, uint32_t secs, int trans) "blk %p CHS %u %u %u trans %d"
 
 # hw/display/jazz_led.c
 jazz_led_read(uint64_t addr, uint8_t val) "read addr=0x%"PRIx64": 0x%x"
@@ -1031,10 +1031,10 @@ win_helper_done(uint32_t tl) "tl=%d"
 win_helper_retry(uint32_t tl) "tl=%d"
 
 # dma-helpers.c
-dma_bdrv_io(void *dbs, void *bs, int64_t sector_num, bool to_dev) "dbs=%p bs=%p sector_num=%" PRId64 " to_dev=%d"
+dma_blk_io(void *dbs, void *bs, int64_t sector_num, bool to_dev) "dbs=%p bs=%p sector_num=%" PRId64 " to_dev=%d"
 dma_aio_cancel(void *dbs) "dbs=%p"
 dma_complete(void *dbs, int ret, void *cb) "dbs=%p ret=%d cb=%p"
-dma_bdrv_cb(void *dbs, int ret) "dbs=%p ret=%d"
+dma_blk_cb(void *dbs, int ret) "dbs=%p ret=%d"
 dma_map_wait(void *dbs) "dbs=%p"
 
 # ui/console.c
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 15/23] ide: Complete conversion from BlockDriverState to BlockBackend
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (13 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 14/23] hw: Convert from BlockDriverState to BlockBackend, mostly Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 16/23] pc87312: Drop unused members of PC87312State Markus Armbruster
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Add a BlockBackend member to TrimAIOCB, so ide_issue_trim_cb() can use
blk_aio_discard() instead of bdrv_aio_discard().

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 hw/ide/core.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index fe12145..c043dbe 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -362,6 +362,7 @@ static void ide_set_signature(IDEState *s)
 
 typedef struct TrimAIOCB {
     BlockAIOCB common;
+    BlockBackend *blk;
     QEMUBH *bh;
     int ret;
     QEMUIOVector *qiov;
@@ -423,8 +424,8 @@ static void ide_issue_trim_cb(void *opaque, int ret)
                 }
 
                 /* Got an entry! Submit and exit.  */
-                iocb->aiocb = bdrv_aio_discard(iocb->common.bs, sector, count,
-                                               ide_issue_trim_cb, opaque);
+                iocb->aiocb = blk_aio_discard(iocb->blk, sector, count,
+                                              ide_issue_trim_cb, opaque);
                 return;
             }
 
@@ -448,6 +449,7 @@ BlockAIOCB *ide_issue_trim(BlockBackend *blk,
     TrimAIOCB *iocb;
 
     iocb = blk_aio_get(&trim_aiocb_info, blk, cb, opaque);
+    iocb->blk = blk;
     iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
     iocb->ret = 0;
     iocb->qiov = qiov;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 16/23] pc87312: Drop unused members of PC87312State
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (14 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 15/23] ide: Complete conversion from BlockDriverState to BlockBackend Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 17/23] blockdev: Drop superfluous DriveInfo member id Markus Armbruster
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 include/hw/isa/pc87312.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/include/hw/isa/pc87312.h b/include/hw/isa/pc87312.h
index befc8bd..bf74470 100644
--- a/include/hw/isa/pc87312.h
+++ b/include/hw/isa/pc87312.h
@@ -47,13 +47,10 @@ typedef struct PC87312State {
 
     struct {
         ISADevice *dev;
-        BlockDriverState *drive[2];
-        uint32_t base;
     } fdc;
 
     struct {
         ISADevice *dev;
-        uint32_t base;
     } ide;
 
     MemoryRegion io;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 17/23] blockdev: Drop superfluous DriveInfo member id
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (15 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 16/23] pc87312: Drop unused members of PC87312State Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 18/23] blockdev: Fix blockdev-add not to create IDE drive (0, 0) Markus Armbruster
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block/block-backend.c     | 1 -
 blockdev.c                | 3 +--
 include/sysemu/blockdev.h | 1 -
 3 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index cc21f3c..1bac033 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -123,7 +123,6 @@ static void drive_info_del(DriveInfo *dinfo)
 {
     if (dinfo) {
         qemu_opts_del(dinfo->opts);
-        g_free(dinfo->id);
         g_free(dinfo->serial);
         g_free(dinfo);
     }
diff --git a/blockdev.c b/blockdev.c
index 6f1e479..4488dfd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -458,7 +458,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
     }
 
     dinfo = g_malloc0(sizeof(*dinfo));
-    dinfo->id = g_strdup(qemu_opts_id(opts));
     blk_set_legacy_dinfo(blk, dinfo);
 
     if (!file || !*file) {
@@ -492,7 +491,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
 
     if (ret < 0) {
         error_setg(errp, "could not open disk image %s: %s",
-                   file ?: dinfo->id, error_get_pretty(error));
+                   file ?: blk_name(blk), error_get_pretty(error));
         error_free(error);
         goto err;
     }
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index f66b89a..27a40d5 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -30,7 +30,6 @@ typedef enum {
 } BlockInterfaceType;
 
 struct DriveInfo {
-    char *id;
     const char *devaddr;
     BlockInterfaceType type;
     int bus;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 18/23] blockdev: Fix blockdev-add not to create IDE drive (0, 0)
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (16 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 17/23] blockdev: Drop superfluous DriveInfo member id Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 19/23] blockdev: Drop DriveInfo member enable_auto_del Markus Armbruster
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

blockdev_init() always creates a DriveInfo, but only drive_new() fills
it in.  qmp_blockdev_add() leaves it blank.  This results in a drive
with type = IF_IDE, bus = 0, unit = 0.  Screwed up in commit ee13ed1c.

Board initialization code looking for IDE drive (0,0) can pick up one
of these bogus drives.  Not sure whether getting the QMP command
executed early enough is likely in practice, though.

Fix by creating DriveInfo in drive_new().  Block backends created by
blockdev-add don't get one.

A few places assume a block backend always has a DriveInfo.  Fix them
up.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 blockdev.c          | 10 ++--------
 hw/block/block.c    | 16 ++++++++++------
 hw/ide/qdev.c       |  2 +-
 hw/scsi/scsi-disk.c |  2 +-
 4 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 4488dfd..12906a6 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -285,7 +285,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
     int on_read_error, on_write_error;
     BlockBackend *blk;
     BlockDriverState *bs;
-    DriveInfo *dinfo;
     ThrottleConfig cfg;
     int snapshot = 0;
     bool copy_on_read;
@@ -457,9 +456,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
         bdrv_set_io_limits(bs, &cfg);
     }
 
-    dinfo = g_malloc0(sizeof(*dinfo));
-    blk_set_legacy_dinfo(blk, dinfo);
-
     if (!file || !*file) {
         if (has_driver_specific_opts) {
             file = NULL;
@@ -902,21 +898,19 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
     }
 
     /* Set legacy DriveInfo fields */
-    dinfo = blk_legacy_dinfo(blk);
+    dinfo = g_malloc0(sizeof(*dinfo));
     dinfo->enable_auto_del = true;
     dinfo->opts = all_opts;
-
     dinfo->cyls = cyls;
     dinfo->heads = heads;
     dinfo->secs = secs;
     dinfo->trans = translation;
-
     dinfo->type = type;
     dinfo->bus = bus_id;
     dinfo->unit = unit_id;
     dinfo->devaddr = devaddr;
-
     dinfo->serial = g_strdup(serial);
+    blk_set_legacy_dinfo(blk, dinfo);
 
     switch(type) {
     case IF_IDE:
diff --git a/hw/block/block.c b/hw/block/block.c
index 0666dd3..a625773 100644
--- a/hw/block/block.c
+++ b/hw/block/block.c
@@ -19,7 +19,9 @@ void blkconf_serial(BlockConf *conf, char **serial)
     if (!*serial) {
         /* try to fall back to value set with legacy -drive serial=... */
         dinfo = blk_legacy_dinfo(conf->blk);
-        *serial = g_strdup(dinfo->serial);
+        if (dinfo) {
+            *serial = g_strdup(dinfo->serial);
+        }
     }
 }
 
@@ -32,11 +34,13 @@ void blkconf_geometry(BlockConf *conf, int *ptrans,
     if (!conf->cyls && !conf->heads && !conf->secs) {
         /* try to fall back to value set with legacy -drive cyls=... */
         dinfo = blk_legacy_dinfo(conf->blk);
-        conf->cyls  = dinfo->cyls;
-        conf->heads = dinfo->heads;
-        conf->secs  = dinfo->secs;
-        if (ptrans) {
-            *ptrans = dinfo->trans;
+        if (dinfo) {
+            conf->cyls  = dinfo->cyls;
+            conf->heads = dinfo->heads;
+            conf->secs  = dinfo->secs;
+            if (ptrans) {
+                *ptrans = dinfo->trans;
+            }
         }
     }
     if (!conf->cyls && !conf->heads && !conf->secs) {
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 4818334..a74c81e 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -206,7 +206,7 @@ static int ide_drive_initfn(IDEDevice *dev)
 {
     DriveInfo *dinfo = blk_legacy_dinfo(dev->conf.blk);
 
-    return ide_dev_initfn(dev, dinfo->media_cd ? IDE_CD : IDE_HD);
+    return ide_dev_initfn(dev, dinfo && dinfo->media_cd ? IDE_CD : IDE_HD);
 }
 
 #define DEFINE_IDE_DEV_PROPERTIES()                     \
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 768c1ad..e0c5ed3 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2331,7 +2331,7 @@ static void scsi_disk_realize(SCSIDevice *dev, Error **errp)
     }
 
     dinfo = blk_legacy_dinfo(dev->conf.blk);
-    if (dinfo->media_cd) {
+    if (dinfo && dinfo->media_cd) {
         scsi_cd_realize(dev, errp);
     } else {
         scsi_hd_realize(dev, errp);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 19/23] blockdev: Drop DriveInfo member enable_auto_del
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (17 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 18/23] blockdev: Fix blockdev-add not to create IDE drive (0, 0) Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 20/23] block/qapi: Convert qmp_query_block() to BlockBackend Markus Armbruster
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Commit 2d246f0 introduced DriveInfo member enable_auto_del to
distinguish DriveInfo created via drive_new() from DriveInfo created
via qmp_blockdev_add().  The latter no longer exist.  Drop
enable_auto_del.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 blockdev.c                | 7 ++-----
 include/sysemu/blockdev.h | 1 -
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 12906a6..317239c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -90,16 +90,14 @@ void blockdev_mark_auto_del(BlockBackend *blk)
     DriveInfo *dinfo = blk_legacy_dinfo(blk);
     BlockDriverState *bs = blk_bs(blk);
 
-    if (dinfo && !dinfo->enable_auto_del) {
+    if (!dinfo) {
         return;
     }
 
     if (bs->job) {
         block_job_cancel(bs->job);
     }
-    if (dinfo) {
-        dinfo->auto_del = 1;
-    }
+    dinfo->auto_del = 1;
 }
 
 void blockdev_auto_del(BlockBackend *blk)
@@ -899,7 +897,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
 
     /* Set legacy DriveInfo fields */
     dinfo = g_malloc0(sizeof(*dinfo));
-    dinfo->enable_auto_del = true;
     dinfo->opts = all_opts;
     dinfo->cyls = cyls;
     dinfo->heads = heads;
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 27a40d5..2129d81 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -35,7 +35,6 @@ struct DriveInfo {
     int bus;
     int unit;
     int auto_del;               /* see blockdev_mark_auto_del() */
-    bool enable_auto_del;       /* Only for legacy drive_new() */
     int media_cd;
     int cyls, heads, secs, trans;
     QemuOpts *opts;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 20/23] block/qapi: Convert qmp_query_block() to BlockBackend
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (18 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 19/23] blockdev: Drop DriveInfo member enable_auto_del Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 21/23] blockdev: Convert qmp_eject(), qmp_change_blockdev() " Markus Armbruster
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Much more command code needs conversion.  I start with this one
because it's using bdrv_dev_* functions, which I'm about to lift into
BlockBackend.

While there, give bdrv_query_info() internal linkage.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block/qapi.c         | 15 ++++++++-------
 include/block/qapi.h |  3 ---
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/block/qapi.c b/block/qapi.c
index cc8f711..02121b2 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -28,6 +28,7 @@
 #include "qapi-visit.h"
 #include "qapi/qmp-output-visitor.h"
 #include "qapi/qmp/types.h"
+#include "sysemu/block-backend.h"
 #ifdef __linux__
 #include <linux/fs.h>
 #include <sys/ioctl.h>
@@ -264,15 +265,15 @@ void bdrv_query_image_info(BlockDriverState *bs,
 }
 
 /* @p_info will be set only on success. */
-void bdrv_query_info(BlockDriverState *bs,
-                     BlockInfo **p_info,
-                     Error **errp)
+static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
+                            Error **errp)
 {
     BlockInfo *info = g_malloc0(sizeof(*info));
+    BlockDriverState *bs = blk_bs(blk);
     BlockDriverState *bs0;
     ImageInfo **p_image_info;
     Error *local_err = NULL;
-    info->device = g_strdup(bdrv_get_device_name(bs));
+    info->device = g_strdup(blk_name(blk));
     info->type = g_strdup("unknown");
     info->locked = bdrv_dev_is_medium_locked(bs);
     info->removable = bdrv_dev_has_removable_media(bs);
@@ -359,12 +360,12 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs)
 BlockInfoList *qmp_query_block(Error **errp)
 {
     BlockInfoList *head = NULL, **p_next = &head;
-    BlockDriverState *bs = NULL;
+    BlockBackend *blk;
     Error *local_err = NULL;
 
-     while ((bs = bdrv_next(bs))) {
+    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
         BlockInfoList *info = g_malloc0(sizeof(*info));
-        bdrv_query_info(bs, &info->value, &local_err);
+        bdrv_query_info(blk, &info->value, &local_err);
         if (local_err) {
             error_propagate(errp, local_err);
             goto err;
diff --git a/include/block/qapi.h b/include/block/qapi.h
index 0374546..168d788 100644
--- a/include/block/qapi.h
+++ b/include/block/qapi.h
@@ -36,9 +36,6 @@ int bdrv_query_snapshot_info_list(BlockDriverState *bs,
 void bdrv_query_image_info(BlockDriverState *bs,
                            ImageInfo **p_info,
                            Error **errp);
-void bdrv_query_info(BlockDriverState *bs,
-                     BlockInfo **p_info,
-                     Error **errp);
 
 void bdrv_snapshot_dump(fprintf_function func_fprintf, void *f,
                         QEMUSnapshotInfo *sn);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 21/23] blockdev: Convert qmp_eject(), qmp_change_blockdev() to BlockBackend
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (19 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 20/23] block/qapi: Convert qmp_query_block() to BlockBackend Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 22/23] block: Lift device model API into BlockBackend Markus Armbruster
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Much more command code needs conversion.  I'm converting these now
because they's using bdrv_dev_* functions, which I'm about to lift
into BlockBackend.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 blockdev.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 317239c..6286c0e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1501,8 +1501,10 @@ exit:
 }
 
 
-static void eject_device(BlockDriverState *bs, int force, Error **errp)
+static void eject_device(BlockBackend *blk, int force, Error **errp)
 {
+    BlockDriverState *bs = blk_bs(blk);
+
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
         return;
     }
@@ -1526,15 +1528,15 @@ static void eject_device(BlockDriverState *bs, int force, Error **errp)
 
 void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
 {
-    BlockDriverState *bs;
+    BlockBackend *blk;
 
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
 
-    eject_device(bs, force, errp);
+    eject_device(blk, force, errp);
 }
 
 void qmp_block_passwd(bool has_device, const char *device,
@@ -1593,16 +1595,18 @@ static void qmp_bdrv_open_encrypted(BlockDriverState *bs, const char *filename,
 void qmp_change_blockdev(const char *device, const char *filename,
                          const char *format, Error **errp)
 {
+    BlockBackend *blk;
     BlockDriverState *bs;
     BlockDriver *drv = NULL;
     int bdrv_flags;
     Error *err = NULL;
 
-    bs = bdrv_find(device);
-    if (!bs) {
+    blk = blk_by_name(device);
+    if (!blk) {
         error_set(errp, QERR_DEVICE_NOT_FOUND, device);
         return;
     }
+    bs = blk_bs(blk);
 
     if (format) {
         drv = bdrv_find_whitelisted_format(format, bs->read_only);
@@ -1612,7 +1616,7 @@ void qmp_change_blockdev(const char *device, const char *filename,
         }
     }
 
-    eject_device(bs, 0, &err);
+    eject_device(blk, 0, &err);
     if (err) {
         error_propagate(errp, err);
         return;
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 22/23] block: Lift device model API into BlockBackend
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (20 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 21/23] blockdev: Convert qmp_eject(), qmp_change_blockdev() " Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 23/23] block: Make device model's references to BlockBackend strong Markus Armbruster
  2014-09-11 19:24 ` [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Move device model attachment / detachment and the BlockDevOps device
model callbacks and their wrappers from BlockDriverState to
BlockBackend.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block.c                        | 126 +++++------------------------------------
 block/block-backend.c          | 107 ++++++++++++++++++++++++++++++----
 block/qapi.c                   |   8 +--
 blockdev.c                     |   8 +--
 include/block/block.h          |  45 ---------------
 include/block/block_int.h      |  12 ++--
 include/sysemu/block-backend.h |  35 ++++++++++++
 7 files changed, 159 insertions(+), 182 deletions(-)

diff --git a/block.c b/block.c
index f71b87c..e81087f 100644
--- a/block.c
+++ b/block.c
@@ -58,9 +58,6 @@ struct BdrvDirtyBitmap {
 
 #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */
 
-#define COROUTINE_POOL_RESERVATION 64 /* number of coroutines to reserve */
-
-static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load);
 static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockCompletionFunc *cb, void *opaque);
@@ -1516,7 +1513,9 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
     }
 
     if (!bdrv_key_required(bs)) {
-        bdrv_dev_change_media_cb(bs, true);
+        if (bs->blk) {
+            blk_dev_change_media_cb(bs->blk, true);
+        }
     } else if (!runstate_check(RUN_STATE_PRELAUNCH)
                && !runstate_check(RUN_STATE_INMIGRATE)
                && !runstate_check(RUN_STATE_PAUSED)) { /* HACK */
@@ -1841,7 +1840,9 @@ void bdrv_close(BlockDriverState *bs)
         }
     }
 
-    bdrv_dev_change_media_cb(bs, false);
+    if (bs->blk) {
+        blk_dev_change_media_cb(bs->blk, false);
+    }
 
     /*throttling disk I/O limits*/
     if (bs->io_limits_enabled) {
@@ -1949,9 +1950,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
     /* move some fields that need to stay attached to the device */
 
     /* dev info */
-    bs_dest->dev_ops            = bs_src->dev_ops;
-    bs_dest->dev_opaque         = bs_src->dev_opaque;
-    bs_dest->dev                = bs_src->dev;
     bs_dest->guest_block_size   = bs_src->guest_block_size;
     bs_dest->copy_on_read       = bs_src->copy_on_read;
 
@@ -2017,7 +2015,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
     assert(!bs_new->blk);
     assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
     assert(bs_new->job == NULL);
-    assert(bs_new->dev == NULL);
     assert(bs_new->io_limits_enabled == false);
     assert(!throttle_have_timer(&bs_new->throttle_state));
 
@@ -2034,7 +2031,6 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
     assert(!bs_new->blk);
 
     /* Check a few fields that should remain attached to the device */
-    assert(bs_new->dev == NULL);
     assert(bs_new->job == NULL);
     assert(bs_new->io_limits_enabled == false);
     assert(!throttle_have_timer(&bs_new->throttle_state));
@@ -2073,7 +2069,6 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top)
 
 static void bdrv_delete(BlockDriverState *bs)
 {
-    assert(!bs->dev);
     assert(!bs->job);
     assert(bdrv_op_blocker_is_empty(bs));
     assert(!bs->refcnt);
@@ -2087,105 +2082,6 @@ static void bdrv_delete(BlockDriverState *bs)
     g_free(bs);
 }
 
-int bdrv_attach_dev(BlockDriverState *bs, void *dev)
-/* TODO change to DeviceState *dev when all users are qdevified */
-{
-    if (bs->dev) {
-        return -EBUSY;
-    }
-    bs->dev = dev;
-    bdrv_iostatus_reset(bs);
-
-    /* We're expecting I/O from the device so bump up coroutine pool size */
-    qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION);
-    return 0;
-}
-
-/* TODO qdevified devices don't use this, remove when devices are qdevified */
-void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev)
-{
-    if (bdrv_attach_dev(bs, dev) < 0) {
-        abort();
-    }
-}
-
-void bdrv_detach_dev(BlockDriverState *bs, void *dev)
-/* TODO change to DeviceState *dev when all users are qdevified */
-{
-    assert(bs->dev == dev);
-    bs->dev = NULL;
-    bs->dev_ops = NULL;
-    bs->dev_opaque = NULL;
-    bs->guest_block_size = 512;
-    qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION);
-}
-
-/* TODO change to return DeviceState * when all users are qdevified */
-void *bdrv_get_attached_dev(BlockDriverState *bs)
-{
-    return bs->dev;
-}
-
-void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops,
-                      void *opaque)
-{
-    bs->dev_ops = ops;
-    bs->dev_opaque = opaque;
-}
-
-static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load)
-{
-    if (bs->dev_ops && bs->dev_ops->change_media_cb) {
-        bool tray_was_closed = !bdrv_dev_is_tray_open(bs);
-        bs->dev_ops->change_media_cb(bs->dev_opaque, load);
-        if (tray_was_closed) {
-            /* tray open */
-            qapi_event_send_device_tray_moved(bdrv_get_device_name(bs),
-                                              true, &error_abort);
-        }
-        if (load) {
-            /* tray close */
-            qapi_event_send_device_tray_moved(bdrv_get_device_name(bs),
-                                              false, &error_abort);
-        }
-    }
-}
-
-bool bdrv_dev_has_removable_media(BlockDriverState *bs)
-{
-    return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb);
-}
-
-void bdrv_dev_eject_request(BlockDriverState *bs, bool force)
-{
-    if (bs->dev_ops && bs->dev_ops->eject_request_cb) {
-        bs->dev_ops->eject_request_cb(bs->dev_opaque, force);
-    }
-}
-
-bool bdrv_dev_is_tray_open(BlockDriverState *bs)
-{
-    if (bs->dev_ops && bs->dev_ops->is_tray_open) {
-        return bs->dev_ops->is_tray_open(bs->dev_opaque);
-    }
-    return false;
-}
-
-static void bdrv_dev_resize_cb(BlockDriverState *bs)
-{
-    if (bs->dev_ops && bs->dev_ops->resize_cb) {
-        bs->dev_ops->resize_cb(bs->dev_opaque);
-    }
-}
-
-bool bdrv_dev_is_medium_locked(BlockDriverState *bs)
-{
-    if (bs->dev_ops && bs->dev_ops->is_medium_locked) {
-        return bs->dev_ops->is_medium_locked(bs->dev_opaque);
-    }
-    return false;
-}
-
 /*
  * Run consistency checks on an image
  *
@@ -3520,7 +3416,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
     ret = drv->bdrv_truncate(bs, offset);
     if (ret == 0) {
         ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
-        bdrv_dev_resize_cb(bs);
+        if (bs->blk) {
+            blk_dev_resize_cb(bs->blk);
+        }
     }
     return ret;
 }
@@ -3714,8 +3612,10 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
         bs->valid_key = 0;
     } else if (!bs->valid_key) {
         bs->valid_key = 1;
-        /* call the change callback now, we skipped it on open */
-        bdrv_dev_change_media_cb(bs, true);
+        if (bs->blk) {
+            /* call the change callback now, we skipped it on open */
+            blk_dev_change_media_cb(bs->blk, true);
+        }
     }
     return ret;
 }
diff --git a/block/block-backend.c b/block/block-backend.c
index 1bac033..6c0c8f2 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -13,6 +13,10 @@
 #include "sysemu/block-backend.h"
 #include "block/block_int.h"
 #include "sysemu/blockdev.h"
+#include "qapi-event.h"
+
+/* Number of coroutines to reserve per attached device model */
+#define COROUTINE_POOL_RESERVATION 64
 
 struct BlockBackend {
     char *name;
@@ -20,6 +24,11 @@ struct BlockBackend {
     BlockDriverState *bs;
     DriveInfo *legacy_dinfo;
     QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
+
+    void *dev;                  /* attached device model, if any */
+    /* TODO change to DeviceState when all users are qdevified */
+    const BlockDevOps *dev_ops;
+    void *dev_opaque;
 };
 
 static void drive_info_del(DriveInfo *dinfo);
@@ -85,6 +94,7 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp)
 static void blk_delete(BlockBackend *blk)
 {
     assert(!blk->refcnt);
+    assert(!blk->dev);
     bdrv_unref(blk->bs);
     blk_detach_bs(blk);
     QTAILQ_REMOVE(&blk_backends, blk, link);
@@ -237,34 +247,109 @@ BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
     assert(0);
 }
 
-void blk_iostatus_enable(BlockBackend *blk)
-{
-    bdrv_iostatus_enable(blk->bs);
-}
-
 int blk_attach_dev(BlockBackend *blk, void *dev)
+/* TODO change to DeviceState *dev when all users are qdevified */
 {
-    return bdrv_attach_dev(blk->bs, dev);
+    if (blk->dev) {
+        return -EBUSY;
+    }
+    blk->dev = dev;
+    bdrv_iostatus_reset(blk->bs);
+
+    /* We're expecting I/O from the device so bump up coroutine pool size */
+    qemu_coroutine_adjust_pool_size(COROUTINE_POOL_RESERVATION);
+    return 0;
 }
 
+/* TODO qdevified devices don't use this, remove when devices are qdevified */
 void blk_attach_dev_nofail(BlockBackend *blk, void *dev)
 {
-    bdrv_attach_dev_nofail(blk->bs, dev);
+    if (blk_attach_dev(blk, dev) < 0) {
+        abort();
+    }
 }
 
 void blk_detach_dev(BlockBackend *blk, void *dev)
+/* TODO change to DeviceState *dev when all users are qdevified */
 {
-    bdrv_detach_dev(blk->bs, dev);
+    assert(blk->dev == dev);
+    blk->dev = NULL;
+    blk->dev_ops = NULL;
+    blk->dev_opaque = NULL;
+    bdrv_set_guest_block_size(blk->bs, 512);
+    qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION);
 }
 
+/* TODO change to return DeviceState * when all users are qdevified */
 void *blk_get_attached_dev(BlockBackend *blk)
 {
-    return bdrv_get_attached_dev(blk->bs);
+    return blk->dev;
 }
 
-void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops, void *opaque)
+void blk_set_dev_ops(BlockBackend *blk, const BlockDevOps *ops,
+                      void *opaque)
 {
-    bdrv_set_dev_ops(blk->bs, ops, opaque);
+    blk->dev_ops = ops;
+    blk->dev_opaque = opaque;
+}
+
+void blk_dev_change_media_cb(BlockBackend *blk, bool load)
+{
+    if (blk->dev_ops && blk->dev_ops->change_media_cb) {
+        bool tray_was_closed = !blk_dev_is_tray_open(blk);
+
+        blk->dev_ops->change_media_cb(blk->dev_opaque, load);
+        if (tray_was_closed) {
+            /* tray open */
+            qapi_event_send_device_tray_moved(blk_name(blk),
+                                              true, &error_abort);
+        }
+        if (load) {
+            /* tray close */
+            qapi_event_send_device_tray_moved(blk_name(blk),
+                                              false, &error_abort);
+        }
+    }
+}
+
+bool blk_dev_has_removable_media(BlockBackend *blk)
+{
+    return !blk->dev || (blk->dev_ops && blk->dev_ops->change_media_cb);
+}
+
+void blk_dev_eject_request(BlockBackend *blk, bool force)
+{
+    if (blk->dev_ops && blk->dev_ops->eject_request_cb) {
+        blk->dev_ops->eject_request_cb(blk->dev_opaque, force);
+    }
+}
+
+bool blk_dev_is_tray_open(BlockBackend *blk)
+{
+    if (blk->dev_ops && blk->dev_ops->is_tray_open) {
+        return blk->dev_ops->is_tray_open(blk->dev_opaque);
+    }
+    return false;
+}
+
+void blk_dev_resize_cb(BlockBackend *blk)
+{
+    if (blk->dev_ops && blk->dev_ops->resize_cb) {
+        blk->dev_ops->resize_cb(blk->dev_opaque);
+    }
+}
+
+bool blk_dev_is_medium_locked(BlockBackend *blk)
+{
+    if (blk->dev_ops && blk->dev_ops->is_medium_locked) {
+        return blk->dev_ops->is_medium_locked(blk->dev_opaque);
+    }
+    return false;
+}
+
+void blk_iostatus_enable(BlockBackend *blk)
+{
+    bdrv_iostatus_enable(blk->bs);
 }
 
 int blk_read(BlockBackend *blk, int64_t sector_num, uint8_t *buf,
diff --git a/block/qapi.c b/block/qapi.c
index 02121b2..921e620 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -275,12 +275,12 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
     Error *local_err = NULL;
     info->device = g_strdup(blk_name(blk));
     info->type = g_strdup("unknown");
-    info->locked = bdrv_dev_is_medium_locked(bs);
-    info->removable = bdrv_dev_has_removable_media(bs);
+    info->locked = blk_dev_is_medium_locked(blk);
+    info->removable = blk_dev_has_removable_media(blk);
 
-    if (bdrv_dev_has_removable_media(bs)) {
+    if (blk_dev_has_removable_media(blk)) {
         info->has_tray_open = true;
-        info->tray_open = bdrv_dev_is_tray_open(bs);
+        info->tray_open = blk_dev_is_tray_open(blk);
     }
 
     if (bdrv_iostatus_is_enabled(bs)) {
diff --git a/blockdev.c b/blockdev.c
index 6286c0e..6dc405b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1508,14 +1508,14 @@ static void eject_device(BlockBackend *blk, int force, Error **errp)
     if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_EJECT, errp)) {
         return;
     }
-    if (!bdrv_dev_has_removable_media(bs)) {
+    if (!blk_dev_has_removable_media(blk)) {
         error_setg(errp, "Device '%s' is not removable",
                    bdrv_get_device_name(bs));
         return;
     }
 
-    if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) {
-        bdrv_dev_eject_request(bs, force);
+    if (blk_dev_is_medium_locked(blk) && !blk_dev_is_tray_open(blk)) {
+        blk_dev_eject_request(blk, force);
         if (!force) {
             error_setg(errp, "Device '%s' is locked",
                        bdrv_get_device_name(bs));
@@ -1746,7 +1746,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
      * can be removed.  If this is a drive with no device backing
      * then we can just get rid of the block driver state right here.
      */
-    if (bdrv_get_attached_dev(bs)) {
+    if (blk_get_attached_dev(blk)) {
         blk_make_anon(blk);
         /* Further I/O must not pause the guest */
         bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
diff --git a/include/block/block.h b/include/block/block.h
index 15a5290..3252039 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -47,41 +47,6 @@ typedef struct BlockFragInfo {
     uint64_t compressed_clusters;
 } BlockFragInfo;
 
-/* Callbacks for block device models */
-typedef struct BlockDevOps {
-    /*
-     * Runs when virtual media changed (monitor commands eject, change)
-     * Argument load is true on load and false on eject.
-     * Beware: doesn't run when a host device's physical media
-     * changes.  Sure would be useful if it did.
-     * Device models with removable media must implement this callback.
-     */
-    void (*change_media_cb)(void *opaque, bool load);
-    /*
-     * Runs when an eject request is issued from the monitor, the tray
-     * is closed, and the medium is locked.
-     * Device models that do not implement is_medium_locked will not need
-     * this callback.  Device models that can lock the medium or tray might
-     * want to implement the callback and unlock the tray when "force" is
-     * true, even if they do not support eject requests.
-     */
-    void (*eject_request_cb)(void *opaque, bool force);
-    /*
-     * Is the virtual tray open?
-     * Device models implement this only when the device has a tray.
-     */
-    bool (*is_tray_open)(void *opaque);
-    /*
-     * Is the virtual medium locked into the device?
-     * Device models implement this only when device has such a lock.
-     */
-    bool (*is_medium_locked)(void *opaque);
-    /*
-     * Runs when the size changed (e.g. monitor command block_resize)
-     */
-    void (*resize_cb)(void *opaque);
-} BlockDevOps;
-
 typedef enum {
     BDRV_REQ_COPY_ON_READ = 0x1,
     BDRV_REQ_ZERO_WRITE   = 0x2,
@@ -228,16 +193,6 @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state);
 void bdrv_reopen_abort(BDRVReopenState *reopen_state);
 void bdrv_close(BlockDriverState *bs);
 void bdrv_add_close_notifier(BlockDriverState *bs, Notifier *notify);
-int bdrv_attach_dev(BlockDriverState *bs, void *dev);
-void bdrv_attach_dev_nofail(BlockDriverState *bs, void *dev);
-void bdrv_detach_dev(BlockDriverState *bs, void *dev);
-void *bdrv_get_attached_dev(BlockDriverState *bs);
-void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops,
-                      void *opaque);
-void bdrv_dev_eject_request(BlockDriverState *bs, bool force);
-bool bdrv_dev_has_removable_media(BlockDriverState *bs);
-bool bdrv_dev_is_tray_open(BlockDriverState *bs);
-bool bdrv_dev_is_medium_locked(BlockDriverState *bs);
 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
               uint8_t *buf, int nb_sectors);
 int bdrv_read_unthrottled(BlockDriverState *bs, int64_t sector_num,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index b3246e7..3b20031 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -325,11 +325,6 @@ struct BlockDriverState {
 
     BlockBackend *blk;          /* owning backend, if any */
 
-    void *dev;                  /* attached device model, if any */
-    /* TODO change to DeviceState when all users are qdevified */
-    const BlockDevOps *dev_ops;
-    void *dev_opaque;
-
     AioContext *aio_context; /* event loop used for fd handlers, timers, etc */
     /* long-running tasks intended to always use the same AioContext as this
      * BDS may register themselves in this list to be notified of changes
@@ -587,4 +582,11 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
                   BlockCompletionFunc *cb, void *opaque,
                   Error **errp);
 
+void blk_dev_change_media_cb(BlockBackend *blk, bool load);
+bool blk_dev_has_removable_media(BlockBackend *blk);
+void blk_dev_eject_request(BlockBackend *blk, bool force);
+bool blk_dev_is_tray_open(BlockBackend *blk);
+bool blk_dev_is_medium_locked(BlockBackend *blk);
+void blk_dev_resize_cb(BlockBackend *blk);
+
 #endif /* BLOCK_INT_H */
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 73f9325..d8734bb 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -25,6 +25,41 @@
  */
 #include "block/block.h"
 
+/* Callbacks for block device models */
+typedef struct BlockDevOps {
+    /*
+     * Runs when virtual media changed (monitor commands eject, change)
+     * Argument load is true on load and false on eject.
+     * Beware: doesn't run when a host device's physical media
+     * changes.  Sure would be useful if it did.
+     * Device models with removable media must implement this callback.
+     */
+    void (*change_media_cb)(void *opaque, bool load);
+    /*
+     * Runs when an eject request is issued from the monitor, the tray
+     * is closed, and the medium is locked.
+     * Device models that do not implement is_medium_locked will not need
+     * this callback.  Device models that can lock the medium or tray might
+     * want to implement the callback and unlock the tray when "force" is
+     * true, even if they do not support eject requests.
+     */
+    void (*eject_request_cb)(void *opaque, bool force);
+    /*
+     * Is the virtual tray open?
+     * Device models implement this only when the device has a tray.
+     */
+    bool (*is_tray_open)(void *opaque);
+    /*
+     * Is the virtual medium locked into the device?
+     * Device models implement this only when device has such a lock.
+     */
+    bool (*is_medium_locked)(void *opaque);
+    /*
+     * Runs when the size changed (e.g. monitor command block_resize)
+     */
+    void (*resize_cb)(void *opaque);
+} BlockDevOps;
+
 BlockBackend *blk_new(const char *name, Error **errp);
 BlockBackend *blk_new_with_bs(const char *name, Error **errp);
 void blk_ref(BlockBackend *blk);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Qemu-devel] [PATCH 23/23] block: Make device model's references to BlockBackend strong
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (21 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 22/23] block: Lift device model API into BlockBackend Markus Armbruster
@ 2014-09-10  8:13 ` Markus Armbruster
  2014-09-11 19:24 ` [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-10  8:13 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Doesn't make a difference just yet, but it's the right thing to do.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 block/block-backend.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index 6c0c8f2..7ad4e44 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -253,6 +253,7 @@ int blk_attach_dev(BlockBackend *blk, void *dev)
     if (blk->dev) {
         return -EBUSY;
     }
+    blk_ref(blk);
     blk->dev = dev;
     bdrv_iostatus_reset(blk->bs);
 
@@ -273,9 +274,10 @@ void blk_detach_dev(BlockBackend *blk, void *dev)
 /* TODO change to DeviceState *dev when all users are qdevified */
 {
     assert(blk->dev == dev);
-    blk->dev = NULL;
     blk->dev_ops = NULL;
     blk->dev_opaque = NULL;
+    blk->dev = NULL;
+    blk_unref(blk);
     bdrv_set_guest_block_size(blk->bs, 512);
     qemu_coroutine_adjust_pool_size(-COROUTINE_POOL_RESERVATION);
 }
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 02/23] block: New BlockBackend Markus Armbruster
@ 2014-09-10  9:56   ` Kevin Wolf
  2014-09-11 10:03     ` Markus Armbruster
  2014-09-10 11:34   ` Benoît Canet
  2014-09-10 12:40   ` Benoît Canet
  2 siblings, 1 reply; 76+ messages in thread
From: Kevin Wolf @ 2014-09-10  9:56 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: benoit.canet, famz, qemu-devel, stefanha

Am 10.09.2014 um 10:13 hat Markus Armbruster geschrieben:
> A block device consists of a frontend device model and a backend.
> 
> A block backend has a tree of block drivers doing the actual work.
> The tree is managed by the block layer.
> 
> We currently use a single abstraction BlockDriverState both for tree
> nodes and the backend as a whole.  Drawbacks:
> 
> * Its API includes both stuff that makes sense only at the block
>   backend level (root of the tree) and stuff that's only for use
>   within the block layer.  This makes the API bigger and more complex
>   than necessary.  Moreover, it's not obvious which interfaces are
>   meant for device models, and which really aren't.
> 
> * Since device models keep a reference to their backend, the backend
>   object can't just be destroyed.  But for media change, we need to
>   replace the tree.  Our solution is to make the BlockDriverState
>   generic, with actual driver state in a separate object, pointed to
>   by member opaque.  That lets us replace the tree by deinitializing
>   and reinitializing its root.  This special need of the root makes
>   the data structure awkward everywhere in the tree.
> 
> The general plan is to separate the APIs into "block backend", for use
> by device models, monitor and whatever other code dealing with block
> backends, and "block driver", for use by the block layer and whatever
> other code (if any) dealing with trees and tree nodes.
> 
> Code dealing with block backends, device models in particular, should
> become completely oblivious of BlockDriverState.  This should let us
> clean up both APIs, and the tree data structures.
> 
> This commit is a first step.  It creates a minimal "block backend"
> API: type BlockBackend and functions to create, destroy and find them.
> BlockBackend objects are created and destroyed, but not yet used for
> anything; that'll come shortly.
> 
> BlockBackend is reference-counted.  Its reference count never exceeds
> one so far, but that's going to change.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block/Makefile.objs            |   2 +-
>  block/block-backend.c          | 110 +++++++++++++++++++++++++++++++++++++++++
>  blockdev.c                     |  10 +++-
>  hw/block/xen_disk.c            |  11 +++++
>  include/qemu/typedefs.h        |   1 +
>  include/sysemu/block-backend.h |  26 ++++++++++
>  qemu-img.c                     |  46 +++++++++++++++++
>  qemu-io.c                      |   8 +++
>  qemu-nbd.c                     |   3 +-
>  9 files changed, 214 insertions(+), 3 deletions(-)
>  create mode 100644 block/block-backend.c
>  create mode 100644 include/sysemu/block-backend.h
> 
> diff --git a/block/Makefile.objs b/block/Makefile.objs
> index f45f939..a70140b 100644
> --- a/block/Makefile.objs
> +++ b/block/Makefile.objs
> @@ -5,7 +5,7 @@ block-obj-y += qed-check.o
>  block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
>  block-obj-$(CONFIG_QUORUM) += quorum.o
>  block-obj-y += parallels.o blkdebug.o blkverify.o
> -block-obj-y += snapshot.o qapi.o
> +block-obj-y += block-backend.o snapshot.o qapi.o
>  block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
>  block-obj-$(CONFIG_POSIX) += raw-posix.o
>  block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
> diff --git a/block/block-backend.c b/block/block-backend.c
> new file mode 100644
> index 0000000..833f7d9
> --- /dev/null
> +++ b/block/block-backend.c
> @@ -0,0 +1,110 @@
> +/*
> + * QEMU Block backends
> + *
> + * Copyright (C) 2014 Red Hat, Inc.
> + *
> + * Authors:
> + *  Markus Armbruster <armbru@redhat.com>,
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * later.  See the COPYING file in the top-level directory.
> + */

I think we still have the long-term plan of exposing a block layer
library that can be consumed by libvirt. As the usage in qemu-io/img/nbd
shows, this will probably have to use BlockBackends, so this code is part
of the block layer core.

Considering this, using the LGPL would be more practical. Can you please
make this change for v2? (Personally, I would have used the MIT license
that the rest of the block layer uses, which also make copying code
around cleaner license-wise, but I know you dislike it.)

> +#include "sysemu/block-backend.h"
> +#include "block/block_int.h"
> +
> +struct BlockBackend {
> +    char *name;
> +    int refcnt;
> +    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
> +};
> +
> +static QTAILQ_HEAD(, BlockBackend) blk_backends =
> +    QTAILQ_HEAD_INITIALIZER(blk_backends);
> +
> +/**
> + * blk_new:
> + * @name: name, must not be %NULL or empty
> + * @errp: return location for an error to be set on failure, or %NULL
> + *
> + * Create a new BlockBackend, with a reference count of one.  Fail if
> + * @name already exists.
> + *
> + * Returns: the BlockBackend on success, %NULL on failure
> + */
> +BlockBackend *blk_new(const char *name, Error **errp)
> +{
> +    BlockBackend *blk = g_new0(BlockBackend, 1);
> +
> +    assert(name && name[0]);
> +    if (blk_by_name(name)) {
> +        error_setg(errp, "Device with id '%s' already exists", name);
> +        return NULL;

blk is leaked here.

> +    }
> +    blk->name = g_strdup(name);
> +    blk->refcnt = 1;
> +    QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
> +    return blk;
> +}
> +
> +static void blk_delete(BlockBackend *blk)
> +{
> +    assert(!blk->refcnt);
> +    QTAILQ_REMOVE(&blk_backends, blk, link);
> +    g_free(blk->name);
> +    g_free(blk);
> +}
> +
> +/**
> + * blk_ref:
> + *
> + * Increment @blk's reference count.
> + */
> +void blk_ref(BlockBackend *blk)
> +{
> +    blk->refcnt++;
> +}
> +
> +/**
> + * blk_unref:
> + *
> + * Decrement @blk's reference count.  If this drops it to zero,
> + * destroy @blk.
> + */
> +void blk_unref(BlockBackend *blk)
> +{
> +    if (blk) {
> +        g_assert(blk->refcnt > 0);

You're mixing assert() and g_assert() in this patch. Any reason for
this? If not, I think plain assert() is clearly in the majority in the
overall codebase.

> +        if (!--blk->refcnt) {
> +            blk_delete(blk);
> +        }
> +    }
> +}
> +
> +const char *blk_name(BlockBackend *blk)
> +{
> +    return blk->name;
> +}
> +
> +BlockBackend *blk_by_name(const char *name)
> +{
> +    BlockBackend *blk;
> +
> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
> +        if (!strcmp(name, blk->name)) {
> +            return blk;
> +        }
> +    }
> +    return NULL;
> +}

No comment for these two non-static functions?

> +/**
> + * blk_next:
> + *
> + * Returns: the first BlockBackend if @blk is null, else @blk's next
> + * sibling, which is %NULL for the last BlockBackend
> + */
> +BlockBackend *blk_next(BlockBackend *blk)
> +{
> +    return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
> +}
> diff --git a/blockdev.c b/blockdev.c
> index 9fbd888..86596bc 100644
> --- a/blockdev.c
> +++ b/blockdev.c

Okay, so here the hard part starts: As long as the BB is completely
unused, it's very hard to review at which places one must be created and
deleted.

What was your approach to systematically find all of them?

> @@ -30,6 +30,7 @@
>   * THE SOFTWARE.
>   */
>  
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/block/block.h"
>  #include "block/blockjob.h"
> @@ -221,6 +222,7 @@ void drive_del(DriveInfo *dinfo)
>      }
>  
>      bdrv_unref(dinfo->bdrv);
> +    blk_unref(blk_by_name(dinfo->id));
>      g_free(dinfo->id);
>      QTAILQ_REMOVE(&drives, dinfo, next);
>      g_free(dinfo->serial);
> @@ -301,6 +303,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      int ro = 0;
>      int bdrv_flags = 0;
>      int on_read_error, on_write_error;
> +    BlockBackend *blk;
>      DriveInfo *dinfo;
>      ThrottleConfig cfg;
>      int snapshot = 0;
> @@ -456,6 +459,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      }
>  
>      /* init */
> +    blk = blk_new(qemu_opts_id(opts), errp);
> +    if (!blk) {
> +        goto early_err;
> +    }
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
>      dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
> @@ -525,6 +532,7 @@ err:
>  bdrv_new_err:
>      g_free(dinfo->id);
>      g_free(dinfo);
> +    blk_unref(blk);
>  early_err:
>      qemu_opts_del(opts);
>  err_no_opts:
> @@ -1770,7 +1778,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>       */
>      if (bdrv_get_attached_dev(bs)) {
>          bdrv_make_anon(bs);
> -
> +        blk_unref(blk_by_name(id));
>          /* Further I/O must not pause the guest */
>          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
>                            BLOCKDEV_ON_ERROR_REPORT);

Won't we unref the BB a second time now when unplugging the device?
(drive_del() called in blockdev_auto_del())

> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> index 8bac7ff..730a021 100644
> --- a/hw/block/xen_disk.c
> +++ b/hw/block/xen_disk.c
> @@ -39,6 +39,7 @@
>  #include "hw/xen/xen_backend.h"
>  #include "xen_blkif.h"
>  #include "sysemu/blockdev.h"
> +#include "sysemu/block-backend.h"
>  
>  /* ------------------------------------------------------------- */
>  
> @@ -852,12 +853,18 @@ static int blk_connect(struct XenDevice *xendev)
>      blkdev->dinfo = drive_get(IF_XEN, 0, index);
>      if (!blkdev->dinfo) {
>          Error *local_err = NULL;
> +        BlockBackend *blk;
>          BlockDriver *drv;
>  
>          /* setup via xenbus -> create new block driver instance */
>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
> +        blk = blk_new(blkdev->dev, NULL);
> +        if (!blk) {
> +            return -1;
> +        }
>          blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
>          if (!blkdev->bs) {
> +            blk_unref(blk);
>              return -1;
>          }
>  
> @@ -868,6 +875,7 @@ static int blk_connect(struct XenDevice *xendev)
>                            error_get_pretty(local_err));
>              error_free(local_err);
>              bdrv_unref(blkdev->bs);
> +            blk_unref(blk);
>              blkdev->bs = NULL;
>              return -1;
>          }
> @@ -983,6 +991,9 @@ static void blk_disconnect(struct XenDevice *xendev)
>      if (blkdev->bs) {
>          bdrv_detach_dev(blkdev->bs, blkdev);
>          bdrv_unref(blkdev->bs);
> +        if (!blkdev->dinfo) {
> +            blk_unref(blk_by_name(blkdev->dev));
> +        }
>          blkdev->bs = NULL;
>      }
>      xen_be_unbind_evtchn(&blkdev->xendev);
> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
> index 5f20b0e..198da2e 100644
> --- a/include/qemu/typedefs.h
> +++ b/include/qemu/typedefs.h
> @@ -35,6 +35,7 @@ typedef struct MachineClass MachineClass;
>  typedef struct NICInfo NICInfo;
>  typedef struct HCIInfo HCIInfo;
>  typedef struct AudioState AudioState;
> +typedef struct BlockBackend BlockBackend;
>  typedef struct BlockDriverState BlockDriverState;
>  typedef struct DriveInfo DriveInfo;
>  typedef struct DisplayState DisplayState;
> diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
> new file mode 100644
> index 0000000..3f8371c
> --- /dev/null
> +++ b/include/sysemu/block-backend.h
> @@ -0,0 +1,26 @@
> +/*
> + * QEMU Block backends
> + *
> + * Copyright (C) 2014 Red Hat, Inc.
> + *
> + * Authors:
> + *  Markus Armbruster <armbru@redhat.com>,
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * later.  See the COPYING file in the top-level directory.
> + */
> +
> +#ifndef BLOCK_BACKEND_H
> +#define BLOCK_BACKEND_H
> +
> +#include "qemu/typedefs.h"
> +#include "qapi/error.h"
> +
> +BlockBackend *blk_new(const char *name, Error **errp);
> +void blk_ref(BlockBackend *blk);
> +void blk_unref(BlockBackend *blk);
> +const char *blk_name(BlockBackend *blk);
> +BlockBackend *blk_by_name(const char *name);
> +BlockBackend *blk_next(BlockBackend *blk);
> +
> +#endif
> diff --git a/qemu-img.c b/qemu-img.c
> index 4490a22..bad3f64 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c

Won't comment on each hunk in qemu-img, but in many cases, on
bdrv_new_open() failure, blk is leaked.

> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index a56ebfc..94b9b49 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -17,7 +17,7 @@
>   */
>  
>  #include "qemu-common.h"
> -#include "block/block.h"
> +#include "sysemu/block-backend.h"
>  #include "block/block_int.h"
>  #include "block/nbd.h"
>  #include "qemu/main-loop.h"
> @@ -687,6 +687,7 @@ int main(int argc, char **argv)
>          drv = NULL;
>      }
>  
> +    blk_new("hda", &error_abort);
>      bs = bdrv_new_named("hda", &error_abort);
>  
>      srcpath = argv[optind];

Where is the matching blk_unref?

Kevin

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 05/23] block: Make BlockBackend own its BlockDriverState
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 05/23] block: Make BlockBackend own its BlockDriverState Markus Armbruster
@ 2014-09-10 10:14   ` Kevin Wolf
  2014-09-11 18:38     ` Markus Armbruster
  0 siblings, 1 reply; 76+ messages in thread
From: Kevin Wolf @ 2014-09-10 10:14 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: benoit.canet, famz, qemu-devel, stefanha

Am 10.09.2014 um 10:13 hat Markus Armbruster geschrieben:
> On BlockBackend destruction, unref its BlockDriverState.  Replaces the
> callers' unrefs.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block/block-backend.c |  9 ++-------
>  blockdev.c            | 11 +++--------
>  hw/block/xen_disk.c   |  6 +++---
>  qemu-img.c            | 35 +----------------------------------
>  qemu-io.c             |  5 -----
>  5 files changed, 9 insertions(+), 57 deletions(-)
> 
> diff --git a/block/block-backend.c b/block/block-backend.c
> index 2a22660..ae51f7f 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -58,10 +58,7 @@ BlockBackend *blk_new(const char *name, Error **errp)
>   * @errp: return location for an error to be set on failure, or %NULL
>   *
>   * Create a new BlockBackend, with a reference count of one, and
> - * attach a new BlockDriverState to it, also with a reference count of
> - * one.  Caller owns *both* references.
> - * TODO Let caller own only the BlockBackend reference
> - * Fail if @name already exists.
> + * a new BlockDriverState attached.  Fail if @name already exists.
>   *
>   * Returns: the BlockBackend on success, %NULL on error
>   */
> @@ -88,6 +85,7 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp)
>  static void blk_delete(BlockBackend *blk)
>  {
>      assert(!blk->refcnt);
> +    bdrv_unref(blk->bs);
>      blk_detach_bs(blk);

I think the bdrv_unref() should really be part of blk_detach_bs().

The same way it would be more logical to have bdrv_ref() as part of
blk_attach_bs(). For blk_new_with_bs() this might mean bdrv_new,
blk_attach_bs, bdrv_unref, which looks a bit odd, but if blk_attach_bs()
is ever called from somewhere else, it probably makes more sense (if it
isn't, it should be static).

Kevin

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new()
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new() Markus Armbruster
@ 2014-09-10 11:03   ` Benoît Canet
  2014-09-10 15:05     ` Eric Blake
  2014-09-11  8:29     ` Markus Armbruster
  2014-09-10 15:07   ` Eric Blake
                     ` (3 subsequent siblings)
  4 siblings, 2 replies; 76+ messages in thread
From: Benoît Canet @ 2014-09-10 11:03 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:30 (+0200), Markus Armbruster wrote :
> Creating an anonymous BDS can't fail.  Make that obvious.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block.c               | 26 +++++++++++++++++++-------
>  block/iscsi.c         |  2 +-
>  block/vvfat.c         |  2 +-
>  blockdev.c            |  2 +-
>  hw/block/xen_disk.c   |  2 +-
>  include/block/block.h |  3 ++-
>  qemu-img.c            |  6 +++---
>  qemu-io.c             |  2 +-
>  qemu-nbd.c            |  2 +-
>  9 files changed, 30 insertions(+), 17 deletions(-)
> 
> diff --git a/block.c b/block.c
> index d06dd51..4b3bcd4 100644
> --- a/block.c
> +++ b/block.c
> @@ -335,10 +335,11 @@ void bdrv_register(BlockDriver *bdrv)
>  }
>  
>  /* create a new block device (by default it is empty) */
> -BlockDriverState *bdrv_new(const char *device_name, Error **errp)
> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
>  {
>      BlockDriverState *bs;
> -    int i;
> +
> +    assert(*device_name);

This assert that device_name is not a null pointer.
But here we are pretty sure that the BDS should be named given the name of the function.
Should we bake an assert on device_name[0] != '\0' to avoid bdrv_new_named being called
with "" as device_name ?

>  
>      if (bdrv_find(device_name)) {
>          error_setg(errp, "Device with id '%s' already exists",
> @@ -351,12 +352,23 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
>          return NULL;
>      }
>  
> -    bs = g_new0(BlockDriverState, 1);
> -    QLIST_INIT(&bs->dirty_bitmaps);
> +    bs = bdrv_new();
> +
>      pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);

>      if (device_name[0] != '\0') {
Then we could remove this test.

>          QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
Because here would be too late anyway: an unammed BDS would have been created if device_name == "".


>      }
> +
> +    return bs;
> +}
> +
> +BlockDriverState *bdrv_new(void)
> +{
> +    BlockDriverState *bs;
> +    int i;
> +
> +    bs = g_new0(BlockDriverState, 1);
> +    QLIST_INIT(&bs->dirty_bitmaps);
>      for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
>          QLIST_INIT(&bs->op_blockers[i]);
>      }
> @@ -1217,7 +1229,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
>          goto free_exit;
>      }
>  
> -    backing_hd = bdrv_new("", errp);
> +    backing_hd = bdrv_new();
>  
>      if (bs->backing_format[0] != '\0') {
>          back_drv = bdrv_find_format(bs->backing_format);
> @@ -1346,7 +1358,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
>      qdict_put(snapshot_options, "file.filename",
>                qstring_from_str(tmp_filename));
>  
> -    bs_snapshot = bdrv_new("", &error_abort);
> +    bs_snapshot = bdrv_new();
>  
>      ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
>                      flags, bdrv_qcow2, &local_err);
> @@ -1417,7 +1429,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
>      if (*pbs) {
>          bs = *pbs;
>      } else {
> -        bs = bdrv_new("", &error_abort);
> +        bs = bdrv_new();
>      }
>  
>      /* NULL means an empty set of options */
> diff --git a/block/iscsi.c b/block/iscsi.c
> index 3e19202..af3d0f6 100644
> --- a/block/iscsi.c
> +++ b/block/iscsi.c
> @@ -1528,7 +1528,7 @@ static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
>      IscsiLun *iscsilun = NULL;
>      QDict *bs_options;
>  
> -    bs = bdrv_new("", &error_abort);
> +    bs = bdrv_new();
>  
>      /* Read out options */
>      total_size =
> diff --git a/block/vvfat.c b/block/vvfat.c
> index 731e591..6c9fde0 100644
> --- a/block/vvfat.c
> +++ b/block/vvfat.c
> @@ -2939,7 +2939,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
>      unlink(s->qcow_filename);
>  #endif
>  
> -    bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort));
> +    bdrv_set_backing_hd(s->bs, bdrv_new());
>      s->bs->backing_hd->drv = &vvfat_write_target;
>      s->bs->backing_hd->opaque = g_new(void *, 1);
>      *(void**)s->bs->backing_hd->opaque = s;
> diff --git a/blockdev.c b/blockdev.c
> index e919566..9fbd888 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -458,7 +458,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      /* init */
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
> -    dinfo->bdrv = bdrv_new(dinfo->id, &error);
> +    dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
>      if (error) {
>          error_propagate(errp, error);
>          goto bdrv_new_err;
> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> index 2dcef07..8bac7ff 100644
> --- a/hw/block/xen_disk.c
> +++ b/hw/block/xen_disk.c
> @@ -856,7 +856,7 @@ static int blk_connect(struct XenDevice *xendev)
>  
>          /* setup via xenbus -> create new block driver instance */
>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
> -        blkdev->bs = bdrv_new(blkdev->dev, NULL);
> +        blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
>          if (!blkdev->bs) {
>              return -1;
>          }
> diff --git a/include/block/block.h b/include/block/block.h
> index 8f4ad16..95139c0 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -203,7 +203,8 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
>  int bdrv_create(BlockDriver *drv, const char* filename,
>                  QemuOpts *opts, Error **errp);
>  int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
> -BlockDriverState *bdrv_new(const char *device_name, Error **errp);
> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp);
> +BlockDriverState *bdrv_new(void);
>  void bdrv_make_anon(BlockDriverState *bs);
>  void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
>  void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
> diff --git a/qemu-img.c b/qemu-img.c
> index 91d1ac3..4490a22 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -296,7 +296,7 @@ static BlockDriverState *bdrv_new_open(const char *id,
>      Error *local_err = NULL;
>      int ret;
>  
> -    bs = bdrv_new(id, &error_abort);
> +    bs = bdrv_new_named(id, &error_abort);
>  
>      if (fmt) {
>          drv = bdrv_find_format(fmt);
> @@ -2425,7 +2425,7 @@ static int img_rebase(int argc, char **argv)
>      if (!unsafe) {
>          char backing_name[1024];
>  
> -        bs_old_backing = bdrv_new("old_backing", &error_abort);
> +        bs_old_backing = bdrv_new_named("old_backing", &error_abort);
>          bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
>          ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
>                          old_backing_drv, &local_err);
> @@ -2436,7 +2436,7 @@ static int img_rebase(int argc, char **argv)
>              goto out;
>          }
>          if (out_baseimg[0]) {
> -            bs_new_backing = bdrv_new("new_backing", &error_abort);
> +            bs_new_backing = bdrv_new_named("new_backing", &error_abort);
>              ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
>                              new_backing_drv, &local_err);
>              if (ret) {
> diff --git a/qemu-io.c b/qemu-io.c
> index d2ab694..44c2e1c 100644
> --- a/qemu-io.c
> +++ b/qemu-io.c
> @@ -58,7 +58,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
>          return 1;
>      }
>  
> -    qemuio_bs = bdrv_new("hda", &error_abort);
> +    qemuio_bs = bdrv_new_named("hda", &error_abort);
>  
>      if (growable) {
>          flags |= BDRV_O_PROTOCOL;
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index 9bc152e..a56ebfc 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -687,7 +687,7 @@ int main(int argc, char **argv)
>          drv = NULL;
>      }
>  
> -    bs = bdrv_new("hda", &error_abort);
> +    bs = bdrv_new_named("hda", &error_abort);
>  
>      srcpath = argv[optind];
>      ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
> -- 
> 1.9.3
> 
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 02/23] block: New BlockBackend Markus Armbruster
  2014-09-10  9:56   ` Kevin Wolf
@ 2014-09-10 11:34   ` Benoît Canet
  2014-09-10 11:44     ` Kevin Wolf
  2014-09-11 10:11     ` Markus Armbruster
  2014-09-10 12:40   ` Benoît Canet
  2 siblings, 2 replies; 76+ messages in thread
From: Benoît Canet @ 2014-09-10 11:34 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:31 (+0200), Markus Armbruster wrote :
> A block device consists of a frontend device model and a backend.
> 
> A block backend has a tree of block drivers doing the actual work.
> The tree is managed by the block layer.
> 
> We currently use a single abstraction BlockDriverState both for tree
> nodes and the backend as a whole.  Drawbacks:
> 
> * Its API includes both stuff that makes sense only at the block
>   backend level (root of the tree) and stuff that's only for use
>   within the block layer.  This makes the API bigger and more complex
>   than necessary.  Moreover, it's not obvious which interfaces are
>   meant for device models, and which really aren't.
> 
> * Since device models keep a reference to their backend, the backend
>   object can't just be destroyed.  But for media change, we need to
>   replace the tree.  Our solution is to make the BlockDriverState
>   generic, with actual driver state in a separate object, pointed to
>   by member opaque.  That lets us replace the tree by deinitializing
>   and reinitializing its root.  This special need of the root makes
>   the data structure awkward everywhere in the tree.
> 
> The general plan is to separate the APIs into "block backend", for use
> by device models, monitor and whatever other code dealing with block
> backends, and "block driver", for use by the block layer and whatever
> other code (if any) dealing with trees and tree nodes.
> 
> Code dealing with block backends, device models in particular, should
> become completely oblivious of BlockDriverState.  This should let us
> clean up both APIs, and the tree data structures.
> 
> This commit is a first step.  It creates a minimal "block backend"
> API: type BlockBackend and functions to create, destroy and find them.
> BlockBackend objects are created and destroyed, but not yet used for
> anything; that'll come shortly.
> 
> BlockBackend is reference-counted.  Its reference count never exceeds
> one so far, but that's going to change.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block/Makefile.objs            |   2 +-
>  block/block-backend.c          | 110 +++++++++++++++++++++++++++++++++++++++++
>  blockdev.c                     |  10 +++-
>  hw/block/xen_disk.c            |  11 +++++
>  include/qemu/typedefs.h        |   1 +
>  include/sysemu/block-backend.h |  26 ++++++++++
>  qemu-img.c                     |  46 +++++++++++++++++
>  qemu-io.c                      |   8 +++
>  qemu-nbd.c                     |   3 +-
>  9 files changed, 214 insertions(+), 3 deletions(-)
>  create mode 100644 block/block-backend.c
>  create mode 100644 include/sysemu/block-backend.h
> 
> diff --git a/block/Makefile.objs b/block/Makefile.objs
> index f45f939..a70140b 100644
> --- a/block/Makefile.objs
> +++ b/block/Makefile.objs
> @@ -5,7 +5,7 @@ block-obj-y += qed-check.o
>  block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
>  block-obj-$(CONFIG_QUORUM) += quorum.o
>  block-obj-y += parallels.o blkdebug.o blkverify.o
> -block-obj-y += snapshot.o qapi.o
> +block-obj-y += block-backend.o snapshot.o qapi.o
>  block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
>  block-obj-$(CONFIG_POSIX) += raw-posix.o
>  block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
> diff --git a/block/block-backend.c b/block/block-backend.c
> new file mode 100644
> index 0000000..833f7d9
> --- /dev/null
> +++ b/block/block-backend.c
> @@ -0,0 +1,110 @@
> +/*
> + * QEMU Block backends
> + *
> + * Copyright (C) 2014 Red Hat, Inc.
> + *
> + * Authors:
> + *  Markus Armbruster <armbru@redhat.com>,
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * later.  See the COPYING file in the top-level directory.
> + */
> +
> +#include "sysemu/block-backend.h"
> +#include "block/block_int.h"
> +
> +struct BlockBackend {
> +    char *name;
> +    int refcnt;
> +    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
> +};
> +
> +static QTAILQ_HEAD(, BlockBackend) blk_backends =
> +    QTAILQ_HEAD_INITIALIZER(blk_backends);
> +
> +/**
> + * blk_new:
> + * @name: name, must not be %NULL or empty
> + * @errp: return location for an error to be set on failure, or %NULL
> + *
> + * Create a new BlockBackend, with a reference count of one.  Fail if
> + * @name already exists.
> + *
> + * Returns: the BlockBackend on success, %NULL on failure
> + */
> +BlockBackend *blk_new(const char *name, Error **errp)

I am responding for the easy part first.

So here the blockbackend is identified by a name

> +{
> +    BlockBackend *blk = g_new0(BlockBackend, 1);
> +
> +    assert(name && name[0]);
> +    if (blk_by_name(name)) {

> +        error_setg(errp, "Device with id '%s' already exists", name);

But here is it an id or a name ?
Do we need to make a choice everywhere in the code between id and name ?

> +        return NULL;
> +    }
> +    blk->name = g_strdup(name);
> +    blk->refcnt = 1;
> +    QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
> +    return blk;
> +}
> +
> +static void blk_delete(BlockBackend *blk)
> +{
> +    assert(!blk->refcnt);
> +    QTAILQ_REMOVE(&blk_backends, blk, link);
> +    g_free(blk->name);
> +    g_free(blk);
> +}
> +
> +/**
> + * blk_ref:
> + *
> + * Increment @blk's reference count.
> + */
> +void blk_ref(BlockBackend *blk)
> +{

if blk_unref you take care of doing
+    if (blk) {
to make sur the user does not pass a NULL pointer.
Transforming blk into a NULL pointer is not a side effect
of blk_unref so this test is designed to prevent a user
brain damage.

If the user can be brain damaged to pass a NULL to blk_unref he
could be equally stupid passing a NULL to blk_ref.
Why not adding the same test here ?


> +    blk->refcnt++;
> +}
> +
> +/**
> + * blk_unref:
> + *
> + * Decrement @blk's reference count.  If this drops it to zero,
> + * destroy @blk.
> + */
> +void blk_unref(BlockBackend *blk)
> +{
> +    if (blk) {
> +        g_assert(blk->refcnt > 0);
> +        if (!--blk->refcnt) {
> +            blk_delete(blk);
> +        }
> +    }
> +}
> +
> +const char *blk_name(BlockBackend *blk)
> +{
> +    return blk->name;
> +}
> +
> +BlockBackend *blk_by_name(const char *name)
> +{
> +    BlockBackend *blk;
> +
> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
> +        if (!strcmp(name, blk->name)) {
> +            return blk;
> +        }
> +    }
> +    return NULL;
> +}
> +
> +/**
> + * blk_next:
> + *
> + * Returns: the first BlockBackend if @blk is null, else @blk's next
> + * sibling, which is %NULL for the last BlockBackend
> + */
> +BlockBackend *blk_next(BlockBackend *blk)
> +{
> +    return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
> +}
> diff --git a/blockdev.c b/blockdev.c
> index 9fbd888..86596bc 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -30,6 +30,7 @@
>   * THE SOFTWARE.
>   */
>  
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/block/block.h"
>  #include "block/blockjob.h"
> @@ -221,6 +222,7 @@ void drive_del(DriveInfo *dinfo)
>      }
>  
>      bdrv_unref(dinfo->bdrv);
> +    blk_unref(blk_by_name(dinfo->id));

Really the mix of name and id is odd.

>      g_free(dinfo->id);
>      QTAILQ_REMOVE(&drives, dinfo, next);
>      g_free(dinfo->serial);
> @@ -301,6 +303,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      int ro = 0;
>      int bdrv_flags = 0;
>      int on_read_error, on_write_error;
> +    BlockBackend *blk;
>      DriveInfo *dinfo;
>      ThrottleConfig cfg;
>      int snapshot = 0;
> @@ -456,6 +459,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      }
>  
>      /* init */
> +    blk = blk_new(qemu_opts_id(opts), errp);
> +    if (!blk) {
> +        goto early_err;
> +    }
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
>      dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
> @@ -525,6 +532,7 @@ err:
>  bdrv_new_err:
>      g_free(dinfo->id);
>      g_free(dinfo);
> +    blk_unref(blk);
>  early_err:
>      qemu_opts_del(opts);
>  err_no_opts:
> @@ -1770,7 +1778,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>       */
>      if (bdrv_get_attached_dev(bs)) {
>          bdrv_make_anon(bs);
> -
> +        blk_unref(blk_by_name(id));
>          /* Further I/O must not pause the guest */
>          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
>                            BLOCKDEV_ON_ERROR_REPORT);
> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> index 8bac7ff..730a021 100644
> --- a/hw/block/xen_disk.c
> +++ b/hw/block/xen_disk.c
> @@ -39,6 +39,7 @@
>  #include "hw/xen/xen_backend.h"
>  #include "xen_blkif.h"
>  #include "sysemu/blockdev.h"
> +#include "sysemu/block-backend.h"
>  
>  /* ------------------------------------------------------------- */
>  
> @@ -852,12 +853,18 @@ static int blk_connect(struct XenDevice *xendev)
>      blkdev->dinfo = drive_get(IF_XEN, 0, index);
>      if (!blkdev->dinfo) {
>          Error *local_err = NULL;
> +        BlockBackend *blk;
>          BlockDriver *drv;
>  
>          /* setup via xenbus -> create new block driver instance */
>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
> +        blk = blk_new(blkdev->dev, NULL);
> +        if (!blk) {
> +            return -1;
> +        }
>          blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
>          if (!blkdev->bs) {
> +            blk_unref(blk);
>              return -1;
>          }
>  
> @@ -868,6 +875,7 @@ static int blk_connect(struct XenDevice *xendev)
>                            error_get_pretty(local_err));
>              error_free(local_err);
>              bdrv_unref(blkdev->bs);
> +            blk_unref(blk);
>              blkdev->bs = NULL;
>              return -1;
>          }
> @@ -983,6 +991,9 @@ static void blk_disconnect(struct XenDevice *xendev)
>      if (blkdev->bs) {
>          bdrv_detach_dev(blkdev->bs, blkdev);
>          bdrv_unref(blkdev->bs);
> +        if (!blkdev->dinfo) {
> +            blk_unref(blk_by_name(blkdev->dev));
> +        }
>          blkdev->bs = NULL;
>      }
>      xen_be_unbind_evtchn(&blkdev->xendev);
> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
> index 5f20b0e..198da2e 100644
> --- a/include/qemu/typedefs.h
> +++ b/include/qemu/typedefs.h
> @@ -35,6 +35,7 @@ typedef struct MachineClass MachineClass;
>  typedef struct NICInfo NICInfo;
>  typedef struct HCIInfo HCIInfo;
>  typedef struct AudioState AudioState;
> +typedef struct BlockBackend BlockBackend;
>  typedef struct BlockDriverState BlockDriverState;
>  typedef struct DriveInfo DriveInfo;
>  typedef struct DisplayState DisplayState;
> diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
> new file mode 100644
> index 0000000..3f8371c
> --- /dev/null
> +++ b/include/sysemu/block-backend.h
> @@ -0,0 +1,26 @@
> +/*
> + * QEMU Block backends
> + *
> + * Copyright (C) 2014 Red Hat, Inc.
> + *
> + * Authors:
> + *  Markus Armbruster <armbru@redhat.com>,
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * later.  See the COPYING file in the top-level directory.
> + */
> +
> +#ifndef BLOCK_BACKEND_H
> +#define BLOCK_BACKEND_H
> +
> +#include "qemu/typedefs.h"
> +#include "qapi/error.h"
> +
> +BlockBackend *blk_new(const char *name, Error **errp);
> +void blk_ref(BlockBackend *blk);
> +void blk_unref(BlockBackend *blk);
> +const char *blk_name(BlockBackend *blk);
> +BlockBackend *blk_by_name(const char *name);
> +BlockBackend *blk_next(BlockBackend *blk);
> +
> +#endif
> diff --git a/qemu-img.c b/qemu-img.c
> index 4490a22..bad3f64 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -29,6 +29,7 @@
>  #include "qemu/error-report.h"
>  #include "qemu/osdep.h"
>  #include "sysemu/sysemu.h"
> +#include "sysemu/block-backend.h"
>  #include "block/block_int.h"
>  #include "block/qapi.h"
>  #include <getopt.h>
> @@ -575,6 +576,7 @@ static int img_check(int argc, char **argv)
>      int c, ret;
>      OutputFormat output_format = OFORMAT_HUMAN;
>      const char *filename, *fmt, *output, *cache;
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      int fix = 0;
>      int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
> @@ -649,6 +651,7 @@ static int img_check(int argc, char **argv)
>          return 1;
>      }
>  
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>      if (!bs) {
>          return 1;
> @@ -710,6 +713,7 @@ static int img_check(int argc, char **argv)
>  fail:
>      qapi_free_ImageCheck(check);
>      bdrv_unref(bs);
> +    blk_unref(blk);
>  
>      return ret;
>  }
> @@ -718,6 +722,7 @@ static int img_commit(int argc, char **argv)
>  {
>      int c, ret, flags;
>      const char *filename, *fmt, *cache;
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      bool quiet = false;
>  
> @@ -756,6 +761,7 @@ static int img_commit(int argc, char **argv)
>          return 1;
>      }
>  
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>      if (!bs) {
>          return 1;
> @@ -780,6 +786,7 @@ static int img_commit(int argc, char **argv)
>      }
>  
>      bdrv_unref(bs);
> +    blk_unref(blk);
>      if (ret) {
>          return 1;
>      }
> @@ -942,6 +949,7 @@ static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
>  static int img_compare(int argc, char **argv)
>  {
>      const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
> +    BlockBackend *blk1, *blk2;
>      BlockDriverState *bs1, *bs2;
>      int64_t total_sectors1, total_sectors2;
>      uint8_t *buf1 = NULL, *buf2 = NULL;
> @@ -1011,6 +1019,7 @@ static int img_compare(int argc, char **argv)
>          goto out3;
>      }
>  
> +    blk1 = blk_new("image 1", &error_abort);
>      bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
>      if (!bs1) {
>          error_report("Can't open file %s", filename1);
> @@ -1018,6 +1027,7 @@ static int img_compare(int argc, char **argv)
>          goto out3;
>      }
>  
> +    blk2 = blk_new("image 2", &error_abort);
>      bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
>      if (!bs2) {
>          error_report("Can't open file %s", filename2);
> @@ -1184,10 +1194,12 @@ static int img_compare(int argc, char **argv)
>  
>  out:
>      bdrv_unref(bs2);
> +    blk_unref(blk2);
>      qemu_vfree(buf1);
>      qemu_vfree(buf2);
>  out2:
>      bdrv_unref(bs1);
> +    blk_unref(blk1);
>  out3:
>      qemu_progress_end();
>      return ret;
> @@ -1200,6 +1212,7 @@ static int img_convert(int argc, char **argv)
>      int progress = 0, flags, src_flags;
>      const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
>      BlockDriver *drv, *proto_drv;
> +    BlockBackend **blk = NULL, *out_blk = NULL;
>      BlockDriverState **bs = NULL, *out_bs = NULL;
>      int64_t total_sectors, nb_sectors, sector_num, bs_offset;
>      int64_t *bs_sectors = NULL;
> @@ -1354,6 +1367,7 @@ static int img_convert(int argc, char **argv)
>  
>      qemu_progress_print(0, 100);
>  
> +    blk = g_new0(BlockBackend *, bs_n);
>      bs = g_new0(BlockDriverState *, bs_n);
>      bs_sectors = g_new(int64_t, bs_n);
>  
> @@ -1361,6 +1375,7 @@ static int img_convert(int argc, char **argv)
>      for (bs_i = 0; bs_i < bs_n; bs_i++) {
>          char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
>                              : g_strdup("source");
> +        blk[bs_i] = blk_new(id, &error_abort);
>          bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
>                                   true, quiet);
>          g_free(id);
> @@ -1486,6 +1501,7 @@ static int img_convert(int argc, char **argv)
>          goto out;
>      }
>  
> +    out_blk = blk_new("target", &error_abort);
>      out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
>      if (!out_bs) {
>          ret = -1;
> @@ -1742,6 +1758,7 @@ out:
>      if (out_bs) {
>          bdrv_unref(out_bs);
>      }
> +    blk_unref(out_blk);
>      if (bs) {
>          for (bs_i = 0; bs_i < bs_n; bs_i++) {
>              if (bs[bs_i]) {
> @@ -1750,6 +1767,12 @@ out:
>          }
>          g_free(bs);
>      }
> +    if (blk) {
> +        for (bs_i = 0; bs_i < bs_n; bs_i++) {
> +            blk_unref(blk[bs_i]);
> +        }
> +        g_free(blk);
> +    }
>      g_free(bs_sectors);
>  fail_getopt:
>      g_free(options);
> @@ -1858,6 +1881,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>      filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
>  
>      while (filename) {
> +        BlockBackend *blk;
>          BlockDriverState *bs;
>          ImageInfo *info;
>          ImageInfoList *elem;
> @@ -1869,6 +1893,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>          }
>          g_hash_table_insert(filenames, (gpointer)filename, NULL);
>  
> +        blk = blk_new("image", &error_abort);
>          bs = bdrv_new_open("image", filename, fmt,
>                             BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
>          if (!bs) {
> @@ -1880,6 +1905,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>              error_report("%s", error_get_pretty(err));
>              error_free(err);
>              bdrv_unref(bs);
> +            blk_unref(blk);
>              goto err;
>          }
>  
> @@ -1889,6 +1915,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>          last = &elem->next;
>  
>          bdrv_unref(bs);
> +        blk_unref(blk);
>  
>          filename = fmt = NULL;
>          if (chain) {
> @@ -2082,6 +2109,7 @@ static int img_map(int argc, char **argv)
>  {
>      int c;
>      OutputFormat output_format = OFORMAT_HUMAN;
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      const char *filename, *fmt, *output;
>      int64_t length;
> @@ -2130,6 +2158,7 @@ static int img_map(int argc, char **argv)
>          return 1;
>      }
>  
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
>      if (!bs) {
>          return 1;
> @@ -2175,6 +2204,7 @@ static int img_map(int argc, char **argv)
>  
>  out:
>      bdrv_unref(bs);
> +    blk_unref(blk);
>      return ret < 0;
>  }
>  
> @@ -2185,6 +2215,7 @@ out:
>  
>  static int img_snapshot(int argc, char **argv)
>  {
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      QEMUSnapshotInfo sn;
>      char *filename, *snapshot_name = NULL;
> @@ -2250,6 +2281,7 @@ static int img_snapshot(int argc, char **argv)
>      filename = argv[optind++];
>  
>      /* Open the image */
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
>      if (!bs) {
>          return 1;
> @@ -2297,6 +2329,7 @@ static int img_snapshot(int argc, char **argv)
>  
>      /* Cleanup */
>      bdrv_unref(bs);
> +    blk_unref(blk);
>      if (ret) {
>          return 1;
>      }
> @@ -2305,6 +2338,7 @@ static int img_snapshot(int argc, char **argv)
>  
>  static int img_rebase(int argc, char **argv)
>  {
> +    BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL;
>      BlockDriverState *bs = NULL, *bs_old_backing = NULL, *bs_new_backing = NULL;
>      BlockDriver *old_backing_drv, *new_backing_drv;
>      char *filename;
> @@ -2393,6 +2427,7 @@ static int img_rebase(int argc, char **argv)
>       * Ignore the old backing file for unsafe rebase in case we want to correct
>       * the reference to a renamed or moved backing file.
>       */
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>      if (!bs) {
>          ret = -1;
> @@ -2425,6 +2460,7 @@ static int img_rebase(int argc, char **argv)
>      if (!unsafe) {
>          char backing_name[1024];
>  
> +        blk_old_backing = blk_new("old_backing", &error_abort);
>          bs_old_backing = bdrv_new_named("old_backing", &error_abort);
>          bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
>          ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
> @@ -2436,6 +2472,7 @@ static int img_rebase(int argc, char **argv)
>              goto out;
>          }
>          if (out_baseimg[0]) {
> +            blk_new_backing = blk_new("new_backing", &error_abort);
>              bs_new_backing = bdrv_new_named("new_backing", &error_abort);
>              ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
>                              new_backing_drv, &local_err);
> @@ -2614,12 +2651,15 @@ out:
>          if (bs_old_backing != NULL) {
>              bdrv_unref(bs_old_backing);
>          }
> +        blk_unref(blk_old_backing);
>          if (bs_new_backing != NULL) {
>              bdrv_unref(bs_new_backing);
>          }
> +        blk_unref(blk_new_backing);
>      }
>  
>      bdrv_unref(bs);
> +    blk_unref(blk);
>      if (ret) {
>          return 1;
>      }
> @@ -2632,6 +2672,7 @@ static int img_resize(int argc, char **argv)
>      const char *filename, *fmt, *size;
>      int64_t n, total_size;
>      bool quiet = false;
> +    BlockBackend *blk = NULL;
>      BlockDriverState *bs = NULL;
>      QemuOpts *param;
>      static QemuOptsList resize_options = {
> @@ -2708,6 +2749,7 @@ static int img_resize(int argc, char **argv)
>      n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
>      qemu_opts_del(param);
>  
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
>                         true, quiet);
>      if (!bs) {
> @@ -2745,6 +2787,7 @@ out:
>      if (bs) {
>          bdrv_unref(bs);
>      }
> +    blk_unref(blk);
>      if (ret) {
>          return 1;
>      }
> @@ -2760,6 +2803,7 @@ static int img_amend(int argc, char **argv)
>      const char *fmt = NULL, *filename, *cache;
>      int flags;
>      bool quiet = false;
> +    BlockBackend *blk = NULL;
>      BlockDriverState *bs = NULL;
>  
>      cache = BDRV_DEFAULT_CACHE;
> @@ -2823,6 +2867,7 @@ static int img_amend(int argc, char **argv)
>          goto out;
>      }
>  
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>      if (!bs) {
>          error_report("Could not open image '%s'", filename);
> @@ -2856,6 +2901,7 @@ out:
>      if (bs) {
>          bdrv_unref(bs);
>      }
> +    blk_unref(blk);
>      qemu_opts_del(opts);
>      qemu_opts_free(create_opts);
>      g_free(options);
> diff --git a/qemu-io.c b/qemu-io.c
> index 44c2e1c..45e5494 100644
> --- a/qemu-io.c
> +++ b/qemu-io.c
> @@ -19,6 +19,7 @@
>  #include "qemu/option.h"
>  #include "qemu/config-file.h"
>  #include "qemu/readline.h"
> +#include "sysemu/block-backend.h"
>  #include "block/block_int.h"
>  #include "trace/control.h"
>  
> @@ -26,6 +27,7 @@
>  
>  static char *progname;
>  
> +static BlockBackend *qemuio_blk;
>  static BlockDriverState *qemuio_bs;
>  
>  /* qemu-io commands passed using -c */
> @@ -37,7 +39,9 @@ static ReadLineState *readline_state;
>  static int close_f(BlockDriverState *bs, int argc, char **argv)
>  {
>      bdrv_unref(bs);
> +    blk_unref(qemuio_blk);
>      qemuio_bs = NULL;
> +    qemuio_blk = NULL;
>      return 0;
>  }
>  
> @@ -58,6 +62,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
>          return 1;
>      }
>  
> +    qemuio_blk = blk_new("hda", &error_abort);
>      qemuio_bs = bdrv_new_named("hda", &error_abort);
>  
>      if (growable) {
> @@ -70,7 +75,9 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
>                  error_get_pretty(local_err));
>          error_free(local_err);
>          bdrv_unref(qemuio_bs);
> +        blk_unref(qemuio_blk);
>          qemuio_bs = NULL;
> +        qemuio_blk = NULL;
>          return 1;
>      }
>  
> @@ -479,6 +486,7 @@ int main(int argc, char **argv)
>      if (qemuio_bs) {
>          bdrv_unref(qemuio_bs);
>      }
> +    blk_unref(qemuio_blk);
>      g_free(readline_state);
>      return 0;
>  }
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index a56ebfc..94b9b49 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -17,7 +17,7 @@
>   */
>  
>  #include "qemu-common.h"
> -#include "block/block.h"
> +#include "sysemu/block-backend.h"
>  #include "block/block_int.h"
>  #include "block/nbd.h"
>  #include "qemu/main-loop.h"
> @@ -687,6 +687,7 @@ int main(int argc, char **argv)
>          drv = NULL;
>      }
>  
> +    blk_new("hda", &error_abort);
>      bs = bdrv_new_named("hda", &error_abort);
>  
>      srcpath = argv[optind];
> -- 
> 1.9.3
> 
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10 11:34   ` Benoît Canet
@ 2014-09-10 11:44     ` Kevin Wolf
  2014-09-10 11:51       ` Benoît Canet
  2014-09-11 10:11     ` Markus Armbruster
  1 sibling, 1 reply; 76+ messages in thread
From: Kevin Wolf @ 2014-09-10 11:44 UTC (permalink / raw)
  To: Benoît Canet; +Cc: famz, Markus Armbruster, stefanha, qemu-devel

Am 10.09.2014 um 13:34 hat Benoît Canet geschrieben:
> The Wednesday 10 Sep 2014 à 10:13:31 (+0200), Markus Armbruster wrote :
> > A block device consists of a frontend device model and a backend.
> > 
> > A block backend has a tree of block drivers doing the actual work.
> > The tree is managed by the block layer.
> > 
> > We currently use a single abstraction BlockDriverState both for tree
> > nodes and the backend as a whole.  Drawbacks:
> > 
> > * Its API includes both stuff that makes sense only at the block
> >   backend level (root of the tree) and stuff that's only for use
> >   within the block layer.  This makes the API bigger and more complex
> >   than necessary.  Moreover, it's not obvious which interfaces are
> >   meant for device models, and which really aren't.
> > 
> > * Since device models keep a reference to their backend, the backend
> >   object can't just be destroyed.  But for media change, we need to
> >   replace the tree.  Our solution is to make the BlockDriverState
> >   generic, with actual driver state in a separate object, pointed to
> >   by member opaque.  That lets us replace the tree by deinitializing
> >   and reinitializing its root.  This special need of the root makes
> >   the data structure awkward everywhere in the tree.
> > 
> > The general plan is to separate the APIs into "block backend", for use
> > by device models, monitor and whatever other code dealing with block
> > backends, and "block driver", for use by the block layer and whatever
> > other code (if any) dealing with trees and tree nodes.
> > 
> > Code dealing with block backends, device models in particular, should
> > become completely oblivious of BlockDriverState.  This should let us
> > clean up both APIs, and the tree data structures.
> > 
> > This commit is a first step.  It creates a minimal "block backend"
> > API: type BlockBackend and functions to create, destroy and find them.
> > BlockBackend objects are created and destroyed, but not yet used for
> > anything; that'll come shortly.
> > 
> > BlockBackend is reference-counted.  Its reference count never exceeds
> > one so far, but that's going to change.
> > 
> > Signed-off-by: Markus Armbruster <armbru@redhat.com>

> > +/**
> > + * blk_ref:
> > + *
> > + * Increment @blk's reference count.
> > + */
> > +void blk_ref(BlockBackend *blk)
> > +{
> 
> if blk_unref you take care of doing
> +    if (blk) {
> to make sur the user does not pass a NULL pointer.
> Transforming blk into a NULL pointer is not a side effect
> of blk_unref so this test is designed to prevent a user
> brain damage.

Not really, I'd rather consider it a convenience feature, just like
you're allowed to call free(NULL) or bdrv_unref(NULL) without having a
check for != NULL everywhere. This will be handy especially in error
paths.

> If the user can be brain damaged to pass a NULL to blk_unref he
> could be equally stupid passing a NULL to blk_ref.
> Why not adding the same test here ?

Whereas in blk_ref() it really wouldn't make any sense.

Kevin

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10 11:44     ` Kevin Wolf
@ 2014-09-10 11:51       ` Benoît Canet
  0 siblings, 0 replies; 76+ messages in thread
From: Benoît Canet @ 2014-09-10 11:51 UTC (permalink / raw)
  To: Kevin Wolf
  Cc: Benoît Canet, famz, Markus Armbruster, stefanha, qemu-devel

The Wednesday 10 Sep 2014 à 13:44:17 (+0200), Kevin Wolf wrote :
> Am 10.09.2014 um 13:34 hat Benoît Canet geschrieben:
> > The Wednesday 10 Sep 2014 à 10:13:31 (+0200), Markus Armbruster wrote :
> > > A block device consists of a frontend device model and a backend.
> > > 
> > > A block backend has a tree of block drivers doing the actual work.
> > > The tree is managed by the block layer.
> > > 
> > > We currently use a single abstraction BlockDriverState both for tree
> > > nodes and the backend as a whole.  Drawbacks:
> > > 
> > > * Its API includes both stuff that makes sense only at the block
> > >   backend level (root of the tree) and stuff that's only for use
> > >   within the block layer.  This makes the API bigger and more complex
> > >   than necessary.  Moreover, it's not obvious which interfaces are
> > >   meant for device models, and which really aren't.
> > > 
> > > * Since device models keep a reference to their backend, the backend
> > >   object can't just be destroyed.  But for media change, we need to
> > >   replace the tree.  Our solution is to make the BlockDriverState
> > >   generic, with actual driver state in a separate object, pointed to
> > >   by member opaque.  That lets us replace the tree by deinitializing
> > >   and reinitializing its root.  This special need of the root makes
> > >   the data structure awkward everywhere in the tree.
> > > 
> > > The general plan is to separate the APIs into "block backend", for use
> > > by device models, monitor and whatever other code dealing with block
> > > backends, and "block driver", for use by the block layer and whatever
> > > other code (if any) dealing with trees and tree nodes.
> > > 
> > > Code dealing with block backends, device models in particular, should
> > > become completely oblivious of BlockDriverState.  This should let us
> > > clean up both APIs, and the tree data structures.
> > > 
> > > This commit is a first step.  It creates a minimal "block backend"
> > > API: type BlockBackend and functions to create, destroy and find them.
> > > BlockBackend objects are created and destroyed, but not yet used for
> > > anything; that'll come shortly.
> > > 
> > > BlockBackend is reference-counted.  Its reference count never exceeds
> > > one so far, but that's going to change.
> > > 
> > > Signed-off-by: Markus Armbruster <armbru@redhat.com>
> 
> > > +/**
> > > + * blk_ref:
> > > + *
> > > + * Increment @blk's reference count.
> > > + */
> > > +void blk_ref(BlockBackend *blk)
> > > +{
> > 
> > if blk_unref you take care of doing
> > +    if (blk) {
> > to make sur the user does not pass a NULL pointer.
> > Transforming blk into a NULL pointer is not a side effect
> > of blk_unref so this test is designed to prevent a user
> > brain damage.
> 
> Not really, I'd rather consider it a convenience feature, just like
> you're allowed to call free(NULL) or bdrv_unref(NULL) without having a
> check for != NULL everywhere. This will be handy especially in error
> paths.

ok I see the spirit of it.

Benoit
> 
> > If the user can be brain damaged to pass a NULL to blk_unref he
> > could be equally stupid passing a NULL to blk_ref.
> > Why not adding the same test here ?
> 
> Whereas in blk_ref() it really wouldn't make any sense.
> 
> Kevin
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState Markus Armbruster
@ 2014-09-10 11:55   ` Benoît Canet
  2014-09-11 10:52     ` Markus Armbruster
  2014-09-10 12:24   ` Kevin Wolf
  1 sibling, 1 reply; 76+ messages in thread
From: Benoît Canet @ 2014-09-10 11:55 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:32 (+0200), Markus Armbruster wrote :
> The pointer from BlockBackend to BlockDriverState is a strong
> reference, managed with bdrv_ref() / bdrv_unref(), the back-pointer is
> a weak one.
> 
> Convenience function blk_new_with_bs() creates a BlockBackend with its
> BlockDriverState.  Callers have to unref both.  The commit after next
> will relieve them of the need to unref the BlockDriverState.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block.c                        |  10 ++--
>  block/block-backend.c          |  79 +++++++++++++++++++++++++++++++
>  blockdev.c                     |  49 +++++++++++---------
>  hw/block/xen_disk.c            |   8 +---
>  include/block/block_int.h      |   2 +
>  include/sysemu/block-backend.h |   5 ++
>  qemu-img.c                     | 103 +++++++++++++++++++++--------------------
>  qemu-io.c                      |   4 +-
>  qemu-nbd.c                     |   3 +-
>  9 files changed, 175 insertions(+), 88 deletions(-)
> 
> diff --git a/block.c b/block.c
> index 4b3bcd4..a6c03da 100644
> --- a/block.c
> +++ b/block.c
> @@ -2032,7 +2032,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
>   * This will modify the BlockDriverState fields, and swap contents
>   * between bs_new and bs_old. Both bs_new and bs_old are modified.
>   *
> - * bs_new is required to be anonymous.
> + * bs_new must be nameless and not attached to a BlockBackend.

1)
Does "nameless" refer to device_name or node_name ?
>From the code I see it's device_name but the wording can be confusing.

maybe:
+ * bs_new must have an empty device_name and not be attached to a BlockBackend.


>   *
>   * This function does not create any image files.
>   */
> @@ -2051,8 +2051,9 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
>          QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list);
>      }
>  
> -    /* bs_new must be anonymous and shouldn't have anything fancy enabled */
> +    /* bs_new must be nameless and shouldn't have anything fancy enabled */
>      assert(bs_new->device_name[0] == '\0');
> +    assert(!bs_new->blk);
>      assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
>      assert(bs_new->job == NULL);
>      assert(bs_new->dev == NULL);
> @@ -2068,8 +2069,9 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
>      bdrv_move_feature_fields(bs_old, bs_new);
>      bdrv_move_feature_fields(bs_new, &tmp);
>  
> -    /* bs_new shouldn't be in bdrv_states even after the swap!  */
> +    /* bs_new must remain nameless and unattached */
Here the proximity get rid of the ambiguity so it's ok.

>      assert(bs_new->device_name[0] == '\0');
> +    assert(!bs_new->blk);
>  
>      /* Check a few fields that should remain attached to the device */
>      assert(bs_new->dev == NULL);
> @@ -2096,7 +2098,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
>   * This will modify the BlockDriverState fields, and swap contents
>   * between bs_new and bs_top. Both bs_new and bs_top are modified.
>   *
> - * bs_new is required to be anonymous.
> + * bs_new must be nameless and not attached to a BlockBackend.
See 1)

>   *
>   * This function does not create any image files.
>   */
> diff --git a/block/block-backend.c b/block/block-backend.c
> index 833f7d9..deccb54 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -16,6 +16,7 @@
>  struct BlockBackend {
>      char *name;
>      int refcnt;
> +    BlockDriverState *bs;
>      QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
>  };
>  
> @@ -47,9 +48,43 @@ BlockBackend *blk_new(const char *name, Error **errp)
>      return blk;
>  }
>  
> +/**
> + * blk_new_with_bs:
> + * @name: name, must not be %NULL or empty
> + * @errp: return location for an error to be set on failure, or %NULL
> + *
> + * Create a new BlockBackend, with a reference count of one, and
> + * attach a new BlockDriverState to it, also with a reference count of
> + * one.  Caller owns *both* references.
> + * TODO Let caller own only the BlockBackend reference
> + * Fail if @name already exists.
> + *
> + * Returns: the BlockBackend on success, %NULL on error
> + */
> +BlockBackend *blk_new_with_bs(const char *name, Error **errp)
> +{
> +    BlockBackend *blk;
> +    BlockDriverState *bs;
> +
> +    blk = blk_new(name, errp);
> +    if (!blk) {
> +        return NULL;
> +    }
> +
> +    bs = bdrv_new_named(name, errp);
> +    if (!bs) {
> +        blk_unref(blk);
> +        return NULL;
> +    }
> +
> +    blk_attach_bs(blk, bs);
> +    return blk;
> +}
> +
>  static void blk_delete(BlockBackend *blk)
>  {
>      assert(!blk->refcnt);
> +    blk_detach_bs(blk);
>      QTAILQ_REMOVE(&blk_backends, blk, link);
>      g_free(blk->name);
>      g_free(blk);
> @@ -70,6 +105,9 @@ void blk_ref(BlockBackend *blk)
>   *
>   * Decrement @blk's reference count.  If this drops it to zero,
>   * destroy @blk.
> + *
> + * Does *not* touch the attached BlockDriverState's reference count.
> + * TODO Decrement it!
>   */
>  void blk_unref(BlockBackend *blk)
>  {
> @@ -108,3 +146,44 @@ BlockBackend *blk_next(BlockBackend *blk)
>  {
>      return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
>  }
> +
> +/**
> + * blk_attach_bs:
> + *
> + * Attach @bs to @blk, taking over the caller's reference to @bs.
> + */
> +void blk_attach_bs(BlockBackend *blk, BlockDriverState *bs)
> +{
> +    assert(!blk->bs && !bs->blk);
> +    blk->bs = bs;
> +    bs->blk = blk;
> +}
> +
> +/**
> + * blk_bs:
> + *
> + * Returns: the BlockDriverState attached to @blk, or %NULL
> + */
> +BlockDriverState *blk_bs(BlockBackend *blk)
> +{
> +    return blk->bs;
> +}
> +
> +/**
> + * blk_detach_bs:
> + *
> + * Detach @blk's BlockDriverState, giving up its reference to the
> + * caller.
> + *
> + * Returns: the detached BlockDriverState
> + */
> +BlockDriverState *blk_detach_bs(BlockBackend *blk)
> +{
> +    BlockDriverState *bs = blk->bs;
> +
> +    if (bs) {
> +        bs->blk = NULL;
> +        blk->bs = NULL;
> +    }
> +    return bs;
> +}
> diff --git a/blockdev.c b/blockdev.c
> index 86596bc..0a0b95e 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -304,6 +304,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      int bdrv_flags = 0;
>      int on_read_error, on_write_error;
>      BlockBackend *blk;
> +    BlockDriverState *bs;
>      DriveInfo *dinfo;
>      ThrottleConfig cfg;
>      int snapshot = 0;
> @@ -459,30 +460,28 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      }
>  
>      /* init */
> -    blk = blk_new(qemu_opts_id(opts), errp);
> +    blk = blk_new_with_bs(qemu_opts_id(opts), errp);
>      if (!blk) {
>          goto early_err;
>      }
> +    bs = blk_bs(blk);
> +    bs->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
> +    bs->read_only = ro;
> +    bs->detect_zeroes = detect_zeroes;
> +
> +    bdrv_set_on_error(bs, on_read_error, on_write_error);
> +
> +    /* disk I/O throttling */
> +    if (throttle_enabled(&cfg)) {
> +        bdrv_io_limits_enable(bs);
> +        bdrv_set_io_limits(bs, &cfg);
> +    }
> +
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
> -    dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
> -    if (error) {
> -        error_propagate(errp, error);
> -        goto bdrv_new_err;
> -    }
> -    dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
> -    dinfo->bdrv->read_only = ro;
> -    dinfo->bdrv->detect_zeroes = detect_zeroes;
> +    dinfo->bdrv = bs;
>      QTAILQ_INSERT_TAIL(&drives, dinfo, next);
>  
> -    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
> -
> -    /* disk I/O throttling */
> -    if (throttle_enabled(&cfg)) {
> -        bdrv_io_limits_enable(dinfo->bdrv);
> -        bdrv_set_io_limits(dinfo->bdrv, &cfg);
> -    }
> -
>      if (!file || !*file) {
>          if (has_driver_specific_opts) {
>              file = NULL;
> @@ -509,7 +508,8 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
>  
>      QINCREF(bs_opts);
> -    ret = bdrv_open(&dinfo->bdrv, file, NULL, bs_opts, bdrv_flags, drv, &error);
> +    ret = bdrv_open(&bs, file, NULL, bs_opts, bdrv_flags, drv, &error);
> +    assert(bs == blk_bs(blk));
>  
>      if (ret < 0) {
>          error_setg(errp, "could not open disk image %s: %s",
> @@ -518,8 +518,9 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>          goto err;
>      }
>  
> -    if (bdrv_key_required(dinfo->bdrv))
> +    if (bdrv_key_required(bs)) {
>          autostart = 0;
> +    }
>  
>      QDECREF(bs_opts);
>      qemu_opts_del(opts);
> @@ -529,7 +530,6 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>  err:
>      bdrv_unref(dinfo->bdrv);
>      QTAILQ_REMOVE(&drives, dinfo, next);
> -bdrv_new_err:
>      g_free(dinfo->id);
>      g_free(dinfo);
>      blk_unref(blk);
> @@ -1746,15 +1746,17 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
>  int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>  {
>      const char *id = qdict_get_str(qdict, "id");
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      AioContext *aio_context;
>      Error *local_err = NULL;
>  
> -    bs = bdrv_find(id);
> -    if (!bs) {
> +    blk = blk_by_name(id);
> +    if (!blk) {
>          error_report("Device '%s' not found", id);
>          return -1;
>      }
> +    bs = blk_bs(blk);
>  
>      aio_context = bdrv_get_aio_context(bs);
>      aio_context_acquire(aio_context);
> @@ -1777,8 +1779,9 @@ 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 (bdrv_get_attached_dev(bs)) {
> +        blk_detach_bs(blk);
> +        blk_unref(blk);
>          bdrv_make_anon(bs);
> -        blk_unref(blk_by_name(id));
>          /* Further I/O must not pause the guest */
>          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
>                            BLOCKDEV_ON_ERROR_REPORT);
> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> index 730a021..51f4f3a 100644
> --- a/hw/block/xen_disk.c
> +++ b/hw/block/xen_disk.c
> @@ -858,15 +858,11 @@ static int blk_connect(struct XenDevice *xendev)
>  
>          /* setup via xenbus -> create new block driver instance */
>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
> -        blk = blk_new(blkdev->dev, NULL);
> +        blk = blk_new_with_bs(blkdev->dev, NULL);
>          if (!blk) {
>              return -1;
>          }
> -        blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
> -        if (!blkdev->bs) {
> -            blk_unref(blk);
> -            return -1;
> -        }
> +        blkdev->bs = blk_bs(blk);
>  
>          drv = bdrv_find_whitelisted_format(blkdev->fileproto, readonly);
>          if (bdrv_open(&blkdev->bs, blkdev->filename, NULL, NULL, qflags,
> diff --git a/include/block/block_int.h b/include/block/block_int.h
> index 8a61215..a04c852 100644
> --- a/include/block/block_int.h
> +++ b/include/block/block_int.h
> @@ -323,6 +323,8 @@ struct BlockDriverState {
>      BlockDriver *drv; /* NULL means no media */
>      void *opaque;
>  
> +    BlockBackend *blk;          /* owning backend, if any */
> +
>      void *dev;                  /* attached device model, if any */
>      /* TODO change to DeviceState when all users are qdevified */
>      const BlockDevOps *dev_ops;
> diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
> index 3f8371c..539b96f 100644
> --- a/include/sysemu/block-backend.h
> +++ b/include/sysemu/block-backend.h
> @@ -17,10 +17,15 @@
>  #include "qapi/error.h"
>  
>  BlockBackend *blk_new(const char *name, Error **errp);
> +BlockBackend *blk_new_with_bs(const char *name, Error **errp);
>  void blk_ref(BlockBackend *blk);
>  void blk_unref(BlockBackend *blk);
>  const char *blk_name(BlockBackend *blk);
>  BlockBackend *blk_by_name(const char *name);
>  BlockBackend *blk_next(BlockBackend *blk);
>  
> +void blk_attach_bs(BlockBackend *blk, BlockDriverState *bs);
> +BlockDriverState *blk_detach_bs(BlockBackend *blk);
> +BlockDriverState *blk_bs(BlockBackend *blk);
> +
>  #endif
> diff --git a/qemu-img.c b/qemu-img.c
> index bad3f64..9fba5a1 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -284,20 +284,19 @@ static int print_block_option_help(const char *filename, const char *fmt)
>      return 0;
>  }
>  
> -static BlockDriverState *bdrv_new_open(const char *id,
> -                                       const char *filename,
> -                                       const char *fmt,
> -                                       int flags,
> -                                       bool require_io,
> -                                       bool quiet)
> +static BlockBackend *img_open(const char *id, const char *filename,
> +                              const char *fmt, int flags,
> +                              bool require_io, bool quiet)
>  {
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      BlockDriver *drv;
>      char password[256];
>      Error *local_err = NULL;
>      int ret;
>  
> -    bs = bdrv_new_named(id, &error_abort);
> +    blk = blk_new_with_bs(id, &error_abort);
> +    bs = blk_bs(blk);
>  
>      if (fmt) {
>          drv = bdrv_find_format(fmt);
> @@ -328,9 +327,10 @@ static BlockDriverState *bdrv_new_open(const char *id,
>              goto fail;
>          }
>      }
> -    return bs;
> +    return blk;
>  fail:
>      bdrv_unref(bs);
> +    blk_unref(blk);
>      return NULL;
>  }
>  
> @@ -651,11 +651,11 @@ static int img_check(int argc, char **argv)
>          return 1;
>      }
>  
> -    blk = blk_new("image", &error_abort);
> -    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
> -    if (!bs) {
> +    blk = img_open("image", filename, fmt, flags, true, quiet);
> +    if (!blk) {
>          return 1;
>      }
> +    bs = blk_bs(blk);
>  
>      check = g_new0(ImageCheck, 1);
>      ret = collect_image_check(bs, check, filename, fmt, fix);
> @@ -761,11 +761,12 @@ static int img_commit(int argc, char **argv)
>          return 1;
>      }
>  
> -    blk = blk_new("image", &error_abort);
> -    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
> -    if (!bs) {
> +    blk = img_open("image", filename, fmt, flags, true, quiet);
> +    if (!blk) {
>          return 1;
>      }
> +    bs = blk_bs(blk);
> +
>      ret = bdrv_commit(bs);
>      switch(ret) {
>      case 0:
> @@ -1019,21 +1020,21 @@ static int img_compare(int argc, char **argv)
>          goto out3;
>      }
>  
> -    blk1 = blk_new("image 1", &error_abort);
> -    bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
> -    if (!bs1) {
> +    blk1 = img_open("image 1", filename1, fmt1, flags, true, quiet);
> +    if (!blk1) {
>          error_report("Can't open file %s", filename1);
>          ret = 2;
>          goto out3;
>      }
> +    bs1 = blk_bs(blk1);
>  
> -    blk2 = blk_new("image 2", &error_abort);
> -    bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
> -    if (!bs2) {
> +    blk2 = img_open("image 2", filename2, fmt2, flags, true, quiet);
> +    if (!blk2) {
>          error_report("Can't open file %s", filename2);
>          ret = 2;
>          goto out2;
>      }
> +    bs2 = blk_bs(blk2);
>  
>      buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
>      buf2 = qemu_blockalign(bs2, IO_BUF_SIZE);
> @@ -1375,15 +1376,15 @@ static int img_convert(int argc, char **argv)
>      for (bs_i = 0; bs_i < bs_n; bs_i++) {
>          char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
>                              : g_strdup("source");
> -        blk[bs_i] = blk_new(id, &error_abort);
> -        bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
> -                                 true, quiet);
> +        blk[bs_i] = img_open(id, argv[optind + bs_i], fmt, src_flags,
> +                             true, quiet);
>          g_free(id);
> -        if (!bs[bs_i]) {
> +        if (!blk[bs_i]) {
>              error_report("Could not open '%s'", argv[optind + bs_i]);
>              ret = -1;
>              goto out;
>          }
> +        bs[bs_i] = blk_bs(blk[bs_i]);
>          bs_sectors[bs_i] = bdrv_nb_sectors(bs[bs_i]);
>          if (bs_sectors[bs_i] < 0) {
>              error_report("Could not get size of %s: %s",
> @@ -1501,12 +1502,12 @@ static int img_convert(int argc, char **argv)
>          goto out;
>      }
>  
> -    out_blk = blk_new("target", &error_abort);
> -    out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
> -    if (!out_bs) {
> +    out_blk = img_open("target", out_filename, out_fmt, flags, true, quiet);
> +    if (!out_blk) {
>          ret = -1;
>          goto out;
>      }
> +    out_bs = blk_bs(out_blk);
>  
>      bs_i = 0;
>      bs_offset = 0;
> @@ -1893,12 +1894,12 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>          }
>          g_hash_table_insert(filenames, (gpointer)filename, NULL);
>  
> -        blk = blk_new("image", &error_abort);
> -        bs = bdrv_new_open("image", filename, fmt,
> -                           BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
> -        if (!bs) {
> +        blk = img_open("image", filename, fmt,
> +                       BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
> +        if (!blk) {
>              goto err;
>          }
> +        bs = blk_bs(blk);
>  
>          bdrv_query_image_info(bs, &info, &err);
>          if (err) {
> @@ -2158,11 +2159,11 @@ static int img_map(int argc, char **argv)
>          return 1;
>      }
>  
> -    blk = blk_new("image", &error_abort);
> -    bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
> -    if (!bs) {
> +    blk = img_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
> +    if (!blk) {
>          return 1;
>      }
> +    bs = blk_bs(blk);
>  
>      if (output_format == OFORMAT_HUMAN) {
>          printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File");
> @@ -2281,11 +2282,11 @@ static int img_snapshot(int argc, char **argv)
>      filename = argv[optind++];
>  
>      /* Open the image */
> -    blk = blk_new("image", &error_abort);
> -    bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
> -    if (!bs) {
> +    blk = img_open("image", filename, NULL, bdrv_oflags, true, quiet);
> +    if (!blk) {
>          return 1;
>      }
> +    bs = blk_bs(blk);
>  
>      /* Perform the requested action */
>      switch(action) {
> @@ -2427,12 +2428,12 @@ static int img_rebase(int argc, char **argv)
>       * Ignore the old backing file for unsafe rebase in case we want to correct
>       * the reference to a renamed or moved backing file.
>       */
> -    blk = blk_new("image", &error_abort);
> -    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
> -    if (!bs) {
> +    blk = img_open("image", filename, fmt, flags, true, quiet);
> +    if (!blk) {
>          ret = -1;
>          goto out;
>      }
> +    bs = blk_bs(blk);
>  
>      /* Find the right drivers for the backing files */
>      old_backing_drv = NULL;
> @@ -2460,8 +2461,8 @@ static int img_rebase(int argc, char **argv)
>      if (!unsafe) {
>          char backing_name[1024];
>  
> -        blk_old_backing = blk_new("old_backing", &error_abort);
> -        bs_old_backing = bdrv_new_named("old_backing", &error_abort);
> +        blk_old_backing = blk_new_with_bs("old_backing", &error_abort);
> +        bs_old_backing = blk_bs(blk_old_backing);
>          bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
>          ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
>                          old_backing_drv, &local_err);
> @@ -2472,8 +2473,8 @@ static int img_rebase(int argc, char **argv)
>              goto out;
>          }
>          if (out_baseimg[0]) {
> -            blk_new_backing = blk_new("new_backing", &error_abort);
> -            bs_new_backing = bdrv_new_named("new_backing", &error_abort);
> +            blk_new_backing = blk_new_with_bs("new_backing", &error_abort);
> +            bs_new_backing = blk_bs(blk_new_backing);
>              ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
>                              new_backing_drv, &local_err);
>              if (ret) {
> @@ -2749,13 +2750,13 @@ static int img_resize(int argc, char **argv)
>      n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
>      qemu_opts_del(param);
>  
> -    blk = blk_new("image", &error_abort);
> -    bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
> -                       true, quiet);
> -    if (!bs) {
> +    blk = img_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
> +                   true, quiet);
> +    if (!blk) {
>          ret = -1;
>          goto out;
>      }
> +    bs = blk_bs(blk);
>  
>      if (relative) {
>          total_size = bdrv_getlength(bs) + n * relative;
> @@ -2867,13 +2868,13 @@ static int img_amend(int argc, char **argv)
>          goto out;
>      }
>  
> -    blk = blk_new("image", &error_abort);
> -    bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
> -    if (!bs) {
> +    blk = img_open("image", filename, fmt, flags, true, quiet);
> +    if (!blk) {
>          error_report("Could not open image '%s'", filename);
>          ret = -1;
>          goto out;
>      }
> +    bs = blk_bs(blk);
>  
>      fmt = bs->drv->format_name;
>  
> diff --git a/qemu-io.c b/qemu-io.c
> index 45e5494..ef1d3ea 100644
> --- a/qemu-io.c
> +++ b/qemu-io.c
> @@ -62,8 +62,8 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
>          return 1;
>      }
>  
> -    qemuio_blk = blk_new("hda", &error_abort);
> -    qemuio_bs = bdrv_new_named("hda", &error_abort);
> +    qemuio_blk = blk_new_with_bs("hda", &error_abort);
> +    qemuio_bs = blk_bs(qemuio_blk);
>  
>      if (growable) {
>          flags |= BDRV_O_PROTOCOL;
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index 94b9b49..8eff588 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -687,8 +687,7 @@ int main(int argc, char **argv)
>          drv = NULL;
>      }
>  
> -    blk_new("hda", &error_abort);
> -    bs = bdrv_new_named("hda", &error_abort);
> +    bs = blk_bs(blk_new_with_bs("hda", &error_abort));
>  
>      srcpath = argv[optind];
>      ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
> -- 
> 1.9.3
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState Markus Armbruster
  2014-09-10 11:55   ` Benoît Canet
@ 2014-09-10 12:24   ` Kevin Wolf
  2014-09-11 15:27     ` Markus Armbruster
  1 sibling, 1 reply; 76+ messages in thread
From: Kevin Wolf @ 2014-09-10 12:24 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: benoit.canet, famz, qemu-devel, stefanha

Am 10.09.2014 um 10:13 hat Markus Armbruster geschrieben:
> The pointer from BlockBackend to BlockDriverState is a strong
> reference, managed with bdrv_ref() / bdrv_unref(), the back-pointer is
> a weak one.
> 
> Convenience function blk_new_with_bs() creates a BlockBackend with its
> BlockDriverState.  Callers have to unref both.  The commit after next
> will relieve them of the need to unref the BlockDriverState.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

I'm wondering whether this is the right direction to take. In creating a
block device, we have the following operations:

1. Create a BlockBackend
2. Create a BlockDriverState
3. Open the BlockDriverState

bdrv_open() can do 2 and 3, which is probably what we want to have in
the end - new/create and delete/close should be a single operation for
BDSes.

Combining 1 and 2 into a single function might make it harder to actually
use bdrv_open() in this way.

> diff --git a/blockdev.c b/blockdev.c
> index 86596bc..0a0b95e 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -304,6 +304,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      int bdrv_flags = 0;
>      int on_read_error, on_write_error;
>      BlockBackend *blk;
> +    BlockDriverState *bs;
>      DriveInfo *dinfo;
>      ThrottleConfig cfg;
>      int snapshot = 0;
> @@ -459,30 +460,28 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      }
>  
>      /* init */
> -    blk = blk_new(qemu_opts_id(opts), errp);
> +    blk = blk_new_with_bs(qemu_opts_id(opts), errp);
>      if (!blk) {
>          goto early_err;
>      }
> +    bs = blk_bs(blk);
> +    bs->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
> +    bs->read_only = ro;
> +    bs->detect_zeroes = detect_zeroes;
> +
> +    bdrv_set_on_error(bs, on_read_error, on_write_error);
> +
> +    /* disk I/O throttling */
> +    if (throttle_enabled(&cfg)) {
> +        bdrv_io_limits_enable(bs);
> +        bdrv_set_io_limits(bs, &cfg);
> +    }
> +
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
> -    dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
> -    if (error) {
> -        error_propagate(errp, error);
> -        goto bdrv_new_err;
> -    }
> -    dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
> -    dinfo->bdrv->read_only = ro;
> -    dinfo->bdrv->detect_zeroes = detect_zeroes;
> +    dinfo->bdrv = bs;
>      QTAILQ_INSERT_TAIL(&drives, dinfo, next);
>  
> -    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
> -
> -    /* disk I/O throttling */
> -    if (throttle_enabled(&cfg)) {
> -        bdrv_io_limits_enable(dinfo->bdrv);
> -        bdrv_set_io_limits(dinfo->bdrv, &cfg);
> -    }
> -
>      if (!file || !*file) {
>          if (has_driver_specific_opts) {
>              file = NULL;

This looks correct, but it's really doing two things at once (on the one
hand changing code to use bs instead of dinfo->bdrv and reordering, on
the other hand introducing blk_new_with_bs()).

Might be worth doing in separate patches.

> @@ -509,7 +508,8 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
>  
>      QINCREF(bs_opts);
> -    ret = bdrv_open(&dinfo->bdrv, file, NULL, bs_opts, bdrv_flags, drv, &error);
> +    ret = bdrv_open(&bs, file, NULL, bs_opts, bdrv_flags, drv, &error);
> +    assert(bs == blk_bs(blk));
>  
>      if (ret < 0) {
>          error_setg(errp, "could not open disk image %s: %s",
> @@ -518,8 +518,9 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>          goto err;
>      }
>  
> -    if (bdrv_key_required(dinfo->bdrv))
> +    if (bdrv_key_required(bs)) {
>          autostart = 0;
> +    }
>  
>      QDECREF(bs_opts);
>      qemu_opts_del(opts);
> @@ -529,7 +530,6 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>  err:
>      bdrv_unref(dinfo->bdrv);
>      QTAILQ_REMOVE(&drives, dinfo, next);
> -bdrv_new_err:
>      g_free(dinfo->id);
>      g_free(dinfo);
>      blk_unref(blk);
> @@ -1746,15 +1746,17 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
>  int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>  {
>      const char *id = qdict_get_str(qdict, "id");
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      AioContext *aio_context;
>      Error *local_err = NULL;
>  
> -    bs = bdrv_find(id);
> -    if (!bs) {
> +    blk = blk_by_name(id);
> +    if (!blk) {
>          error_report("Device '%s' not found", id);
>          return -1;
>      }
> +    bs = blk_bs(blk);
>  
>      aio_context = bdrv_get_aio_context(bs);
>      aio_context_acquire(aio_context);
> @@ -1777,8 +1779,9 @@ 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 (bdrv_get_attached_dev(bs)) {
> +        blk_detach_bs(blk);
> +        blk_unref(blk);

We're not doing real refcounting yet, but if we did, and if the refcount
didn't drop to zero here, why would detaching the bs still be correct?

blk_delete() already takes care of detaching after this patch, so I
suppose removing the call here would be right.

>          bdrv_make_anon(bs);
> -        blk_unref(blk_by_name(id));
>          /* Further I/O must not pause the guest */
>          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
>                            BLOCKDEV_ON_ERROR_REPORT);

Kevin

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 02/23] block: New BlockBackend Markus Armbruster
  2014-09-10  9:56   ` Kevin Wolf
  2014-09-10 11:34   ` Benoît Canet
@ 2014-09-10 12:40   ` Benoît Canet
  2014-09-10 12:46     ` Benoît Canet
  2014-09-11 10:21     ` Markus Armbruster
  2 siblings, 2 replies; 76+ messages in thread
From: Benoît Canet @ 2014-09-10 12:40 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:31 (+0200), Markus Armbruster wrote :
> A block device consists of a frontend device model and a backend.
> 
> A block backend has a tree of block drivers doing the actual work.
> The tree is managed by the block layer.
> 
> We currently use a single abstraction BlockDriverState both for tree
> nodes and the backend as a whole.  Drawbacks:
> 
> * Its API includes both stuff that makes sense only at the block
>   backend level (root of the tree) and stuff that's only for use
>   within the block layer.  This makes the API bigger and more complex
>   than necessary.  Moreover, it's not obvious which interfaces are
>   meant for device models, and which really aren't.
> 
> * Since device models keep a reference to their backend, the backend
>   object can't just be destroyed.  But for media change, we need to
>   replace the tree.  Our solution is to make the BlockDriverState
>   generic, with actual driver state in a separate object, pointed to
>   by member opaque.  That lets us replace the tree by deinitializing
>   and reinitializing its root.  This special need of the root makes
>   the data structure awkward everywhere in the tree.
> 
> The general plan is to separate the APIs into "block backend", for use
> by device models, monitor and whatever other code dealing with block
> backends, and "block driver", for use by the block layer and whatever
> other code (if any) dealing with trees and tree nodes.
> 
> Code dealing with block backends, device models in particular, should
> become completely oblivious of BlockDriverState.  This should let us
> clean up both APIs, and the tree data structures.
> 
> This commit is a first step.  It creates a minimal "block backend"
> API: type BlockBackend and functions to create, destroy and find them.
> BlockBackend objects are created and destroyed, but not yet used for
> anything; that'll come shortly.
> 
> BlockBackend is reference-counted.  Its reference count never exceeds
> one so far, but that's going to change.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block/Makefile.objs            |   2 +-
>  block/block-backend.c          | 110 +++++++++++++++++++++++++++++++++++++++++
>  blockdev.c                     |  10 +++-
>  hw/block/xen_disk.c            |  11 +++++
>  include/qemu/typedefs.h        |   1 +
>  include/sysemu/block-backend.h |  26 ++++++++++
>  qemu-img.c                     |  46 +++++++++++++++++
>  qemu-io.c                      |   8 +++
>  qemu-nbd.c                     |   3 +-
>  9 files changed, 214 insertions(+), 3 deletions(-)
>  create mode 100644 block/block-backend.c
>  create mode 100644 include/sysemu/block-backend.h
> 
> diff --git a/block/Makefile.objs b/block/Makefile.objs
> index f45f939..a70140b 100644
> --- a/block/Makefile.objs
> +++ b/block/Makefile.objs
> @@ -5,7 +5,7 @@ block-obj-y += qed-check.o
>  block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
>  block-obj-$(CONFIG_QUORUM) += quorum.o
>  block-obj-y += parallels.o blkdebug.o blkverify.o
> -block-obj-y += snapshot.o qapi.o
> +block-obj-y += block-backend.o snapshot.o qapi.o
>  block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
>  block-obj-$(CONFIG_POSIX) += raw-posix.o
>  block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
> diff --git a/block/block-backend.c b/block/block-backend.c
> new file mode 100644
> index 0000000..833f7d9
> --- /dev/null
> +++ b/block/block-backend.c
> @@ -0,0 +1,110 @@
> +/*
> + * QEMU Block backends
> + *
> + * Copyright (C) 2014 Red Hat, Inc.
> + *
> + * Authors:
> + *  Markus Armbruster <armbru@redhat.com>,
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * later.  See the COPYING file in the top-level directory.
> + */
> +
> +#include "sysemu/block-backend.h"
> +#include "block/block_int.h"
> +
> +struct BlockBackend {
> +    char *name;
> +    int refcnt;
> +    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
> +};
> +
> +static QTAILQ_HEAD(, BlockBackend) blk_backends =
> +    QTAILQ_HEAD_INITIALIZER(blk_backends);
> +
> +/**
> + * blk_new:
> + * @name: name, must not be %NULL or empty
> + * @errp: return location for an error to be set on failure, or %NULL
> + *
> + * Create a new BlockBackend, with a reference count of one.  Fail if
> + * @name already exists.
> + *
> + * Returns: the BlockBackend on success, %NULL on failure
> + */
> +BlockBackend *blk_new(const char *name, Error **errp)
> +{
> +    BlockBackend *blk = g_new0(BlockBackend, 1);
> +
> +    assert(name && name[0]);
> +    if (blk_by_name(name)) {
> +        error_setg(errp, "Device with id '%s' already exists", name);
> +        return NULL;
> +    }
> +    blk->name = g_strdup(name);
> +    blk->refcnt = 1;
> +    QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
> +    return blk;
> +}
> +
> +static void blk_delete(BlockBackend *blk)
> +{
> +    assert(!blk->refcnt);
> +    QTAILQ_REMOVE(&blk_backends, blk, link);
> +    g_free(blk->name);
> +    g_free(blk);
> +}
> +
> +/**
> + * blk_ref:
> + *
> + * Increment @blk's reference count.
> + */
> +void blk_ref(BlockBackend *blk)
> +{
> +    blk->refcnt++;
> +}
> +
> +/**
> + * blk_unref:
> + *
> + * Decrement @blk's reference count.  If this drops it to zero,
> + * destroy @blk.
> + */
> +void blk_unref(BlockBackend *blk)
> +{
> +    if (blk) {
> +        g_assert(blk->refcnt > 0);
> +        if (!--blk->refcnt) {
> +            blk_delete(blk);
> +        }
> +    }
> +}
> +
> +const char *blk_name(BlockBackend *blk)
> +{
> +    return blk->name;
> +}
> +
> +BlockBackend *blk_by_name(const char *name)
> +{
> +    BlockBackend *blk;
> +
> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
> +        if (!strcmp(name, blk->name)) {
> +            return blk;
> +        }
> +    }
> +    return NULL;
> +}
> +
> +/**
> + * blk_next:
> + *
> + * Returns: the first BlockBackend if @blk is null, else @blk's next
> + * sibling, which is %NULL for the last BlockBackend
> + */
> +BlockBackend *blk_next(BlockBackend *blk)
> +{
> +    return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
> +}
> diff --git a/blockdev.c b/blockdev.c
> index 9fbd888..86596bc 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -30,6 +30,7 @@
>   * THE SOFTWARE.
>   */
>  
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/block/block.h"
>  #include "block/blockjob.h"
> @@ -221,6 +222,7 @@ void drive_del(DriveInfo *dinfo)
>      }
>  
>      bdrv_unref(dinfo->bdrv);
> +    blk_unref(blk_by_name(dinfo->id));
>      g_free(dinfo->id);
>      QTAILQ_REMOVE(&drives, dinfo, next);
>      g_free(dinfo->serial);
> @@ -301,6 +303,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      int ro = 0;
>      int bdrv_flags = 0;
>      int on_read_error, on_write_error;
> +    BlockBackend *blk;
>      DriveInfo *dinfo;
>      ThrottleConfig cfg;
>      int snapshot = 0;
> @@ -456,6 +459,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      }
>  
>      /* init */
> +    blk = blk_new(qemu_opts_id(opts), errp);
> +    if (!blk) {
> +        goto early_err;
> +    }

Here you create a new block backend.
And you don't attach it to anything in any way yet.

So down in the code the following test will leak it:
    if (!file || !*file) {                                                      
        if (has_driver_specific_opts) {                                         
            file = NULL;                                                        
        } else {                                                                
            QDECREF(bs_opts);                                                   
            qemu_opts_del(opts);                                                
            return dinfo;                                                       
        }                                                                       
    } 

I am sure one of your next patchs fixes this but for this
precise commit this do look like a leak.

>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
>      dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
> @@ -525,6 +532,7 @@ err:
>  bdrv_new_err:
>      g_free(dinfo->id);
>      g_free(dinfo);
> +    blk_unref(blk);
>  early_err:
>      qemu_opts_del(opts);
>  err_no_opts:
> @@ -1770,7 +1778,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>       */
>      if (bdrv_get_attached_dev(bs)) {
>          bdrv_make_anon(bs);
> -
> +        blk_unref(blk_by_name(id));
>          /* Further I/O must not pause the guest */
>          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
>                            BLOCKDEV_ON_ERROR_REPORT);
> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> index 8bac7ff..730a021 100644
> --- a/hw/block/xen_disk.c
> +++ b/hw/block/xen_disk.c
> @@ -39,6 +39,7 @@
>  #include "hw/xen/xen_backend.h"
>  #include "xen_blkif.h"
>  #include "sysemu/blockdev.h"
> +#include "sysemu/block-backend.h"
>  
>  /* ------------------------------------------------------------- */
>  
> @@ -852,12 +853,18 @@ static int blk_connect(struct XenDevice *xendev)
>      blkdev->dinfo = drive_get(IF_XEN, 0, index);
>      if (!blkdev->dinfo) {
>          Error *local_err = NULL;
> +        BlockBackend *blk;
>          BlockDriver *drv;
>  
>          /* setup via xenbus -> create new block driver instance */
>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
> +        blk = blk_new(blkdev->dev, NULL);
> +        if (!blk) {
> +            return -1;
> +        }
>          blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
>          if (!blkdev->bs) {
> +            blk_unref(blk);
>              return -1;
>          }
>  
> @@ -868,6 +875,7 @@ static int blk_connect(struct XenDevice *xendev)
>                            error_get_pretty(local_err));
>              error_free(local_err);
>              bdrv_unref(blkdev->bs);
> +            blk_unref(blk);
>              blkdev->bs = NULL;
>              return -1;
>          }
> @@ -983,6 +991,9 @@ static void blk_disconnect(struct XenDevice *xendev)
>      if (blkdev->bs) {
>          bdrv_detach_dev(blkdev->bs, blkdev);
>          bdrv_unref(blkdev->bs);
> +        if (!blkdev->dinfo) {
> +            blk_unref(blk_by_name(blkdev->dev));
> +        }
>          blkdev->bs = NULL;
>      }
>      xen_be_unbind_evtchn(&blkdev->xendev);
> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
> index 5f20b0e..198da2e 100644
> --- a/include/qemu/typedefs.h
> +++ b/include/qemu/typedefs.h
> @@ -35,6 +35,7 @@ typedef struct MachineClass MachineClass;
>  typedef struct NICInfo NICInfo;
>  typedef struct HCIInfo HCIInfo;
>  typedef struct AudioState AudioState;
> +typedef struct BlockBackend BlockBackend;
>  typedef struct BlockDriverState BlockDriverState;
>  typedef struct DriveInfo DriveInfo;
>  typedef struct DisplayState DisplayState;
> diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
> new file mode 100644
> index 0000000..3f8371c
> --- /dev/null
> +++ b/include/sysemu/block-backend.h
> @@ -0,0 +1,26 @@
> +/*
> + * QEMU Block backends
> + *
> + * Copyright (C) 2014 Red Hat, Inc.
> + *
> + * Authors:
> + *  Markus Armbruster <armbru@redhat.com>,
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or
> + * later.  See the COPYING file in the top-level directory.
> + */
> +
> +#ifndef BLOCK_BACKEND_H
> +#define BLOCK_BACKEND_H
> +
> +#include "qemu/typedefs.h"
> +#include "qapi/error.h"
> +
> +BlockBackend *blk_new(const char *name, Error **errp);
> +void blk_ref(BlockBackend *blk);
> +void blk_unref(BlockBackend *blk);
> +const char *blk_name(BlockBackend *blk);
> +BlockBackend *blk_by_name(const char *name);
> +BlockBackend *blk_next(BlockBackend *blk);
> +
> +#endif
> diff --git a/qemu-img.c b/qemu-img.c
> index 4490a22..bad3f64 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -29,6 +29,7 @@
>  #include "qemu/error-report.h"
>  #include "qemu/osdep.h"
>  #include "sysemu/sysemu.h"
> +#include "sysemu/block-backend.h"
>  #include "block/block_int.h"
>  #include "block/qapi.h"
>  #include <getopt.h>
> @@ -575,6 +576,7 @@ static int img_check(int argc, char **argv)
>      int c, ret;
>      OutputFormat output_format = OFORMAT_HUMAN;
>      const char *filename, *fmt, *output, *cache;
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      int fix = 0;
>      int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
> @@ -649,6 +651,7 @@ static int img_check(int argc, char **argv)
>          return 1;
>      }
>  

> +    blk = blk_new("image", &error_abort);
Hmm we are so sure this will work that we don't do if (!block) ?

>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>      if (!bs) {
>          return 1;
> @@ -710,6 +713,7 @@ static int img_check(int argc, char **argv)
>  fail:
>      qapi_free_ImageCheck(check);
>      bdrv_unref(bs);
> +    blk_unref(blk);
>  
>      return ret;
>  }
> @@ -718,6 +722,7 @@ static int img_commit(int argc, char **argv)
>  {
>      int c, ret, flags;
>      const char *filename, *fmt, *cache;
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      bool quiet = false;
>  
> @@ -756,6 +761,7 @@ static int img_commit(int argc, char **argv)
>          return 1;
>      }
>  
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>      if (!bs) {
>          return 1;
> @@ -780,6 +786,7 @@ static int img_commit(int argc, char **argv)
>      }
>  
>      bdrv_unref(bs);
> +    blk_unref(blk);
>      if (ret) {
>          return 1;
>      }
> @@ -942,6 +949,7 @@ static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
>  static int img_compare(int argc, char **argv)
>  {
>      const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
> +    BlockBackend *blk1, *blk2;
>      BlockDriverState *bs1, *bs2;
>      int64_t total_sectors1, total_sectors2;
>      uint8_t *buf1 = NULL, *buf2 = NULL;
> @@ -1011,6 +1019,7 @@ static int img_compare(int argc, char **argv)
>          goto out3;
>      }
>  
> +    blk1 = blk_new("image 1", &error_abort);
>      bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
>      if (!bs1) {
>          error_report("Can't open file %s", filename1);
> @@ -1018,6 +1027,7 @@ static int img_compare(int argc, char **argv)
>          goto out3;
>      }
>  
> +    blk2 = blk_new("image 2", &error_abort);
>      bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
>      if (!bs2) {
>          error_report("Can't open file %s", filename2);
> @@ -1184,10 +1194,12 @@ static int img_compare(int argc, char **argv)
>  
>  out:
>      bdrv_unref(bs2);
> +    blk_unref(blk2);
>      qemu_vfree(buf1);
>      qemu_vfree(buf2);
>  out2:
>      bdrv_unref(bs1);
> +    blk_unref(blk1);
>  out3:
>      qemu_progress_end();
>      return ret;
> @@ -1200,6 +1212,7 @@ static int img_convert(int argc, char **argv)
>      int progress = 0, flags, src_flags;
>      const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
>      BlockDriver *drv, *proto_drv;
> +    BlockBackend **blk = NULL, *out_blk = NULL;
>      BlockDriverState **bs = NULL, *out_bs = NULL;
>      int64_t total_sectors, nb_sectors, sector_num, bs_offset;
>      int64_t *bs_sectors = NULL;
> @@ -1354,6 +1367,7 @@ static int img_convert(int argc, char **argv)
>  
>      qemu_progress_print(0, 100);
>  
> +    blk = g_new0(BlockBackend *, bs_n);
>      bs = g_new0(BlockDriverState *, bs_n);
>      bs_sectors = g_new(int64_t, bs_n);
>  
> @@ -1361,6 +1375,7 @@ static int img_convert(int argc, char **argv)
>      for (bs_i = 0; bs_i < bs_n; bs_i++) {
>          char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
>                              : g_strdup("source");
> +        blk[bs_i] = blk_new(id, &error_abort);
>          bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
>                                   true, quiet);
>          g_free(id);
> @@ -1486,6 +1501,7 @@ static int img_convert(int argc, char **argv)
>          goto out;
>      }
>  
> +    out_blk = blk_new("target", &error_abort);
>      out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
>      if (!out_bs) {
>          ret = -1;
> @@ -1742,6 +1758,7 @@ out:
>      if (out_bs) {
>          bdrv_unref(out_bs);
>      }
> +    blk_unref(out_blk);
>      if (bs) {
>          for (bs_i = 0; bs_i < bs_n; bs_i++) {
>              if (bs[bs_i]) {
> @@ -1750,6 +1767,12 @@ out:
>          }
>          g_free(bs);
>      }
> +    if (blk) {
> +        for (bs_i = 0; bs_i < bs_n; bs_i++) {
> +            blk_unref(blk[bs_i]);
> +        }
> +        g_free(blk);
> +    }
>      g_free(bs_sectors);
>  fail_getopt:
>      g_free(options);
> @@ -1858,6 +1881,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>      filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
>  
>      while (filename) {
> +        BlockBackend *blk;
>          BlockDriverState *bs;
>          ImageInfo *info;
>          ImageInfoList *elem;
> @@ -1869,6 +1893,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>          }
>          g_hash_table_insert(filenames, (gpointer)filename, NULL);
>  
> +        blk = blk_new("image", &error_abort);
>          bs = bdrv_new_open("image", filename, fmt,
>                             BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
>          if (!bs) {

I think it misses an 
> +            blk_unref(blk);
in if(!bs) branch.

> @@ -1880,6 +1905,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>              error_report("%s", error_get_pretty(err));
>              error_free(err);
>              bdrv_unref(bs);
> +            blk_unref(blk);
>              goto err;
>          }
>  
> @@ -1889,6 +1915,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>          last = &elem->next;
>  
>          bdrv_unref(bs);
> +        blk_unref(blk);
>  
>          filename = fmt = NULL;
>          if (chain) {
> @@ -2082,6 +2109,7 @@ static int img_map(int argc, char **argv)
>  {
>      int c;
>      OutputFormat output_format = OFORMAT_HUMAN;
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      const char *filename, *fmt, *output;
>      int64_t length;
> @@ -2130,6 +2158,7 @@ static int img_map(int argc, char **argv)
>          return 1;
>      }
>  
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
>      if (!bs) {
>          return 1;
> @@ -2175,6 +2204,7 @@ static int img_map(int argc, char **argv)
>  
>  out:
>      bdrv_unref(bs);
> +    blk_unref(blk);
>      return ret < 0;
>  }
>  
> @@ -2185,6 +2215,7 @@ out:
>  
>  static int img_snapshot(int argc, char **argv)
>  {
> +    BlockBackend *blk;
>      BlockDriverState *bs;
>      QEMUSnapshotInfo sn;
>      char *filename, *snapshot_name = NULL;
> @@ -2250,6 +2281,7 @@ static int img_snapshot(int argc, char **argv)
>      filename = argv[optind++];
>  
>      /* Open the image */
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
>      if (!bs) {
>          return 1;
> @@ -2297,6 +2329,7 @@ static int img_snapshot(int argc, char **argv)
>  
>      /* Cleanup */
>      bdrv_unref(bs);
> +    blk_unref(blk);
>      if (ret) {
>          return 1;
>      }
> @@ -2305,6 +2338,7 @@ static int img_snapshot(int argc, char **argv)
>  
>  static int img_rebase(int argc, char **argv)
>  {
> +    BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL;
>      BlockDriverState *bs = NULL, *bs_old_backing = NULL, *bs_new_backing = NULL;
>      BlockDriver *old_backing_drv, *new_backing_drv;
>      char *filename;
> @@ -2393,6 +2427,7 @@ static int img_rebase(int argc, char **argv)
>       * Ignore the old backing file for unsafe rebase in case we want to correct
>       * the reference to a renamed or moved backing file.
>       */
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>      if (!bs) {
>          ret = -1;
> @@ -2425,6 +2460,7 @@ static int img_rebase(int argc, char **argv)
>      if (!unsafe) {
>          char backing_name[1024];
>  
> +        blk_old_backing = blk_new("old_backing", &error_abort);
>          bs_old_backing = bdrv_new_named("old_backing", &error_abort);
>          bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
>          ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
> @@ -2436,6 +2472,7 @@ static int img_rebase(int argc, char **argv)
>              goto out;
>          }
>          if (out_baseimg[0]) {
> +            blk_new_backing = blk_new("new_backing", &error_abort);
>              bs_new_backing = bdrv_new_named("new_backing", &error_abort);
>              ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
>                              new_backing_drv, &local_err);
> @@ -2614,12 +2651,15 @@ out:
>          if (bs_old_backing != NULL) {
>              bdrv_unref(bs_old_backing);
>          }
> +        blk_unref(blk_old_backing);
>          if (bs_new_backing != NULL) {
>              bdrv_unref(bs_new_backing);
>          }
> +        blk_unref(blk_new_backing);
>      }
>  
>      bdrv_unref(bs);
> +    blk_unref(blk);
>      if (ret) {
>          return 1;
>      }
> @@ -2632,6 +2672,7 @@ static int img_resize(int argc, char **argv)
>      const char *filename, *fmt, *size;
>      int64_t n, total_size;
>      bool quiet = false;
> +    BlockBackend *blk = NULL;
>      BlockDriverState *bs = NULL;
>      QemuOpts *param;
>      static QemuOptsList resize_options = {
> @@ -2708,6 +2749,7 @@ static int img_resize(int argc, char **argv)
>      n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
>      qemu_opts_del(param);
>  
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
>                         true, quiet);
>      if (!bs) {
> @@ -2745,6 +2787,7 @@ out:
>      if (bs) {
>          bdrv_unref(bs);
>      }
> +    blk_unref(blk);
>      if (ret) {
>          return 1;
>      }
> @@ -2760,6 +2803,7 @@ static int img_amend(int argc, char **argv)
>      const char *fmt = NULL, *filename, *cache;
>      int flags;
>      bool quiet = false;
> +    BlockBackend *blk = NULL;
>      BlockDriverState *bs = NULL;
>  
>      cache = BDRV_DEFAULT_CACHE;
> @@ -2823,6 +2867,7 @@ static int img_amend(int argc, char **argv)
>          goto out;
>      }
>  
> +    blk = blk_new("image", &error_abort);
>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>      if (!bs) {
>          error_report("Could not open image '%s'", filename);
> @@ -2856,6 +2901,7 @@ out:
>      if (bs) {
>          bdrv_unref(bs);
>      }
> +    blk_unref(blk);
>      qemu_opts_del(opts);
>      qemu_opts_free(create_opts);
>      g_free(options);
> diff --git a/qemu-io.c b/qemu-io.c
> index 44c2e1c..45e5494 100644
> --- a/qemu-io.c
> +++ b/qemu-io.c
> @@ -19,6 +19,7 @@
>  #include "qemu/option.h"
>  #include "qemu/config-file.h"
>  #include "qemu/readline.h"
> +#include "sysemu/block-backend.h"
>  #include "block/block_int.h"
>  #include "trace/control.h"
>  
> @@ -26,6 +27,7 @@
>  
>  static char *progname;
>  
> +static BlockBackend *qemuio_blk;
>  static BlockDriverState *qemuio_bs;
>  
>  /* qemu-io commands passed using -c */
> @@ -37,7 +39,9 @@ static ReadLineState *readline_state;
>  static int close_f(BlockDriverState *bs, int argc, char **argv)
>  {
>      bdrv_unref(bs);
> +    blk_unref(qemuio_blk);
>      qemuio_bs = NULL;
> +    qemuio_blk = NULL;
>      return 0;
>  }
>  
> @@ -58,6 +62,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
>          return 1;
>      }
>  
> +    qemuio_blk = blk_new("hda", &error_abort);

>      qemuio_bs = bdrv_new_named("hda", &error_abort);
I see accepting that an allocation _will_ work is the qemu tools style.

>  
>      if (growable) {
> @@ -70,7 +75,9 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
>                  error_get_pretty(local_err));
>          error_free(local_err);
>          bdrv_unref(qemuio_bs);
> +        blk_unref(qemuio_blk);
>          qemuio_bs = NULL;
> +        qemuio_blk = NULL;
>          return 1;
>      }
>  
> @@ -479,6 +486,7 @@ int main(int argc, char **argv)
>      if (qemuio_bs) {
>          bdrv_unref(qemuio_bs);
>      }
> +    blk_unref(qemuio_blk);
>      g_free(readline_state);
>      return 0;
>  }
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index a56ebfc..94b9b49 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -17,7 +17,7 @@
>   */
>  
>  #include "qemu-common.h"
> -#include "block/block.h"
> +#include "sysemu/block-backend.h"
>  #include "block/block_int.h"
>  #include "block/nbd.h"
>  #include "qemu/main-loop.h"
> @@ -687,6 +687,7 @@ int main(int argc, char **argv)
>          drv = NULL;
>      }
>  
> +    blk_new("hda", &error_abort);
>      bs = bdrv_new_named("hda", &error_abort);
>  
>      srcpath = argv[optind];
> -- 
> 1.9.3
> 
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10 12:40   ` Benoît Canet
@ 2014-09-10 12:46     ` Benoît Canet
  2014-09-11 10:22       ` Markus Armbruster
  2014-09-11 10:21     ` Markus Armbruster
  1 sibling, 1 reply; 76+ messages in thread
From: Benoît Canet @ 2014-09-10 12:46 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, Markus Armbruster, stefanha, qemu-devel

The Wednesday 10 Sep 2014 à 14:40:42 (+0200), Benoît Canet wrote :
> The Wednesday 10 Sep 2014 à 10:13:31 (+0200), Markus Armbruster wrote :
> > A block device consists of a frontend device model and a backend.
> > 
> > A block backend has a tree of block drivers doing the actual work.
> > The tree is managed by the block layer.
> > 
> > We currently use a single abstraction BlockDriverState both for tree
> > nodes and the backend as a whole.  Drawbacks:
> > 
> > * Its API includes both stuff that makes sense only at the block
> >   backend level (root of the tree) and stuff that's only for use
> >   within the block layer.  This makes the API bigger and more complex
> >   than necessary.  Moreover, it's not obvious which interfaces are
> >   meant for device models, and which really aren't.
> > 
> > * Since device models keep a reference to their backend, the backend
> >   object can't just be destroyed.  But for media change, we need to
> >   replace the tree.  Our solution is to make the BlockDriverState
> >   generic, with actual driver state in a separate object, pointed to
> >   by member opaque.  That lets us replace the tree by deinitializing
> >   and reinitializing its root.  This special need of the root makes
> >   the data structure awkward everywhere in the tree.
> > 
> > The general plan is to separate the APIs into "block backend", for use
> > by device models, monitor and whatever other code dealing with block
> > backends, and "block driver", for use by the block layer and whatever
> > other code (if any) dealing with trees and tree nodes.
> > 
> > Code dealing with block backends, device models in particular, should
> > become completely oblivious of BlockDriverState.  This should let us
> > clean up both APIs, and the tree data structures.
> > 
> > This commit is a first step.  It creates a minimal "block backend"
> > API: type BlockBackend and functions to create, destroy and find them.
> > BlockBackend objects are created and destroyed, but not yet used for
> > anything; that'll come shortly.
> > 
> > BlockBackend is reference-counted.  Its reference count never exceeds
> > one so far, but that's going to change.
> > 
> > Signed-off-by: Markus Armbruster <armbru@redhat.com>
> > ---
> >  block/Makefile.objs            |   2 +-
> >  block/block-backend.c          | 110 +++++++++++++++++++++++++++++++++++++++++
> >  blockdev.c                     |  10 +++-
> >  hw/block/xen_disk.c            |  11 +++++
> >  include/qemu/typedefs.h        |   1 +
> >  include/sysemu/block-backend.h |  26 ++++++++++
> >  qemu-img.c                     |  46 +++++++++++++++++
> >  qemu-io.c                      |   8 +++
> >  qemu-nbd.c                     |   3 +-
> >  9 files changed, 214 insertions(+), 3 deletions(-)
> >  create mode 100644 block/block-backend.c
> >  create mode 100644 include/sysemu/block-backend.h
> > 
> > diff --git a/block/Makefile.objs b/block/Makefile.objs
> > index f45f939..a70140b 100644
> > --- a/block/Makefile.objs
> > +++ b/block/Makefile.objs
> > @@ -5,7 +5,7 @@ block-obj-y += qed-check.o
> >  block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
> >  block-obj-$(CONFIG_QUORUM) += quorum.o
> >  block-obj-y += parallels.o blkdebug.o blkverify.o
> > -block-obj-y += snapshot.o qapi.o
> > +block-obj-y += block-backend.o snapshot.o qapi.o
> >  block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
> >  block-obj-$(CONFIG_POSIX) += raw-posix.o
> >  block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
> > diff --git a/block/block-backend.c b/block/block-backend.c
> > new file mode 100644
> > index 0000000..833f7d9
> > --- /dev/null
> > +++ b/block/block-backend.c
> > @@ -0,0 +1,110 @@
> > +/*
> > + * QEMU Block backends
> > + *
> > + * Copyright (C) 2014 Red Hat, Inc.
> > + *
> > + * Authors:
> > + *  Markus Armbruster <armbru@redhat.com>,
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2 or
> > + * later.  See the COPYING file in the top-level directory.
> > + */
> > +
> > +#include "sysemu/block-backend.h"
> > +#include "block/block_int.h"
> > +
> > +struct BlockBackend {
> > +    char *name;
> > +    int refcnt;
> > +    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
> > +};
> > +
> > +static QTAILQ_HEAD(, BlockBackend) blk_backends =
> > +    QTAILQ_HEAD_INITIALIZER(blk_backends);
> > +
> > +/**
> > + * blk_new:
> > + * @name: name, must not be %NULL or empty
> > + * @errp: return location for an error to be set on failure, or %NULL
> > + *
> > + * Create a new BlockBackend, with a reference count of one.  Fail if
> > + * @name already exists.
> > + *
> > + * Returns: the BlockBackend on success, %NULL on failure
> > + */
> > +BlockBackend *blk_new(const char *name, Error **errp)
> > +{
> > +    BlockBackend *blk = g_new0(BlockBackend, 1);
> > +
> > +    assert(name && name[0]);
> > +    if (blk_by_name(name)) {
> > +        error_setg(errp, "Device with id '%s' already exists", name);
> > +        return NULL;
> > +    }
> > +    blk->name = g_strdup(name);
> > +    blk->refcnt = 1;
> > +    QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
> > +    return blk;
> > +}
> > +
> > +static void blk_delete(BlockBackend *blk)
> > +{
> > +    assert(!blk->refcnt);
> > +    QTAILQ_REMOVE(&blk_backends, blk, link);
> > +    g_free(blk->name);
> > +    g_free(blk);
> > +}
> > +
> > +/**
> > + * blk_ref:
> > + *
> > + * Increment @blk's reference count.
> > + */
> > +void blk_ref(BlockBackend *blk)
> > +{
> > +    blk->refcnt++;
> > +}
> > +
> > +/**
> > + * blk_unref:
> > + *
> > + * Decrement @blk's reference count.  If this drops it to zero,
> > + * destroy @blk.
> > + */
> > +void blk_unref(BlockBackend *blk)
> > +{
> > +    if (blk) {
> > +        g_assert(blk->refcnt > 0);
> > +        if (!--blk->refcnt) {
> > +            blk_delete(blk);
> > +        }
> > +    }
> > +}
> > +
> > +const char *blk_name(BlockBackend *blk)
> > +{
> > +    return blk->name;
> > +}
> > +
> > +BlockBackend *blk_by_name(const char *name)
> > +{
> > +    BlockBackend *blk;
> > +
> > +    QTAILQ_FOREACH(blk, &blk_backends, link) {
> > +        if (!strcmp(name, blk->name)) {
> > +            return blk;
> > +        }
> > +    }
> > +    return NULL;
> > +}
> > +
> > +/**
> > + * blk_next:
> > + *
> > + * Returns: the first BlockBackend if @blk is null, else @blk's next
> > + * sibling, which is %NULL for the last BlockBackend
> > + */
> > +BlockBackend *blk_next(BlockBackend *blk)
> > +{
> > +    return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
> > +}
> > diff --git a/blockdev.c b/blockdev.c
> > index 9fbd888..86596bc 100644
> > --- a/blockdev.c
> > +++ b/blockdev.c
> > @@ -30,6 +30,7 @@
> >   * THE SOFTWARE.
> >   */
> >  
> > +#include "sysemu/block-backend.h"
> >  #include "sysemu/blockdev.h"
> >  #include "hw/block/block.h"
> >  #include "block/blockjob.h"
> > @@ -221,6 +222,7 @@ void drive_del(DriveInfo *dinfo)
> >      }
> >  
> >      bdrv_unref(dinfo->bdrv);
> > +    blk_unref(blk_by_name(dinfo->id));
> >      g_free(dinfo->id);
> >      QTAILQ_REMOVE(&drives, dinfo, next);
> >      g_free(dinfo->serial);
> > @@ -301,6 +303,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
> >      int ro = 0;
> >      int bdrv_flags = 0;
> >      int on_read_error, on_write_error;
> > +    BlockBackend *blk;
> >      DriveInfo *dinfo;
> >      ThrottleConfig cfg;
> >      int snapshot = 0;
> > @@ -456,6 +459,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
> >      }
> >  
> >      /* init */
> > +    blk = blk_new(qemu_opts_id(opts), errp);
> > +    if (!blk) {
> > +        goto early_err;
> > +    }
> 
> Here you create a new block backend.
> And you don't attach it to anything in any way yet.
> 
> So down in the code the following test will leak it:
>     if (!file || !*file) {                                                      
>         if (has_driver_specific_opts) {                                         
>             file = NULL;                                                        
>         } else {                                                                
>             QDECREF(bs_opts);                                                   
>             qemu_opts_del(opts);                                                
>             return dinfo;                                                       
>         }                                                                       
>     } 
> 
> I am sure one of your next patchs fixes this but for this
> precise commit this do look like a leak.
> 
> >      dinfo = g_malloc0(sizeof(*dinfo));
> >      dinfo->id = g_strdup(qemu_opts_id(opts));
> >      dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
> > @@ -525,6 +532,7 @@ err:
> >  bdrv_new_err:
> >      g_free(dinfo->id);
> >      g_free(dinfo);
> > +    blk_unref(blk);
> >  early_err:
> >      qemu_opts_del(opts);
> >  err_no_opts:
> > @@ -1770,7 +1778,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
> >       */
> >      if (bdrv_get_attached_dev(bs)) {
> >          bdrv_make_anon(bs);
> > -
> > +        blk_unref(blk_by_name(id));
> >          /* Further I/O must not pause the guest */
> >          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
> >                            BLOCKDEV_ON_ERROR_REPORT);
> > diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> > index 8bac7ff..730a021 100644
> > --- a/hw/block/xen_disk.c
> > +++ b/hw/block/xen_disk.c
> > @@ -39,6 +39,7 @@
> >  #include "hw/xen/xen_backend.h"
> >  #include "xen_blkif.h"
> >  #include "sysemu/blockdev.h"
> > +#include "sysemu/block-backend.h"
> >  
> >  /* ------------------------------------------------------------- */
> >  
> > @@ -852,12 +853,18 @@ static int blk_connect(struct XenDevice *xendev)
> >      blkdev->dinfo = drive_get(IF_XEN, 0, index);
> >      if (!blkdev->dinfo) {
> >          Error *local_err = NULL;
> > +        BlockBackend *blk;
> >          BlockDriver *drv;
> >  
> >          /* setup via xenbus -> create new block driver instance */
> >          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
> > +        blk = blk_new(blkdev->dev, NULL);
> > +        if (!blk) {
> > +            return -1;
> > +        }
> >          blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
> >          if (!blkdev->bs) {
> > +            blk_unref(blk);
> >              return -1;
> >          }
> >  
> > @@ -868,6 +875,7 @@ static int blk_connect(struct XenDevice *xendev)
> >                            error_get_pretty(local_err));
> >              error_free(local_err);
> >              bdrv_unref(blkdev->bs);
> > +            blk_unref(blk);
> >              blkdev->bs = NULL;
> >              return -1;
> >          }
> > @@ -983,6 +991,9 @@ static void blk_disconnect(struct XenDevice *xendev)
> >      if (blkdev->bs) {
> >          bdrv_detach_dev(blkdev->bs, blkdev);
> >          bdrv_unref(blkdev->bs);
> > +        if (!blkdev->dinfo) {
> > +            blk_unref(blk_by_name(blkdev->dev));
> > +        }
> >          blkdev->bs = NULL;
> >      }
> >      xen_be_unbind_evtchn(&blkdev->xendev);
> > diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
> > index 5f20b0e..198da2e 100644
> > --- a/include/qemu/typedefs.h
> > +++ b/include/qemu/typedefs.h
> > @@ -35,6 +35,7 @@ typedef struct MachineClass MachineClass;
> >  typedef struct NICInfo NICInfo;
> >  typedef struct HCIInfo HCIInfo;
> >  typedef struct AudioState AudioState;
> > +typedef struct BlockBackend BlockBackend;
> >  typedef struct BlockDriverState BlockDriverState;
> >  typedef struct DriveInfo DriveInfo;
> >  typedef struct DisplayState DisplayState;
> > diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
> > new file mode 100644
> > index 0000000..3f8371c
> > --- /dev/null
> > +++ b/include/sysemu/block-backend.h
> > @@ -0,0 +1,26 @@
> > +/*
> > + * QEMU Block backends
> > + *
> > + * Copyright (C) 2014 Red Hat, Inc.
> > + *
> > + * Authors:
> > + *  Markus Armbruster <armbru@redhat.com>,
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2 or
> > + * later.  See the COPYING file in the top-level directory.
> > + */
> > +
> > +#ifndef BLOCK_BACKEND_H
> > +#define BLOCK_BACKEND_H
> > +
> > +#include "qemu/typedefs.h"
> > +#include "qapi/error.h"
> > +
> > +BlockBackend *blk_new(const char *name, Error **errp);
> > +void blk_ref(BlockBackend *blk);
> > +void blk_unref(BlockBackend *blk);
> > +const char *blk_name(BlockBackend *blk);
> > +BlockBackend *blk_by_name(const char *name);
> > +BlockBackend *blk_next(BlockBackend *blk);
> > +
> > +#endif
> > diff --git a/qemu-img.c b/qemu-img.c
> > index 4490a22..bad3f64 100644
> > --- a/qemu-img.c
> > +++ b/qemu-img.c
> > @@ -29,6 +29,7 @@
> >  #include "qemu/error-report.h"
> >  #include "qemu/osdep.h"
> >  #include "sysemu/sysemu.h"
> > +#include "sysemu/block-backend.h"
> >  #include "block/block_int.h"
> >  #include "block/qapi.h"
> >  #include <getopt.h>
> > @@ -575,6 +576,7 @@ static int img_check(int argc, char **argv)
> >      int c, ret;
> >      OutputFormat output_format = OFORMAT_HUMAN;
> >      const char *filename, *fmt, *output, *cache;
> > +    BlockBackend *blk;
> >      BlockDriverState *bs;
> >      int fix = 0;
> >      int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
> > @@ -649,6 +651,7 @@ static int img_check(int argc, char **argv)
> >          return 1;
> >      }
> >  
> 
> > +    blk = blk_new("image", &error_abort);
> Hmm we are so sure this will work that we don't do if (!block) ?

Ok I understood we are sure because we control the id and won't use twice the same.

> 
> >      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
> >      if (!bs) {
> >          return 1;
> > @@ -710,6 +713,7 @@ static int img_check(int argc, char **argv)
> >  fail:
> >      qapi_free_ImageCheck(check);
> >      bdrv_unref(bs);
> > +    blk_unref(blk);
> >  
> >      return ret;
> >  }
> > @@ -718,6 +722,7 @@ static int img_commit(int argc, char **argv)
> >  {
> >      int c, ret, flags;
> >      const char *filename, *fmt, *cache;
> > +    BlockBackend *blk;
> >      BlockDriverState *bs;
> >      bool quiet = false;
> >  
> > @@ -756,6 +761,7 @@ static int img_commit(int argc, char **argv)
> >          return 1;
> >      }
> >  
> > +    blk = blk_new("image", &error_abort);
> >      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
> >      if (!bs) {
> >          return 1;
> > @@ -780,6 +786,7 @@ static int img_commit(int argc, char **argv)
> >      }
> >  
> >      bdrv_unref(bs);
> > +    blk_unref(blk);
> >      if (ret) {
> >          return 1;
> >      }
> > @@ -942,6 +949,7 @@ static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
> >  static int img_compare(int argc, char **argv)
> >  {
> >      const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
> > +    BlockBackend *blk1, *blk2;
> >      BlockDriverState *bs1, *bs2;
> >      int64_t total_sectors1, total_sectors2;
> >      uint8_t *buf1 = NULL, *buf2 = NULL;
> > @@ -1011,6 +1019,7 @@ static int img_compare(int argc, char **argv)
> >          goto out3;
> >      }
> >  
> > +    blk1 = blk_new("image 1", &error_abort);
> >      bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
> >      if (!bs1) {
> >          error_report("Can't open file %s", filename1);
> > @@ -1018,6 +1027,7 @@ static int img_compare(int argc, char **argv)
> >          goto out3;
> >      }
> >  
> > +    blk2 = blk_new("image 2", &error_abort);
> >      bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
> >      if (!bs2) {
> >          error_report("Can't open file %s", filename2);
> > @@ -1184,10 +1194,12 @@ static int img_compare(int argc, char **argv)
> >  
> >  out:
> >      bdrv_unref(bs2);
> > +    blk_unref(blk2);
> >      qemu_vfree(buf1);
> >      qemu_vfree(buf2);
> >  out2:
> >      bdrv_unref(bs1);
> > +    blk_unref(blk1);
> >  out3:
> >      qemu_progress_end();
> >      return ret;
> > @@ -1200,6 +1212,7 @@ static int img_convert(int argc, char **argv)
> >      int progress = 0, flags, src_flags;
> >      const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
> >      BlockDriver *drv, *proto_drv;
> > +    BlockBackend **blk = NULL, *out_blk = NULL;
> >      BlockDriverState **bs = NULL, *out_bs = NULL;
> >      int64_t total_sectors, nb_sectors, sector_num, bs_offset;
> >      int64_t *bs_sectors = NULL;
> > @@ -1354,6 +1367,7 @@ static int img_convert(int argc, char **argv)
> >  
> >      qemu_progress_print(0, 100);
> >  
> > +    blk = g_new0(BlockBackend *, bs_n);
> >      bs = g_new0(BlockDriverState *, bs_n);
> >      bs_sectors = g_new(int64_t, bs_n);
> >  
> > @@ -1361,6 +1375,7 @@ static int img_convert(int argc, char **argv)
> >      for (bs_i = 0; bs_i < bs_n; bs_i++) {
> >          char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
> >                              : g_strdup("source");
> > +        blk[bs_i] = blk_new(id, &error_abort);
> >          bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
> >                                   true, quiet);
> >          g_free(id);
> > @@ -1486,6 +1501,7 @@ static int img_convert(int argc, char **argv)
> >          goto out;
> >      }
> >  
> > +    out_blk = blk_new("target", &error_abort);
> >      out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
> >      if (!out_bs) {
> >          ret = -1;
> > @@ -1742,6 +1758,7 @@ out:
> >      if (out_bs) {
> >          bdrv_unref(out_bs);
> >      }
> > +    blk_unref(out_blk);
> >      if (bs) {
> >          for (bs_i = 0; bs_i < bs_n; bs_i++) {
> >              if (bs[bs_i]) {
> > @@ -1750,6 +1767,12 @@ out:
> >          }
> >          g_free(bs);
> >      }
> > +    if (blk) {
> > +        for (bs_i = 0; bs_i < bs_n; bs_i++) {
> > +            blk_unref(blk[bs_i]);
> > +        }
> > +        g_free(blk);
> > +    }
> >      g_free(bs_sectors);
> >  fail_getopt:
> >      g_free(options);
> > @@ -1858,6 +1881,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
> >      filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
> >  
> >      while (filename) {
> > +        BlockBackend *blk;
> >          BlockDriverState *bs;
> >          ImageInfo *info;
> >          ImageInfoList *elem;
> > @@ -1869,6 +1893,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
> >          }
> >          g_hash_table_insert(filenames, (gpointer)filename, NULL);
> >  
> > +        blk = blk_new("image", &error_abort);
> >          bs = bdrv_new_open("image", filename, fmt,
> >                             BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
> >          if (!bs) {
> 
> I think it misses an 
> > +            blk_unref(blk);
> in if(!bs) branch.
> 
> > @@ -1880,6 +1905,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
> >              error_report("%s", error_get_pretty(err));
> >              error_free(err);
> >              bdrv_unref(bs);
> > +            blk_unref(blk);
> >              goto err;
> >          }
> >  
> > @@ -1889,6 +1915,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
> >          last = &elem->next;
> >  
> >          bdrv_unref(bs);
> > +        blk_unref(blk);
> >  
> >          filename = fmt = NULL;
> >          if (chain) {
> > @@ -2082,6 +2109,7 @@ static int img_map(int argc, char **argv)
> >  {
> >      int c;
> >      OutputFormat output_format = OFORMAT_HUMAN;
> > +    BlockBackend *blk;
> >      BlockDriverState *bs;
> >      const char *filename, *fmt, *output;
> >      int64_t length;
> > @@ -2130,6 +2158,7 @@ static int img_map(int argc, char **argv)
> >          return 1;
> >      }
> >  
> > +    blk = blk_new("image", &error_abort);
> >      bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
> >      if (!bs) {
> >          return 1;
> > @@ -2175,6 +2204,7 @@ static int img_map(int argc, char **argv)
> >  
> >  out:
> >      bdrv_unref(bs);
> > +    blk_unref(blk);
> >      return ret < 0;
> >  }
> >  
> > @@ -2185,6 +2215,7 @@ out:
> >  
> >  static int img_snapshot(int argc, char **argv)
> >  {
> > +    BlockBackend *blk;
> >      BlockDriverState *bs;
> >      QEMUSnapshotInfo sn;
> >      char *filename, *snapshot_name = NULL;
> > @@ -2250,6 +2281,7 @@ static int img_snapshot(int argc, char **argv)
> >      filename = argv[optind++];
> >  
> >      /* Open the image */
> > +    blk = blk_new("image", &error_abort);
> >      bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
> >      if (!bs) {
> >          return 1;
> > @@ -2297,6 +2329,7 @@ static int img_snapshot(int argc, char **argv)
> >  
> >      /* Cleanup */
> >      bdrv_unref(bs);
> > +    blk_unref(blk);
> >      if (ret) {
> >          return 1;
> >      }
> > @@ -2305,6 +2338,7 @@ static int img_snapshot(int argc, char **argv)
> >  
> >  static int img_rebase(int argc, char **argv)
> >  {
> > +    BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL;
> >      BlockDriverState *bs = NULL, *bs_old_backing = NULL, *bs_new_backing = NULL;
> >      BlockDriver *old_backing_drv, *new_backing_drv;
> >      char *filename;
> > @@ -2393,6 +2427,7 @@ static int img_rebase(int argc, char **argv)
> >       * Ignore the old backing file for unsafe rebase in case we want to correct
> >       * the reference to a renamed or moved backing file.
> >       */
> > +    blk = blk_new("image", &error_abort);
> >      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
> >      if (!bs) {
> >          ret = -1;
> > @@ -2425,6 +2460,7 @@ static int img_rebase(int argc, char **argv)
> >      if (!unsafe) {
> >          char backing_name[1024];
> >  
> > +        blk_old_backing = blk_new("old_backing", &error_abort);
> >          bs_old_backing = bdrv_new_named("old_backing", &error_abort);
> >          bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
> >          ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
> > @@ -2436,6 +2472,7 @@ static int img_rebase(int argc, char **argv)
> >              goto out;
> >          }
> >          if (out_baseimg[0]) {
> > +            blk_new_backing = blk_new("new_backing", &error_abort);
> >              bs_new_backing = bdrv_new_named("new_backing", &error_abort);
> >              ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
> >                              new_backing_drv, &local_err);
> > @@ -2614,12 +2651,15 @@ out:
> >          if (bs_old_backing != NULL) {
> >              bdrv_unref(bs_old_backing);
> >          }
> > +        blk_unref(blk_old_backing);
> >          if (bs_new_backing != NULL) {
> >              bdrv_unref(bs_new_backing);
> >          }
> > +        blk_unref(blk_new_backing);
> >      }
> >  
> >      bdrv_unref(bs);
> > +    blk_unref(blk);
> >      if (ret) {
> >          return 1;
> >      }
> > @@ -2632,6 +2672,7 @@ static int img_resize(int argc, char **argv)
> >      const char *filename, *fmt, *size;
> >      int64_t n, total_size;
> >      bool quiet = false;
> > +    BlockBackend *blk = NULL;
> >      BlockDriverState *bs = NULL;
> >      QemuOpts *param;
> >      static QemuOptsList resize_options = {
> > @@ -2708,6 +2749,7 @@ static int img_resize(int argc, char **argv)
> >      n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
> >      qemu_opts_del(param);
> >  
> > +    blk = blk_new("image", &error_abort);
> >      bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
> >                         true, quiet);
> >      if (!bs) {
> > @@ -2745,6 +2787,7 @@ out:
> >      if (bs) {
> >          bdrv_unref(bs);
> >      }
> > +    blk_unref(blk);
> >      if (ret) {
> >          return 1;
> >      }
> > @@ -2760,6 +2803,7 @@ static int img_amend(int argc, char **argv)
> >      const char *fmt = NULL, *filename, *cache;
> >      int flags;
> >      bool quiet = false;
> > +    BlockBackend *blk = NULL;
> >      BlockDriverState *bs = NULL;
> >  
> >      cache = BDRV_DEFAULT_CACHE;
> > @@ -2823,6 +2867,7 @@ static int img_amend(int argc, char **argv)
> >          goto out;
> >      }
> >  
> > +    blk = blk_new("image", &error_abort);
> >      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
> >      if (!bs) {
> >          error_report("Could not open image '%s'", filename);
> > @@ -2856,6 +2901,7 @@ out:
> >      if (bs) {
> >          bdrv_unref(bs);
> >      }
> > +    blk_unref(blk);
> >      qemu_opts_del(opts);
> >      qemu_opts_free(create_opts);
> >      g_free(options);
> > diff --git a/qemu-io.c b/qemu-io.c
> > index 44c2e1c..45e5494 100644
> > --- a/qemu-io.c
> > +++ b/qemu-io.c
> > @@ -19,6 +19,7 @@
> >  #include "qemu/option.h"
> >  #include "qemu/config-file.h"
> >  #include "qemu/readline.h"
> > +#include "sysemu/block-backend.h"
> >  #include "block/block_int.h"
> >  #include "trace/control.h"
> >  
> > @@ -26,6 +27,7 @@
> >  
> >  static char *progname;
> >  
> > +static BlockBackend *qemuio_blk;
> >  static BlockDriverState *qemuio_bs;
> >  
> >  /* qemu-io commands passed using -c */
> > @@ -37,7 +39,9 @@ static ReadLineState *readline_state;
> >  static int close_f(BlockDriverState *bs, int argc, char **argv)
> >  {
> >      bdrv_unref(bs);
> > +    blk_unref(qemuio_blk);
> >      qemuio_bs = NULL;
> > +    qemuio_blk = NULL;
> >      return 0;
> >  }
> >  
> > @@ -58,6 +62,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
> >          return 1;
> >      }
> >  
> > +    qemuio_blk = blk_new("hda", &error_abort);
> 
> >      qemuio_bs = bdrv_new_named("hda", &error_abort);
> I see accepting that an allocation _will_ work is the qemu tools style.
> 
> >  
> >      if (growable) {
> > @@ -70,7 +75,9 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
> >                  error_get_pretty(local_err));
> >          error_free(local_err);
> >          bdrv_unref(qemuio_bs);
> > +        blk_unref(qemuio_blk);
> >          qemuio_bs = NULL;
> > +        qemuio_blk = NULL;
> >          return 1;
> >      }
> >  
> > @@ -479,6 +486,7 @@ int main(int argc, char **argv)
> >      if (qemuio_bs) {
> >          bdrv_unref(qemuio_bs);
> >      }
> > +    blk_unref(qemuio_blk);
> >      g_free(readline_state);
> >      return 0;
> >  }
> > diff --git a/qemu-nbd.c b/qemu-nbd.c
> > index a56ebfc..94b9b49 100644
> > --- a/qemu-nbd.c
> > +++ b/qemu-nbd.c
> > @@ -17,7 +17,7 @@
> >   */
> >  
> >  #include "qemu-common.h"
> > -#include "block/block.h"
> > +#include "sysemu/block-backend.h"
> >  #include "block/block_int.h"
> >  #include "block/nbd.h"
> >  #include "qemu/main-loop.h"
> > @@ -687,6 +687,7 @@ int main(int argc, char **argv)
> >          drv = NULL;
> >      }
> >  
> > +    blk_new("hda", &error_abort);
> >      bs = bdrv_new_named("hda", &error_abort);
> >  
> >      srcpath = argv[optind];
> > -- 
> > 1.9.3
> > 
> > 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo Markus Armbruster
@ 2014-09-10 13:08   ` Benoît Canet
  2014-09-11 18:03     ` Markus Armbruster
  2014-09-10 13:30   ` Kevin Wolf
  1 sibling, 1 reply; 76+ messages in thread
From: Benoît Canet @ 2014-09-10 13:08 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:33 (+0200), Markus Armbruster wrote :
> Make the BlockBackend own the DriveInfo.  Change blockdev_init() to
> return the BlockBackend instead of the DriveInfo.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block/block-backend.c     | 38 +++++++++++++++++++++++
>  blockdev.c                | 79 +++++++++++++++++++++--------------------------
>  include/sysemu/blockdev.h |  4 +++
>  3 files changed, 78 insertions(+), 43 deletions(-)
> 
> diff --git a/block/block-backend.c b/block/block-backend.c
> index deccb54..2a22660 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -12,14 +12,18 @@
>  
>  #include "sysemu/block-backend.h"
>  #include "block/block_int.h"
> +#include "sysemu/blockdev.h"
>  
>  struct BlockBackend {
>      char *name;
>      int refcnt;
>      BlockDriverState *bs;
> +    DriveInfo *legacy_dinfo;
>      QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
>  };
>  

> +static void drive_info_del(DriveInfo *dinfo);

Is there any technical reason not to just put the
drive_info_del above the blk_delete function ?
I don't see any possible circular references between the two.

Some people like Eric frown upon static function prototypes
in final code that's why I am asking.

> +
>  static QTAILQ_HEAD(, BlockBackend) blk_backends =
>      QTAILQ_HEAD_INITIALIZER(blk_backends);
>  
> @@ -87,6 +91,7 @@ static void blk_delete(BlockBackend *blk)
>      blk_detach_bs(blk);
>      QTAILQ_REMOVE(&blk_backends, blk, link);
>      g_free(blk->name);
> +    drive_info_del(blk->legacy_dinfo);
>      g_free(blk);
>  }
>  
> @@ -119,6 +124,16 @@ void blk_unref(BlockBackend *blk)
>      }
>  }
>  
> +static void drive_info_del(DriveInfo *dinfo)
> +{
> +    if (dinfo) {
> +        qemu_opts_del(dinfo->opts);
> +        g_free(dinfo->id);
> +        g_free(dinfo->serial);
> +        g_free(dinfo);
> +    }
> +}
> +
>  const char *blk_name(BlockBackend *blk)
>  {
>      return blk->name;
> @@ -187,3 +202,26 @@ BlockDriverState *blk_detach_bs(BlockBackend *blk)
>      }
>      return bs;
>  }
> +
> +DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
> +{
> +    return blk->legacy_dinfo;
> +}
> +
> +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
> +{
> +    assert(!blk->legacy_dinfo);
> +    return blk->legacy_dinfo = dinfo;
> +}
> +
> +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
> +{
> +    BlockBackend *blk;
> +
> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
> +        if (blk->legacy_dinfo == dinfo) {
> +            return blk;
> +        }
> +    }
> +    assert(0);
> +}
> diff --git a/blockdev.c b/blockdev.c
> index 0a0b95e..73e2da9 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -47,8 +47,6 @@
>  #include "trace.h"
>  #include "sysemu/arch_init.h"
>  
> -static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
> -
>  static const char *const if_name[IF_COUNT] = {
>      [IF_NONE] = "none",
>      [IF_IDE] = "ide",
> @@ -89,7 +87,8 @@ static const int if_max_devs[IF_COUNT] = {
>   */
>  void blockdev_mark_auto_del(BlockDriverState *bs)
>  {
> -    DriveInfo *dinfo = drive_get_by_blockdev(bs);
> +    BlockBackend *blk = bs->blk;
> +    DriveInfo *dinfo = blk_legacy_dinfo(blk);
>  
>      if (dinfo && !dinfo->enable_auto_del) {
>          return;
> @@ -105,7 +104,8 @@ void blockdev_mark_auto_del(BlockDriverState *bs)
>  
>  void blockdev_auto_del(BlockDriverState *bs)
>  {
> -    DriveInfo *dinfo = drive_get_by_blockdev(bs);
> +    BlockBackend *blk = bs->blk;
> +    DriveInfo *dinfo = blk_legacy_dinfo(blk);
>  
>      if (dinfo && dinfo->auto_del) {
>          drive_del(dinfo);
> @@ -153,15 +153,15 @@ QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
>  
>  DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
>  {
> +    BlockBackend *blk;
>      DriveInfo *dinfo;
>  
> -    /* seek interface, bus and unit */
> -
> -    QTAILQ_FOREACH(dinfo, &drives, next) {
> -        if (dinfo->type == type &&
> -	    dinfo->bus == bus &&
> -	    dinfo->unit == unit)
> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {

Here I understand why you didn't made blk_next pure round robin circling in a loop.
Maybe the comments of the blk_next function should say it's just an iterator.

> +        dinfo = blk_legacy_dinfo(blk);
> +        if (dinfo && dinfo->type == type
> +            && dinfo->bus == bus && dinfo->unit == unit) {
>              return dinfo;
> +        }
>      }
>  
>      return NULL;
> @@ -177,13 +177,15 @@ DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
>  int drive_get_max_bus(BlockInterfaceType type)
>  {
>      int max_bus;
> +    BlockBackend *blk;
>      DriveInfo *dinfo;
>  
>      max_bus = -1;
> -    QTAILQ_FOREACH(dinfo, &drives, next) {
> -        if(dinfo->type == type &&
> -           dinfo->bus > max_bus)
> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
> +        dinfo = blk_legacy_dinfo(blk);
> +        if (dinfo && dinfo->type == type && dinfo->bus > max_bus) {
>              max_bus = dinfo->bus;
> +        }
>      }
>      return max_bus;
>  }
> @@ -200,11 +202,11 @@ DriveInfo *drive_get_next(BlockInterfaceType type)
>  
>  DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
>  {
> -    DriveInfo *dinfo;
> +    BlockBackend *blk;
>  
> -    QTAILQ_FOREACH(dinfo, &drives, next) {
> -        if (dinfo->bdrv == bs) {
> -            return dinfo;
> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
> +        if (blk_bs(blk) == bs) {
> +            return blk_legacy_dinfo(blk);
>          }
>      }
>      return NULL;
> @@ -217,16 +219,10 @@ static void bdrv_format_print(void *opaque, const char *name)
>  
>  void drive_del(DriveInfo *dinfo)
>  {
> -    if (dinfo->opts) {
> -        qemu_opts_del(dinfo->opts);
> -    }
> +    BlockBackend *blk = dinfo->bdrv->blk;
>  
>      bdrv_unref(dinfo->bdrv);
> -    blk_unref(blk_by_name(dinfo->id));
> -    g_free(dinfo->id);
> -    QTAILQ_REMOVE(&drives, dinfo, next);
> -    g_free(dinfo->serial);
> -    g_free(dinfo);
> +    blk_unref(blk);
>  }
>  
>  typedef struct {
> @@ -296,8 +292,8 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
>  typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
>  
>  /* Takes the ownership of bs_opts */
> -static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
> -                                Error **errp)
> +static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
> +                                   Error **errp)
>  {
>      const char *buf;
>      int ro = 0;
> @@ -480,7 +476,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
>      dinfo->bdrv = bs;
> -    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
> +    blk_set_legacy_dinfo(blk, dinfo);
>  
>      if (!file || !*file) {
>          if (has_driver_specific_opts) {
> @@ -488,7 +484,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>          } else {
>              QDECREF(bs_opts);
>              qemu_opts_del(opts);
> -            return dinfo;

> +            return blk;
Here you fix the leak I found on a previous patch.

>          }
>      }
>      if (snapshot) {
> @@ -525,13 +521,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      QDECREF(bs_opts);
>      qemu_opts_del(opts);
>  
> -    return dinfo;
> +    return blk;
>  
>  err:
>      bdrv_unref(dinfo->bdrv);
> -    QTAILQ_REMOVE(&drives, dinfo, next);
> -    g_free(dinfo->id);
> -    g_free(dinfo);
>      blk_unref(blk);
>  early_err:
>      qemu_opts_del(opts);
> @@ -635,6 +628,7 @@ QemuOptsList qemu_legacy_drive_opts = {
>  DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>  {
>      const char *value;
> +    BlockBackend *blk;
>      DriveInfo *dinfo = NULL;
>      QDict *bs_opts;
>      QemuOpts *legacy_opts;
> @@ -917,19 +911,17 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>      }
>  
>      /* Actual block device init: Functionality shared with blockdev-add */
> -    dinfo = blockdev_init(filename, bs_opts, &local_err);
> +    blk = blockdev_init(filename, bs_opts, &local_err);
>      bs_opts = NULL;
> -    if (dinfo == NULL) {
> -        if (local_err) {
> -            error_report("%s", error_get_pretty(local_err));
> -            error_free(local_err);
> -        }

> +    if (!blk) {

Just down the code an existing test does if (local_err) { after
blk = blockdev_init(NULL, qdict, &local_err);.

Is the prefered convention checking blk or local_err ?

> +        error_report("%s", error_get_pretty(local_err));
>          goto fail;
>      } else {
>          assert(!local_err);
>      }
>  
>      /* Set legacy DriveInfo fields */
> +    dinfo = blk_legacy_dinfo(blk);
>      dinfo->enable_auto_del = true;
>      dinfo->opts = all_opts;
>  
> @@ -2478,7 +2470,7 @@ void qmp_change_backing_file(const char *device,
>  void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
>  {
>      QmpOutputVisitor *ov = qmp_output_visitor_new();
> -    DriveInfo *dinfo;
> +    BlockBackend *blk;
>      QObject *obj;
>      QDict *qdict;
>      Error *local_err = NULL;
> @@ -2516,14 +2508,15 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
>  
>      qdict_flatten(qdict);
>  
> -    dinfo = blockdev_init(NULL, qdict, &local_err);
> +    blk = blockdev_init(NULL, qdict, &local_err);
>      if (local_err) {
>          error_propagate(errp, local_err);
>          goto fail;
>      }
>  
> -    if (bdrv_key_required(dinfo->bdrv)) {
> -        drive_del(dinfo);
> +    if (bdrv_key_required(blk_bs(blk))) {
> +        bdrv_unref(blk_bs(blk));
> +        blk_unref(blk);
>          error_setg(errp, "blockdev-add doesn't support encrypted devices");
>          goto fail;
>      }
> diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
> index 23a5d10..2ed297b 100644
> --- a/include/sysemu/blockdev.h
> +++ b/include/sysemu/blockdev.h
> @@ -45,6 +45,10 @@ struct DriveInfo {
>      QTAILQ_ENTRY(DriveInfo) next;
>  };
>  
> +DriveInfo *blk_legacy_dinfo(BlockBackend *blk);
> +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo);
> +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo);
> +
>  DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
>  DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
>  int drive_get_max_bus(BlockInterfaceType type);
> -- 
> 1.9.3
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo Markus Armbruster
  2014-09-10 13:08   ` Benoît Canet
@ 2014-09-10 13:30   ` Kevin Wolf
  2014-09-11 17:41     ` Markus Armbruster
  1 sibling, 1 reply; 76+ messages in thread
From: Kevin Wolf @ 2014-09-10 13:30 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: benoit.canet, famz, qemu-devel, stefanha

Am 10.09.2014 um 10:13 hat Markus Armbruster geschrieben:
> Make the BlockBackend own the DriveInfo.  Change blockdev_init() to
> return the BlockBackend instead of the DriveInfo.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block/block-backend.c     | 38 +++++++++++++++++++++++
>  blockdev.c                | 79 +++++++++++++++++++++--------------------------
>  include/sysemu/blockdev.h |  4 +++
>  3 files changed, 78 insertions(+), 43 deletions(-)
> 
> diff --git a/block/block-backend.c b/block/block-backend.c
> index deccb54..2a22660 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -12,14 +12,18 @@
>  
>  #include "sysemu/block-backend.h"
>  #include "block/block_int.h"
> +#include "sysemu/blockdev.h"
>  
>  struct BlockBackend {
>      char *name;
>      int refcnt;
>      BlockDriverState *bs;
> +    DriveInfo *legacy_dinfo;
>      QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
>  };
>  
> +static void drive_info_del(DriveInfo *dinfo);
> +
>  static QTAILQ_HEAD(, BlockBackend) blk_backends =
>      QTAILQ_HEAD_INITIALIZER(blk_backends);
>  
> @@ -87,6 +91,7 @@ static void blk_delete(BlockBackend *blk)
>      blk_detach_bs(blk);
>      QTAILQ_REMOVE(&blk_backends, blk, link);
>      g_free(blk->name);
> +    drive_info_del(blk->legacy_dinfo);
>      g_free(blk);
>  }
>  
> @@ -119,6 +124,16 @@ void blk_unref(BlockBackend *blk)
>      }
>  }
>  
> +static void drive_info_del(DriveInfo *dinfo)
> +{
> +    if (dinfo) {
> +        qemu_opts_del(dinfo->opts);
> +        g_free(dinfo->id);
> +        g_free(dinfo->serial);
> +        g_free(dinfo);
> +    }
> +}
> +
>  const char *blk_name(BlockBackend *blk)
>  {
>      return blk->name;
> @@ -187,3 +202,26 @@ BlockDriverState *blk_detach_bs(BlockBackend *blk)
>      }
>      return bs;
>  }
> +
> +DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
> +{
> +    return blk->legacy_dinfo;
> +}
> +
> +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
> +{
> +    assert(!blk->legacy_dinfo);
> +    return blk->legacy_dinfo = dinfo;
> +}
> +
> +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
> +{
> +    BlockBackend *blk;
> +
> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
> +        if (blk->legacy_dinfo == dinfo) {
> +            return blk;
> +        }
> +    }
> +    assert(0);
> +}
> diff --git a/blockdev.c b/blockdev.c
> index 0a0b95e..73e2da9 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -47,8 +47,6 @@
>  #include "trace.h"
>  #include "sysemu/arch_init.h"
>  
> -static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
> -
>  static const char *const if_name[IF_COUNT] = {
>      [IF_NONE] = "none",
>      [IF_IDE] = "ide",
> @@ -89,7 +87,8 @@ static const int if_max_devs[IF_COUNT] = {
>   */
>  void blockdev_mark_auto_del(BlockDriverState *bs)
>  {
> -    DriveInfo *dinfo = drive_get_by_blockdev(bs);
> +    BlockBackend *blk = bs->blk;
> +    DriveInfo *dinfo = blk_legacy_dinfo(blk);
>  
>      if (dinfo && !dinfo->enable_auto_del) {
>          return;
> @@ -105,7 +104,8 @@ void blockdev_mark_auto_del(BlockDriverState *bs)
>  
>  void blockdev_auto_del(BlockDriverState *bs)
>  {
> -    DriveInfo *dinfo = drive_get_by_blockdev(bs);
> +    BlockBackend *blk = bs->blk;
> +    DriveInfo *dinfo = blk_legacy_dinfo(blk);
>  
>      if (dinfo && dinfo->auto_del) {
>          drive_del(dinfo);

The if condition looks as if there were cases where dinfo was NULL. To
be precise, this was introduced in commit 0fc0f1fa, so that hot unplug
after a forced drive_del wouldn't segfault.

Does such a device that doesn't have a dinfo at least have a
BlockBackend? If it doesn't, we'll segfault in blk_legacy_dinfo(). I
won't say that I understand that part of the code, but I can't see why
BlockBackend would still be there when DriveInfo isn't any more.

> @@ -153,15 +153,15 @@ QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
>  
>  DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
>  {
> +    BlockBackend *blk;
>      DriveInfo *dinfo;
>  
> -    /* seek interface, bus and unit */
> -
> -    QTAILQ_FOREACH(dinfo, &drives, next) {
> -        if (dinfo->type == type &&
> -	    dinfo->bus == bus &&
> -	    dinfo->unit == unit)
> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
> +        dinfo = blk_legacy_dinfo(blk);
> +        if (dinfo && dinfo->type == type
> +            && dinfo->bus == bus && dinfo->unit == unit) {
>              return dinfo;
> +        }
>      }
>  
>      return NULL;
> @@ -177,13 +177,15 @@ DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
>  int drive_get_max_bus(BlockInterfaceType type)
>  {
>      int max_bus;
> +    BlockBackend *blk;
>      DriveInfo *dinfo;
>  
>      max_bus = -1;
> -    QTAILQ_FOREACH(dinfo, &drives, next) {
> -        if(dinfo->type == type &&
> -           dinfo->bus > max_bus)
> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
> +        dinfo = blk_legacy_dinfo(blk);
> +        if (dinfo && dinfo->type == type && dinfo->bus > max_bus) {
>              max_bus = dinfo->bus;
> +        }
>      }
>      return max_bus;
>  }
> @@ -200,11 +202,11 @@ DriveInfo *drive_get_next(BlockInterfaceType type)
>  
>  DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
>  {
> -    DriveInfo *dinfo;
> +    BlockBackend *blk;
>  
> -    QTAILQ_FOREACH(dinfo, &drives, next) {
> -        if (dinfo->bdrv == bs) {
> -            return dinfo;
> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
> +        if (blk_bs(blk) == bs) {
> +            return blk_legacy_dinfo(blk);
>          }
>      }
>      return NULL;
> @@ -217,16 +219,10 @@ static void bdrv_format_print(void *opaque, const char *name)
>  
>  void drive_del(DriveInfo *dinfo)
>  {
> -    if (dinfo->opts) {
> -        qemu_opts_del(dinfo->opts);
> -    }
> +    BlockBackend *blk = dinfo->bdrv->blk;
>  
>      bdrv_unref(dinfo->bdrv);
> -    blk_unref(blk_by_name(dinfo->id));
> -    g_free(dinfo->id);
> -    QTAILQ_REMOVE(&drives, dinfo, next);
> -    g_free(dinfo->serial);
> -    g_free(dinfo);
> +    blk_unref(blk);
>  }

Now the dinfo stays alive until the last reference for blk is gone. We
probably don't care much about the memory that isn't used any more, but
not freed yet. What about dinfo->opts? Does it block IDs that should be
available again?

Do we need a dinfo_attach/detach like for BDSes?

>  typedef struct {
> @@ -296,8 +292,8 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
>  typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
>  
>  /* Takes the ownership of bs_opts */
> -static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
> -                                Error **errp)
> +static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
> +                                   Error **errp)
>  {
>      const char *buf;
>      int ro = 0;
> @@ -480,7 +476,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
>      dinfo->bdrv = bs;
> -    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
> +    blk_set_legacy_dinfo(blk, dinfo);
>  
>      if (!file || !*file) {
>          if (has_driver_specific_opts) {
> @@ -488,7 +484,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>          } else {
>              QDECREF(bs_opts);
>              qemu_opts_del(opts);
> -            return dinfo;
> +            return blk;
>          }
>      }
>      if (snapshot) {
> @@ -525,13 +521,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      QDECREF(bs_opts);
>      qemu_opts_del(opts);
>  
> -    return dinfo;
> +    return blk;
>  
>  err:
>      bdrv_unref(dinfo->bdrv);
> -    QTAILQ_REMOVE(&drives, dinfo, next);
> -    g_free(dinfo->id);
> -    g_free(dinfo);
>      blk_unref(blk);
>  early_err:
>      qemu_opts_del(opts);
> @@ -635,6 +628,7 @@ QemuOptsList qemu_legacy_drive_opts = {
>  DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>  {
>      const char *value;
> +    BlockBackend *blk;
>      DriveInfo *dinfo = NULL;
>      QDict *bs_opts;
>      QemuOpts *legacy_opts;
> @@ -917,19 +911,17 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>      }
>  
>      /* Actual block device init: Functionality shared with blockdev-add */
> -    dinfo = blockdev_init(filename, bs_opts, &local_err);
> +    blk = blockdev_init(filename, bs_opts, &local_err);
>      bs_opts = NULL;
> -    if (dinfo == NULL) {
> -        if (local_err) {
> -            error_report("%s", error_get_pretty(local_err));
> -            error_free(local_err);
> -        }
> +    if (!blk) {
> +        error_report("%s", error_get_pretty(local_err));

Now local_err is leaked.

>          goto fail;
>      } else {
>          assert(!local_err);
>      }

Kevin

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new()
  2014-09-10 11:03   ` Benoît Canet
@ 2014-09-10 15:05     ` Eric Blake
  2014-09-11  8:20       ` Markus Armbruster
  2014-09-11  8:29     ` Markus Armbruster
  1 sibling, 1 reply; 76+ messages in thread
From: Eric Blake @ 2014-09-10 15:05 UTC (permalink / raw)
  To: Benoît Canet, Markus Armbruster; +Cc: kwolf, famz, qemu-devel, stefanha

[-- Attachment #1: Type: text/plain, Size: 1221 bytes --]

On 09/10/2014 05:03 AM, Benoît Canet wrote:
> The Wednesday 10 Sep 2014 à 10:13:30 (+0200), Markus Armbruster wrote :
>> Creating an anonymous BDS can't fail.  Make that obvious.
>>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---

>>  /* create a new block device (by default it is empty) */
>> -BlockDriverState *bdrv_new(const char *device_name, Error **errp)
>> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
>>  {
>>      BlockDriverState *bs;
>> -    int i;
>> +
>> +    assert(*device_name);
> 
> This assert that device_name is not a null pointer.

No, it assumes that device_name is non-NULL and blindly dereferences it;
it is asserting that the first byte of the dereferenced pointer is not NUL.

> But here we are pretty sure that the BDS should be named given the name of the function.
> Should we bake an assert on device_name[0] != '\0' to avoid bdrv_new_named being called
> with "" as device_name ?

That's already what the code does.  About the only thing it could do
differently is:

assert(device_name && *device_name);

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new()
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new() Markus Armbruster
  2014-09-10 11:03   ` Benoît Canet
@ 2014-09-10 15:07   ` Eric Blake
  2014-09-10 15:27   ` Benoît Canet
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 76+ messages in thread
From: Eric Blake @ 2014-09-10 15:07 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

[-- Attachment #1: Type: text/plain, Size: 726 bytes --]

On 09/10/2014 02:13 AM, Markus Armbruster wrote:
> Creating an anonymous BDS can't fail.  Make that obvious.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block.c               | 26 +++++++++++++++++++-------
>  block/iscsi.c         |  2 +-
>  block/vvfat.c         |  2 +-
>  blockdev.c            |  2 +-
>  hw/block/xen_disk.c   |  2 +-
>  include/block/block.h |  3 ++-
>  qemu-img.c            |  6 +++---
>  qemu-io.c             |  2 +-
>  qemu-nbd.c            |  2 +-
>  9 files changed, 30 insertions(+), 17 deletions(-)

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new()
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new() Markus Armbruster
  2014-09-10 11:03   ` Benoît Canet
  2014-09-10 15:07   ` Eric Blake
@ 2014-09-10 15:27   ` Benoît Canet
  2014-09-10 21:22   ` Benoît Canet
  2014-09-11  6:33   ` Fam Zheng
  4 siblings, 0 replies; 76+ messages in thread
From: Benoît Canet @ 2014-09-10 15:27 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:30 (+0200), Markus Armbruster wrote :
> Creating an anonymous BDS can't fail.  Make that obvious.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block.c               | 26 +++++++++++++++++++-------
>  block/iscsi.c         |  2 +-
>  block/vvfat.c         |  2 +-
>  blockdev.c            |  2 +-
>  hw/block/xen_disk.c   |  2 +-
>  include/block/block.h |  3 ++-
>  qemu-img.c            |  6 +++---
>  qemu-io.c             |  2 +-
>  qemu-nbd.c            |  2 +-
>  9 files changed, 30 insertions(+), 17 deletions(-)
> 
> diff --git a/block.c b/block.c
> index d06dd51..4b3bcd4 100644
> --- a/block.c
> +++ b/block.c
> @@ -335,10 +335,11 @@ void bdrv_register(BlockDriver *bdrv)
>  }
>  
>  /* create a new block device (by default it is empty) */
> -BlockDriverState *bdrv_new(const char *device_name, Error **errp)
> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
>  {
>      BlockDriverState *bs;
> -    int i;
> +
> +    assert(*device_name);
>  
>      if (bdrv_find(device_name)) {
>          error_setg(errp, "Device with id '%s' already exists",
> @@ -351,12 +352,23 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
>          return NULL;
>      }
>  
> -    bs = g_new0(BlockDriverState, 1);
> -    QLIST_INIT(&bs->dirty_bitmaps);
> +    bs = bdrv_new();
> +
>      pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
>      if (device_name[0] != '\0') {
>          QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
>      }
> +
> +    return bs;
> +}
> +
> +BlockDriverState *bdrv_new(void)
> +{
> +    BlockDriverState *bs;
> +    int i;
> +
> +    bs = g_new0(BlockDriverState, 1);
> +    QLIST_INIT(&bs->dirty_bitmaps);
>      for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
>          QLIST_INIT(&bs->op_blockers[i]);
>      }
> @@ -1217,7 +1229,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
>          goto free_exit;
>      }
>  
> -    backing_hd = bdrv_new("", errp);
> +    backing_hd = bdrv_new();
>  
>      if (bs->backing_format[0] != '\0') {
>          back_drv = bdrv_find_format(bs->backing_format);
> @@ -1346,7 +1358,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
>      qdict_put(snapshot_options, "file.filename",
>                qstring_from_str(tmp_filename));
>  
> -    bs_snapshot = bdrv_new("", &error_abort);
> +    bs_snapshot = bdrv_new();
>  
>      ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
>                      flags, bdrv_qcow2, &local_err);
> @@ -1417,7 +1429,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
>      if (*pbs) {
>          bs = *pbs;
>      } else {
> -        bs = bdrv_new("", &error_abort);
> +        bs = bdrv_new();
>      }
>  
>      /* NULL means an empty set of options */
> diff --git a/block/iscsi.c b/block/iscsi.c
> index 3e19202..af3d0f6 100644
> --- a/block/iscsi.c
> +++ b/block/iscsi.c
> @@ -1528,7 +1528,7 @@ static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
>      IscsiLun *iscsilun = NULL;
>      QDict *bs_options;
>  
> -    bs = bdrv_new("", &error_abort);
> +    bs = bdrv_new();
>  
>      /* Read out options */
>      total_size =
> diff --git a/block/vvfat.c b/block/vvfat.c
> index 731e591..6c9fde0 100644
> --- a/block/vvfat.c
> +++ b/block/vvfat.c
> @@ -2939,7 +2939,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
>      unlink(s->qcow_filename);
>  #endif
>  
> -    bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort));
> +    bdrv_set_backing_hd(s->bs, bdrv_new());
>      s->bs->backing_hd->drv = &vvfat_write_target;
>      s->bs->backing_hd->opaque = g_new(void *, 1);
>      *(void**)s->bs->backing_hd->opaque = s;
> diff --git a/blockdev.c b/blockdev.c
> index e919566..9fbd888 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -458,7 +458,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      /* init */
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
> -    dinfo->bdrv = bdrv_new(dinfo->id, &error);
> +    dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
>      if (error) {
>          error_propagate(errp, error);
>          goto bdrv_new_err;
> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> index 2dcef07..8bac7ff 100644
> --- a/hw/block/xen_disk.c
> +++ b/hw/block/xen_disk.c
> @@ -856,7 +856,7 @@ static int blk_connect(struct XenDevice *xendev)
>  
>          /* setup via xenbus -> create new block driver instance */
>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
> -        blkdev->bs = bdrv_new(blkdev->dev, NULL);
> +        blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
>          if (!blkdev->bs) {
>              return -1;
>          }
> diff --git a/include/block/block.h b/include/block/block.h
> index 8f4ad16..95139c0 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -203,7 +203,8 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
>  int bdrv_create(BlockDriver *drv, const char* filename,
>                  QemuOpts *opts, Error **errp);
>  int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
> -BlockDriverState *bdrv_new(const char *device_name, Error **errp);
> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp);
> +BlockDriverState *bdrv_new(void);
>  void bdrv_make_anon(BlockDriverState *bs);
>  void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
>  void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
> diff --git a/qemu-img.c b/qemu-img.c
> index 91d1ac3..4490a22 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -296,7 +296,7 @@ static BlockDriverState *bdrv_new_open(const char *id,
>      Error *local_err = NULL;
>      int ret;
>  
> -    bs = bdrv_new(id, &error_abort);
> +    bs = bdrv_new_named(id, &error_abort);
>  
>      if (fmt) {
>          drv = bdrv_find_format(fmt);
> @@ -2425,7 +2425,7 @@ static int img_rebase(int argc, char **argv)
>      if (!unsafe) {
>          char backing_name[1024];
>  
> -        bs_old_backing = bdrv_new("old_backing", &error_abort);
> +        bs_old_backing = bdrv_new_named("old_backing", &error_abort);
>          bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
>          ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
>                          old_backing_drv, &local_err);
> @@ -2436,7 +2436,7 @@ static int img_rebase(int argc, char **argv)
>              goto out;
>          }
>          if (out_baseimg[0]) {
> -            bs_new_backing = bdrv_new("new_backing", &error_abort);
> +            bs_new_backing = bdrv_new_named("new_backing", &error_abort);
>              ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
>                              new_backing_drv, &local_err);
>              if (ret) {
> diff --git a/qemu-io.c b/qemu-io.c
> index d2ab694..44c2e1c 100644
> --- a/qemu-io.c
> +++ b/qemu-io.c
> @@ -58,7 +58,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
>          return 1;
>      }
>  
> -    qemuio_bs = bdrv_new("hda", &error_abort);
> +    qemuio_bs = bdrv_new_named("hda", &error_abort);
>  
>      if (growable) {
>          flags |= BDRV_O_PROTOCOL;
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index 9bc152e..a56ebfc 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -687,7 +687,7 @@ int main(int argc, char **argv)
>          drv = NULL;
>      }
>  
> -    bs = bdrv_new("hda", &error_abort);
> +    bs = bdrv_new_named("hda", &error_abort);
>  
>      srcpath = argv[optind];
>      ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
> -- 
> 1.9.3
> 
Reviewed-by: Benoît Canet <benoit.canet@nodalink.com>

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[]
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[] Markus Armbruster
@ 2014-09-10 16:09   ` Eric Blake
  2014-09-11 18:45     ` Markus Armbruster
  2014-09-11 11:34   ` Benoît Canet
  1 sibling, 1 reply; 76+ messages in thread
From: Eric Blake @ 2014-09-10 16:09 UTC (permalink / raw)
  To: Markus Armbruster, qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

[-- Attachment #1: Type: text/plain, Size: 794 bytes --]

On 09/10/2014 02:13 AM, Markus Armbruster wrote:
> device_name[] is can become non-empty only in bdrv_new_named() and

s/is //

> bdrv_move_feature_fields().  The latter is used only to undo damage
> done by bdrv_swap().  The former is called only by blk_new_with_bs().
> Therefore, when a BlockDriverState's device_name[] is non-empty, then
> it's owned by a BlockBackend.
> 
> The converse is also true, because blk_attach_bs() is called only by
> blk_new_with_bs() so far.
> 
> Furthermore, blk_new_with_bs() keeps the two names equal.
> 
> Therefore, device_name[] is redundant.  Eliminate it.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---


-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new()
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new() Markus Armbruster
                     ` (2 preceding siblings ...)
  2014-09-10 15:27   ` Benoît Canet
@ 2014-09-10 21:22   ` Benoît Canet
  2014-09-11  6:33   ` Fam Zheng
  4 siblings, 0 replies; 76+ messages in thread
From: Benoît Canet @ 2014-09-10 21:22 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:30 (+0200), Markus Armbruster wrote :
> Creating an anonymous BDS can't fail.  Make that obvious.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block.c               | 26 +++++++++++++++++++-------
>  block/iscsi.c         |  2 +-
>  block/vvfat.c         |  2 +-
>  blockdev.c            |  2 +-
>  hw/block/xen_disk.c   |  2 +-
>  include/block/block.h |  3 ++-
>  qemu-img.c            |  6 +++---
>  qemu-io.c             |  2 +-
>  qemu-nbd.c            |  2 +-
>  9 files changed, 30 insertions(+), 17 deletions(-)
> 
> diff --git a/block.c b/block.c
> index d06dd51..4b3bcd4 100644
> --- a/block.c
> +++ b/block.c
> @@ -335,10 +335,11 @@ void bdrv_register(BlockDriver *bdrv)
>  }
>  
>  /* create a new block device (by default it is empty) */
> -BlockDriverState *bdrv_new(const char *device_name, Error **errp)
> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
>  {
>      BlockDriverState *bs;
> -    int i;
> +
> +    assert(*device_name);
>  
>      if (bdrv_find(device_name)) {
>          error_setg(errp, "Device with id '%s' already exists",
> @@ -351,12 +352,23 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
>          return NULL;
>      }
>  
> -    bs = g_new0(BlockDriverState, 1);
> -    QLIST_INIT(&bs->dirty_bitmaps);
> +    bs = bdrv_new();
> +
>      pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
>      if (device_name[0] != '\0') {

If finally understood why I said crap about the above assert.
If *device_name is true then device_name[0] != '\0' is true.
I diagnosed it in reverse.

I think we can remove the if up here the code will be simpler.

>          QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
>      }
> +
> +    return bs;
> +}
> +
> +BlockDriverState *bdrv_new(void)
> +{
> +    BlockDriverState *bs;
> +    int i;
> +
> +    bs = g_new0(BlockDriverState, 1);
> +    QLIST_INIT(&bs->dirty_bitmaps);
>      for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
>          QLIST_INIT(&bs->op_blockers[i]);
>      }
> @@ -1217,7 +1229,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
>          goto free_exit;
>      }
>  
> -    backing_hd = bdrv_new("", errp);
> +    backing_hd = bdrv_new();
>  
>      if (bs->backing_format[0] != '\0') {
>          back_drv = bdrv_find_format(bs->backing_format);
> @@ -1346,7 +1358,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
>      qdict_put(snapshot_options, "file.filename",
>                qstring_from_str(tmp_filename));
>  
> -    bs_snapshot = bdrv_new("", &error_abort);
> +    bs_snapshot = bdrv_new();
>  
>      ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
>                      flags, bdrv_qcow2, &local_err);
> @@ -1417,7 +1429,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
>      if (*pbs) {
>          bs = *pbs;
>      } else {
> -        bs = bdrv_new("", &error_abort);
> +        bs = bdrv_new();
>      }
>  
>      /* NULL means an empty set of options */
> diff --git a/block/iscsi.c b/block/iscsi.c
> index 3e19202..af3d0f6 100644
> --- a/block/iscsi.c
> +++ b/block/iscsi.c
> @@ -1528,7 +1528,7 @@ static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
>      IscsiLun *iscsilun = NULL;
>      QDict *bs_options;
>  
> -    bs = bdrv_new("", &error_abort);
> +    bs = bdrv_new();
>  
>      /* Read out options */
>      total_size =
> diff --git a/block/vvfat.c b/block/vvfat.c
> index 731e591..6c9fde0 100644
> --- a/block/vvfat.c
> +++ b/block/vvfat.c
> @@ -2939,7 +2939,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
>      unlink(s->qcow_filename);
>  #endif
>  
> -    bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort));
> +    bdrv_set_backing_hd(s->bs, bdrv_new());
>      s->bs->backing_hd->drv = &vvfat_write_target;
>      s->bs->backing_hd->opaque = g_new(void *, 1);
>      *(void**)s->bs->backing_hd->opaque = s;
> diff --git a/blockdev.c b/blockdev.c
> index e919566..9fbd888 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -458,7 +458,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      /* init */
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
> -    dinfo->bdrv = bdrv_new(dinfo->id, &error);
> +    dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
>      if (error) {
>          error_propagate(errp, error);
>          goto bdrv_new_err;
> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> index 2dcef07..8bac7ff 100644
> --- a/hw/block/xen_disk.c
> +++ b/hw/block/xen_disk.c
> @@ -856,7 +856,7 @@ static int blk_connect(struct XenDevice *xendev)
>  
>          /* setup via xenbus -> create new block driver instance */
>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
> -        blkdev->bs = bdrv_new(blkdev->dev, NULL);
> +        blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
>          if (!blkdev->bs) {
>              return -1;
>          }
> diff --git a/include/block/block.h b/include/block/block.h
> index 8f4ad16..95139c0 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -203,7 +203,8 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
>  int bdrv_create(BlockDriver *drv, const char* filename,
>                  QemuOpts *opts, Error **errp);
>  int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
> -BlockDriverState *bdrv_new(const char *device_name, Error **errp);
> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp);
> +BlockDriverState *bdrv_new(void);
>  void bdrv_make_anon(BlockDriverState *bs);
>  void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
>  void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
> diff --git a/qemu-img.c b/qemu-img.c
> index 91d1ac3..4490a22 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -296,7 +296,7 @@ static BlockDriverState *bdrv_new_open(const char *id,
>      Error *local_err = NULL;
>      int ret;
>  
> -    bs = bdrv_new(id, &error_abort);
> +    bs = bdrv_new_named(id, &error_abort);
>  
>      if (fmt) {
>          drv = bdrv_find_format(fmt);
> @@ -2425,7 +2425,7 @@ static int img_rebase(int argc, char **argv)
>      if (!unsafe) {
>          char backing_name[1024];
>  
> -        bs_old_backing = bdrv_new("old_backing", &error_abort);
> +        bs_old_backing = bdrv_new_named("old_backing", &error_abort);
>          bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
>          ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
>                          old_backing_drv, &local_err);
> @@ -2436,7 +2436,7 @@ static int img_rebase(int argc, char **argv)
>              goto out;
>          }
>          if (out_baseimg[0]) {
> -            bs_new_backing = bdrv_new("new_backing", &error_abort);
> +            bs_new_backing = bdrv_new_named("new_backing", &error_abort);
>              ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
>                              new_backing_drv, &local_err);
>              if (ret) {
> diff --git a/qemu-io.c b/qemu-io.c
> index d2ab694..44c2e1c 100644
> --- a/qemu-io.c
> +++ b/qemu-io.c
> @@ -58,7 +58,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
>          return 1;
>      }
>  
> -    qemuio_bs = bdrv_new("hda", &error_abort);
> +    qemuio_bs = bdrv_new_named("hda", &error_abort);
>  
>      if (growable) {
>          flags |= BDRV_O_PROTOCOL;
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index 9bc152e..a56ebfc 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -687,7 +687,7 @@ int main(int argc, char **argv)
>          drv = NULL;
>      }
>  
> -    bs = bdrv_new("hda", &error_abort);
> +    bs = bdrv_new_named("hda", &error_abort);
>  
>      srcpath = argv[optind];
>      ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
> -- 
> 1.9.3
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new()
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new() Markus Armbruster
                     ` (3 preceding siblings ...)
  2014-09-10 21:22   ` Benoît Canet
@ 2014-09-11  6:33   ` Fam Zheng
  4 siblings, 0 replies; 76+ messages in thread
From: Fam Zheng @ 2014-09-11  6:33 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, qemu-devel, stefanha

On Wed, 09/10 10:13, Markus Armbruster wrote:
> Creating an anonymous BDS can't fail.  Make that obvious.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block.c               | 26 +++++++++++++++++++-------
>  block/iscsi.c         |  2 +-
>  block/vvfat.c         |  2 +-
>  blockdev.c            |  2 +-
>  hw/block/xen_disk.c   |  2 +-
>  include/block/block.h |  3 ++-
>  qemu-img.c            |  6 +++---
>  qemu-io.c             |  2 +-
>  qemu-nbd.c            |  2 +-
>  9 files changed, 30 insertions(+), 17 deletions(-)

Reviewed-by: Fam Zheng <famz@redhat.com>

> 
> diff --git a/block.c b/block.c
> index d06dd51..4b3bcd4 100644
> --- a/block.c
> +++ b/block.c
> @@ -335,10 +335,11 @@ void bdrv_register(BlockDriver *bdrv)
>  }
>  
>  /* create a new block device (by default it is empty) */
> -BlockDriverState *bdrv_new(const char *device_name, Error **errp)
> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
>  {
>      BlockDriverState *bs;
> -    int i;
> +
> +    assert(*device_name);
>  
>      if (bdrv_find(device_name)) {
>          error_setg(errp, "Device with id '%s' already exists",
> @@ -351,12 +352,23 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
>          return NULL;
>      }
>  
> -    bs = g_new0(BlockDriverState, 1);
> -    QLIST_INIT(&bs->dirty_bitmaps);
> +    bs = bdrv_new();
> +
>      pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
>      if (device_name[0] != '\0') {
>          QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
>      }
> +
> +    return bs;
> +}
> +
> +BlockDriverState *bdrv_new(void)
> +{
> +    BlockDriverState *bs;
> +    int i;
> +
> +    bs = g_new0(BlockDriverState, 1);
> +    QLIST_INIT(&bs->dirty_bitmaps);
>      for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
>          QLIST_INIT(&bs->op_blockers[i]);
>      }
> @@ -1217,7 +1229,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *options, Error **errp)
>          goto free_exit;
>      }
>  
> -    backing_hd = bdrv_new("", errp);
> +    backing_hd = bdrv_new();
>  
>      if (bs->backing_format[0] != '\0') {
>          back_drv = bdrv_find_format(bs->backing_format);
> @@ -1346,7 +1358,7 @@ int bdrv_append_temp_snapshot(BlockDriverState *bs, int flags, Error **errp)
>      qdict_put(snapshot_options, "file.filename",
>                qstring_from_str(tmp_filename));
>  
> -    bs_snapshot = bdrv_new("", &error_abort);
> +    bs_snapshot = bdrv_new();
>  
>      ret = bdrv_open(&bs_snapshot, NULL, NULL, snapshot_options,
>                      flags, bdrv_qcow2, &local_err);
> @@ -1417,7 +1429,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
>      if (*pbs) {
>          bs = *pbs;
>      } else {
> -        bs = bdrv_new("", &error_abort);
> +        bs = bdrv_new();
>      }
>  
>      /* NULL means an empty set of options */
> diff --git a/block/iscsi.c b/block/iscsi.c
> index 3e19202..af3d0f6 100644
> --- a/block/iscsi.c
> +++ b/block/iscsi.c
> @@ -1528,7 +1528,7 @@ static int iscsi_create(const char *filename, QemuOpts *opts, Error **errp)
>      IscsiLun *iscsilun = NULL;
>      QDict *bs_options;
>  
> -    bs = bdrv_new("", &error_abort);
> +    bs = bdrv_new();
>  
>      /* Read out options */
>      total_size =
> diff --git a/block/vvfat.c b/block/vvfat.c
> index 731e591..6c9fde0 100644
> --- a/block/vvfat.c
> +++ b/block/vvfat.c
> @@ -2939,7 +2939,7 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)
>      unlink(s->qcow_filename);
>  #endif
>  
> -    bdrv_set_backing_hd(s->bs, bdrv_new("", &error_abort));
> +    bdrv_set_backing_hd(s->bs, bdrv_new());
>      s->bs->backing_hd->drv = &vvfat_write_target;
>      s->bs->backing_hd->opaque = g_new(void *, 1);
>      *(void**)s->bs->backing_hd->opaque = s;
> diff --git a/blockdev.c b/blockdev.c
> index e919566..9fbd888 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -458,7 +458,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>      /* init */
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
> -    dinfo->bdrv = bdrv_new(dinfo->id, &error);
> +    dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
>      if (error) {
>          error_propagate(errp, error);
>          goto bdrv_new_err;
> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> index 2dcef07..8bac7ff 100644
> --- a/hw/block/xen_disk.c
> +++ b/hw/block/xen_disk.c
> @@ -856,7 +856,7 @@ static int blk_connect(struct XenDevice *xendev)
>  
>          /* setup via xenbus -> create new block driver instance */
>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
> -        blkdev->bs = bdrv_new(blkdev->dev, NULL);
> +        blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
>          if (!blkdev->bs) {
>              return -1;
>          }
> diff --git a/include/block/block.h b/include/block/block.h
> index 8f4ad16..95139c0 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -203,7 +203,8 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
>  int bdrv_create(BlockDriver *drv, const char* filename,
>                  QemuOpts *opts, Error **errp);
>  int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
> -BlockDriverState *bdrv_new(const char *device_name, Error **errp);
> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp);
> +BlockDriverState *bdrv_new(void);
>  void bdrv_make_anon(BlockDriverState *bs);
>  void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
>  void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top);
> diff --git a/qemu-img.c b/qemu-img.c
> index 91d1ac3..4490a22 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -296,7 +296,7 @@ static BlockDriverState *bdrv_new_open(const char *id,
>      Error *local_err = NULL;
>      int ret;
>  
> -    bs = bdrv_new(id, &error_abort);
> +    bs = bdrv_new_named(id, &error_abort);
>  
>      if (fmt) {
>          drv = bdrv_find_format(fmt);
> @@ -2425,7 +2425,7 @@ static int img_rebase(int argc, char **argv)
>      if (!unsafe) {
>          char backing_name[1024];
>  
> -        bs_old_backing = bdrv_new("old_backing", &error_abort);
> +        bs_old_backing = bdrv_new_named("old_backing", &error_abort);
>          bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
>          ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
>                          old_backing_drv, &local_err);
> @@ -2436,7 +2436,7 @@ static int img_rebase(int argc, char **argv)
>              goto out;
>          }
>          if (out_baseimg[0]) {
> -            bs_new_backing = bdrv_new("new_backing", &error_abort);
> +            bs_new_backing = bdrv_new_named("new_backing", &error_abort);
>              ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
>                              new_backing_drv, &local_err);
>              if (ret) {
> diff --git a/qemu-io.c b/qemu-io.c
> index d2ab694..44c2e1c 100644
> --- a/qemu-io.c
> +++ b/qemu-io.c
> @@ -58,7 +58,7 @@ static int openfile(char *name, int flags, int growable, QDict *opts)
>          return 1;
>      }
>  
> -    qemuio_bs = bdrv_new("hda", &error_abort);
> +    qemuio_bs = bdrv_new_named("hda", &error_abort);
>  
>      if (growable) {
>          flags |= BDRV_O_PROTOCOL;
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index 9bc152e..a56ebfc 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -687,7 +687,7 @@ int main(int argc, char **argv)
>          drv = NULL;
>      }
>  
> -    bs = bdrv_new("hda", &error_abort);
> +    bs = bdrv_new_named("hda", &error_abort);
>  
>      srcpath = argv[optind];
>      ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err);
> -- 
> 1.9.3
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new()
  2014-09-10 15:05     ` Eric Blake
@ 2014-09-11  8:20       ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11  8:20 UTC (permalink / raw)
  To: Eric Blake; +Cc: Benoît Canet, kwolf, famz, qemu-devel, stefanha

Eric Blake <eblake@redhat.com> writes:

> On 09/10/2014 05:03 AM, Benoît Canet wrote:
>> The Wednesday 10 Sep 2014 à 10:13:30 (+0200), Markus Armbruster wrote :
>>> Creating an anonymous BDS can't fail.  Make that obvious.
>>>
>>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>>> ---
>
>>>  /* create a new block device (by default it is empty) */
>>> -BlockDriverState *bdrv_new(const char *device_name, Error **errp)
>>> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
>>>  {
>>>      BlockDriverState *bs;
>>> -    int i;
>>> +
>>> +    assert(*device_name);
>> 
>> This assert that device_name is not a null pointer.
>
> No, it assumes that device_name is non-NULL and blindly dereferences it;
> it is asserting that the first byte of the dereferenced pointer is not NUL.
>
>> But here we are pretty sure that the BDS should be named given the
>> name of the function.
>> Should we bake an assert on device_name[0] != '\0' to avoid
>> bdrv_new_named being called
>> with "" as device_name ?
>
> That's already what the code does.  About the only thing it could do
> differently is:
>
> assert(device_name && *device_name);

Converts a crash into an assertion failure.  No difference to me, but if
you guys think it's a worthwhile improvement...

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new()
  2014-09-10 11:03   ` Benoît Canet
  2014-09-10 15:05     ` Eric Blake
@ 2014-09-11  8:29     ` Markus Armbruster
  1 sibling, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11  8:29 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> The Wednesday 10 Sep 2014 à 10:13:30 (+0200), Markus Armbruster wrote :
>> Creating an anonymous BDS can't fail.  Make that obvious.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  block.c               | 26 +++++++++++++++++++-------
>>  block/iscsi.c         |  2 +-
>>  block/vvfat.c         |  2 +-
>>  blockdev.c            |  2 +-
>>  hw/block/xen_disk.c   |  2 +-
>>  include/block/block.h |  3 ++-
>>  qemu-img.c            |  6 +++---
>>  qemu-io.c             |  2 +-
>>  qemu-nbd.c            |  2 +-
>>  9 files changed, 30 insertions(+), 17 deletions(-)
>> 
>> diff --git a/block.c b/block.c
>> index d06dd51..4b3bcd4 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -335,10 +335,11 @@ void bdrv_register(BlockDriver *bdrv)
>>  }
>>  
>>  /* create a new block device (by default it is empty) */
>> -BlockDriverState *bdrv_new(const char *device_name, Error **errp)
>> +BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
>>  {
>>      BlockDriverState *bs;
>> -    int i;
>> +
>> +    assert(*device_name);
>
> This assert that device_name is not a null pointer.
> But here we are pretty sure that the BDS should be named given the
> name of the function.
> Should we bake an assert on device_name[0] != '\0' to avoid
> bdrv_new_named being called
> with "" as device_name ?
>
>>  
>>      if (bdrv_find(device_name)) {
>>          error_setg(errp, "Device with id '%s' already exists",
>> @@ -351,12 +352,23 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
>>          return NULL;
>>      }
>>  
>> -    bs = g_new0(BlockDriverState, 1);
>> -    QLIST_INIT(&bs->dirty_bitmaps);
>> +    bs = bdrv_new();
>> +
>>      pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
>
>>      if (device_name[0] != '\0') {
> Then we could remove this test.
>
>>          QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
> Because here would be too late anyway: an unammed BDS would have been
> created if device_name == "".

Short answer: not worth it, the function goes away in PATCH 08, and its
replacement works like you suggest.

Slightly longer answer: PATCH 02 adds BlockBackend, which also checks
device names.  blk_new() does it the way you suggest.  PATCH 08 removes
the now redundant BlockDriverState device name, including this function.

[...]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10  9:56   ` Kevin Wolf
@ 2014-09-11 10:03     ` Markus Armbruster
  2014-09-11 11:45       ` Markus Armbruster
  2014-09-11 14:38       ` Markus Armbruster
  0 siblings, 2 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 10:03 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: benoit.canet, famz, qemu-devel, stefanha

Kevin Wolf <kwolf@redhat.com> writes:

> Am 10.09.2014 um 10:13 hat Markus Armbruster geschrieben:
>> A block device consists of a frontend device model and a backend.
>> 
>> A block backend has a tree of block drivers doing the actual work.
>> The tree is managed by the block layer.
>> 
>> We currently use a single abstraction BlockDriverState both for tree
>> nodes and the backend as a whole.  Drawbacks:
>> 
>> * Its API includes both stuff that makes sense only at the block
>>   backend level (root of the tree) and stuff that's only for use
>>   within the block layer.  This makes the API bigger and more complex
>>   than necessary.  Moreover, it's not obvious which interfaces are
>>   meant for device models, and which really aren't.
>> 
>> * Since device models keep a reference to their backend, the backend
>>   object can't just be destroyed.  But for media change, we need to
>>   replace the tree.  Our solution is to make the BlockDriverState
>>   generic, with actual driver state in a separate object, pointed to
>>   by member opaque.  That lets us replace the tree by deinitializing
>>   and reinitializing its root.  This special need of the root makes
>>   the data structure awkward everywhere in the tree.
>> 
>> The general plan is to separate the APIs into "block backend", for use
>> by device models, monitor and whatever other code dealing with block
>> backends, and "block driver", for use by the block layer and whatever
>> other code (if any) dealing with trees and tree nodes.
>> 
>> Code dealing with block backends, device models in particular, should
>> become completely oblivious of BlockDriverState.  This should let us
>> clean up both APIs, and the tree data structures.
>> 
>> This commit is a first step.  It creates a minimal "block backend"
>> API: type BlockBackend and functions to create, destroy and find them.
>> BlockBackend objects are created and destroyed, but not yet used for
>> anything; that'll come shortly.
>> 
>> BlockBackend is reference-counted.  Its reference count never exceeds
>> one so far, but that's going to change.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  block/Makefile.objs            |   2 +-
>>  block/block-backend.c          | 110 +++++++++++++++++++++++++++++++++++++++++
>>  blockdev.c                     |  10 +++-
>>  hw/block/xen_disk.c            |  11 +++++
>>  include/qemu/typedefs.h        |   1 +
>>  include/sysemu/block-backend.h |  26 ++++++++++
>>  qemu-img.c                     |  46 +++++++++++++++++
>>  qemu-io.c                      |   8 +++
>>  qemu-nbd.c                     |   3 +-
>>  9 files changed, 214 insertions(+), 3 deletions(-)
>>  create mode 100644 block/block-backend.c
>>  create mode 100644 include/sysemu/block-backend.h
>> 
>> diff --git a/block/Makefile.objs b/block/Makefile.objs
>> index f45f939..a70140b 100644
>> --- a/block/Makefile.objs
>> +++ b/block/Makefile.objs
>> @@ -5,7 +5,7 @@ block-obj-y += qed-check.o
>>  block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
>>  block-obj-$(CONFIG_QUORUM) += quorum.o
>>  block-obj-y += parallels.o blkdebug.o blkverify.o
>> -block-obj-y += snapshot.o qapi.o
>> +block-obj-y += block-backend.o snapshot.o qapi.o
>>  block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
>>  block-obj-$(CONFIG_POSIX) += raw-posix.o
>>  block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> new file mode 100644
>> index 0000000..833f7d9
>> --- /dev/null
>> +++ b/block/block-backend.c
>> @@ -0,0 +1,110 @@
>> +/*
>> + * QEMU Block backends
>> + *
>> + * Copyright (C) 2014 Red Hat, Inc.
>> + *
>> + * Authors:
>> + *  Markus Armbruster <armbru@redhat.com>,
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or
>> + * later.  See the COPYING file in the top-level directory.
>> + */
>
> I think we still have the long-term plan of exposing a block layer
> library that can be consumed by libvirt. As the usage in qemu-io/img/nbd
> shows, this will probably have to use BlockBackends, so this code is part
> of the block layer core.
>
> Considering this, using the LGPL would be more practical. Can you please
> make this change for v2? (Personally, I would have used the MIT license
> that the rest of the block layer uses, which also make copying code
> around cleaner license-wise, but I know you dislike it.)

I do.

Having to accept the Lesser GPL's leaching loophole annoys me, but the
libvirt licensing boat has long sailed.

>> +#include "sysemu/block-backend.h"
>> +#include "block/block_int.h"
>> +
>> +struct BlockBackend {
>> +    char *name;
>> +    int refcnt;
>> +    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
>> +};
>> +
>> +static QTAILQ_HEAD(, BlockBackend) blk_backends =
>> +    QTAILQ_HEAD_INITIALIZER(blk_backends);
>> +
>> +/**
>> + * blk_new:
>> + * @name: name, must not be %NULL or empty
>> + * @errp: return location for an error to be set on failure, or %NULL
>> + *
>> + * Create a new BlockBackend, with a reference count of one.  Fail if
>> + * @name already exists.
>> + *
>> + * Returns: the BlockBackend on success, %NULL on failure
>> + */
>> +BlockBackend *blk_new(const char *name, Error **errp)
>> +{
>> +    BlockBackend *blk = g_new0(BlockBackend, 1);
>> +
>> +    assert(name && name[0]);
>> +    if (blk_by_name(name)) {
>> +        error_setg(errp, "Device with id '%s' already exists", name);
>> +        return NULL;
>
> blk is leaked here.

Fixed.

>> +    }
>> +    blk->name = g_strdup(name);
>> +    blk->refcnt = 1;
>> +    QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
>> +    return blk;
>> +}
>> +
>> +static void blk_delete(BlockBackend *blk)
>> +{
>> +    assert(!blk->refcnt);
>> +    QTAILQ_REMOVE(&blk_backends, blk, link);
>> +    g_free(blk->name);
>> +    g_free(blk);
>> +}
>> +
>> +/**
>> + * blk_ref:
>> + *
>> + * Increment @blk's reference count.
>> + */
>> +void blk_ref(BlockBackend *blk)
>> +{
>> +    blk->refcnt++;
>> +}
>> +
>> +/**
>> + * blk_unref:
>> + *
>> + * Decrement @blk's reference count.  If this drops it to zero,
>> + * destroy @blk.
>> + */
>> +void blk_unref(BlockBackend *blk)
>> +{
>> +    if (blk) {
>> +        g_assert(blk->refcnt > 0);
>
> You're mixing assert() and g_assert() in this patch. Any reason for
> this?

Stupidity?

>       If not, I think plain assert() is clearly in the majority in the
> overall codebase.

Fixed.

>> +        if (!--blk->refcnt) {
>> +            blk_delete(blk);
>> +        }
>> +    }
>> +}
>> +
>> +const char *blk_name(BlockBackend *blk)
>> +{
>> +    return blk->name;
>> +}
>> +
>> +BlockBackend *blk_by_name(const char *name)
>> +{
>> +    BlockBackend *blk;
>> +
>> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
>> +        if (!strcmp(name, blk->name)) {
>> +            return blk;
>> +        }
>> +    }
>> +    return NULL;
>> +}
>
> No comment for these two non-static functions?

I considered the abysmal signal-to-noise ratio of their GTK-Doc-style
function comments, and balked.

Considering we're not using this style in the block layer much, what do
you think about me abandoning this GTK-doc business, and adding
*concise* function comments to all my new public functions instead?

>> +/**
>> + * blk_next:
>> + *
>> + * Returns: the first BlockBackend if @blk is null, else @blk's next
>> + * sibling, which is %NULL for the last BlockBackend
>> + */
>> +BlockBackend *blk_next(BlockBackend *blk)
>> +{
>> +    return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
>> +}
>> diff --git a/blockdev.c b/blockdev.c
>> index 9fbd888..86596bc 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>
> Okay, so here the hard part starts: As long as the BB is completely
> unused, it's very hard to review at which places one must be created and
> deleted.
>
> What was your approach to systematically find all of them?

Good question!  Fortunately, I have an answer ready :)

We want to create a BB exactly when we're creating a named BDS.  "Named"
in the sense of "in bdrv_states".

We want to destroy a BB exactly when we're destroying the BDS that
motivated its creation.

This is a baby step towards having named BDSes owned by a BB.  That'll
be done by PATCH 05.

The places creating a named BDS are all clearly visible in PATCH 01,
because I rename the function doing that to bdrv_new_named().

This patch adds a blk_new() right next to every bdrv_new_named(), except
for qemu-img.c.  qemu-img.c calls bdrv_new_named() in bdrv_new_open().
I can't easily call blk_new() there, because the callers need the new BB
to be able to destroy it, but I can't easily return the new BB in
addition to the new BDS.  So I call blk_new() right before every
bdrv_new_open() instead.

BB destruction isn't quite as obvious, because destruction of named and
nameless BDSes looks the same in the code.  Either you examine all
bdrv_unref() and figure out whether it's named, and if yes, where you
can get the BB you need to unref here.  Or you figure out for every
allocation of a named BDS where it can be destroyed, and add the BB
destruction there.  That's what I did.

>> @@ -30,6 +30,7 @@
>>   * THE SOFTWARE.
>>   */
>>  
>> +#include "sysemu/block-backend.h"
>>  #include "sysemu/blockdev.h"
>>  #include "hw/block/block.h"
>>  #include "block/blockjob.h"
>> @@ -221,6 +222,7 @@ void drive_del(DriveInfo *dinfo)
>>      }
>>  
>>      bdrv_unref(dinfo->bdrv);
>> +    blk_unref(blk_by_name(dinfo->id));
>>      g_free(dinfo->id);
>>      QTAILQ_REMOVE(&drives, dinfo, next);
>>      g_free(dinfo->serial);
>> @@ -301,6 +303,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      int ro = 0;
>>      int bdrv_flags = 0;
>>      int on_read_error, on_write_error;
>> +    BlockBackend *blk;
>>      DriveInfo *dinfo;
>>      ThrottleConfig cfg;
>>      int snapshot = 0;
>> @@ -456,6 +459,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      }
>>  
>>      /* init */
>> +    blk = blk_new(qemu_opts_id(opts), errp);
>> +    if (!blk) {
>> +        goto early_err;
>> +    }
>>      dinfo = g_malloc0(sizeof(*dinfo));
>>      dinfo->id = g_strdup(qemu_opts_id(opts));
>>      dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
>> @@ -525,6 +532,7 @@ err:
>>  bdrv_new_err:
>>      g_free(dinfo->id);
>>      g_free(dinfo);
>> +    blk_unref(blk);
>>  early_err:
>>      qemu_opts_del(opts);
>>  err_no_opts:
>> @@ -1770,7 +1778,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>>       */
>>      if (bdrv_get_attached_dev(bs)) {
>>          bdrv_make_anon(bs);
>> -
>> +        blk_unref(blk_by_name(id));
>>          /* Further I/O must not pause the guest */
>>          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
>>                            BLOCKDEV_ON_ERROR_REPORT);
>
> Won't we unref the BB a second time now when unplugging the device?
> (drive_del() called in blockdev_auto_del())

Short answer: you're right, there's a bug, and I'll fix it.

Long answer: this part is hairy, because the drive_del command is badly
designed.

For historical reasons, unplugging a device model destroys the block
backends it's attached to, and this is the only way to destroy block
backends.

Aside: we're not carrying that misfeature forward to blockdev-add.

For some device models, the guest can prevent unplug.  Some users need a
way to forcibly revoke device model access to the block backend then, so
the underlying images can be safely used for something else.

drive_del lets you do that.  Unfortunately, it conflates revoking access
with destroying the backend.

Commit 9063f81 makes drive_del immediately destroy the root BDS.  Nice:
the device name becomes available for reuse immediately.  Not so nice:
the device model's pointer to the root BDS dangles, and we're prone to
crash when the memory gets reused.

Commit d22b2f4 fixed that by hiding the root BDS instead of destroying
it.  Destruction only happens on unplug.  "Hiding" means removing it
from bdrv_states and graph_bdrv_states; see bdrv_make_anon().

We should've limited the command to revoking access, avoiding this silly
hiding business.

The obvious thing to do here is match the mess: hide the BB along with
the BDS here, delete it in blockdev_auto_del().

Trouble is that hiding it makes it hard to find in blockdev_auto_del().

I tried to avoid the need to find it there by destroying it here.  On
unplug, drive_del()'s blk_unref(blk_by_name(dinfo->id)) won't do
anything, because blk_by_name() returns NULL.  *Except* when the user
has since added *another* BB with the same name!  Oops...

Simplest possible solution: I hide the BB here, and *leak* it (with a
fat FIXME comment) until it becomes easy enough to find.  I guess I can
find it right in the next patch.

>> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
>> index 8bac7ff..730a021 100644
>> --- a/hw/block/xen_disk.c
>> +++ b/hw/block/xen_disk.c
>> @@ -39,6 +39,7 @@
>>  #include "hw/xen/xen_backend.h"
>>  #include "xen_blkif.h"
>>  #include "sysemu/blockdev.h"
>> +#include "sysemu/block-backend.h"
>>  
>>  /* ------------------------------------------------------------- */
>>  
>> @@ -852,12 +853,18 @@ static int blk_connect(struct XenDevice *xendev)
>>      blkdev->dinfo = drive_get(IF_XEN, 0, index);
>>      if (!blkdev->dinfo) {
>>          Error *local_err = NULL;
>> +        BlockBackend *blk;
>>          BlockDriver *drv;
>>  
>>          /* setup via xenbus -> create new block driver instance */
>>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
>> +        blk = blk_new(blkdev->dev, NULL);
>> +        if (!blk) {
>> +            return -1;
>> +        }
>>          blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
>>          if (!blkdev->bs) {
>> +            blk_unref(blk);
>>              return -1;
>>          }
>>  
>> @@ -868,6 +875,7 @@ static int blk_connect(struct XenDevice *xendev)
>>                            error_get_pretty(local_err));
>>              error_free(local_err);
>>              bdrv_unref(blkdev->bs);
>> +            blk_unref(blk);
>>              blkdev->bs = NULL;
>>              return -1;
>>          }
>> @@ -983,6 +991,9 @@ static void blk_disconnect(struct XenDevice *xendev)
>>      if (blkdev->bs) {
>>          bdrv_detach_dev(blkdev->bs, blkdev);
>>          bdrv_unref(blkdev->bs);
>> +        if (!blkdev->dinfo) {
>> +            blk_unref(blk_by_name(blkdev->dev));
>> +        }
>>          blkdev->bs = NULL;
>>      }
>>      xen_be_unbind_evtchn(&blkdev->xendev);
>> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
>> index 5f20b0e..198da2e 100644
>> --- a/include/qemu/typedefs.h
>> +++ b/include/qemu/typedefs.h
>> @@ -35,6 +35,7 @@ typedef struct MachineClass MachineClass;
>>  typedef struct NICInfo NICInfo;
>>  typedef struct HCIInfo HCIInfo;
>>  typedef struct AudioState AudioState;
>> +typedef struct BlockBackend BlockBackend;
>>  typedef struct BlockDriverState BlockDriverState;
>>  typedef struct DriveInfo DriveInfo;
>>  typedef struct DisplayState DisplayState;
>> diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
>> new file mode 100644
>> index 0000000..3f8371c
>> --- /dev/null
>> +++ b/include/sysemu/block-backend.h
>> @@ -0,0 +1,26 @@
>> +/*
>> + * QEMU Block backends
>> + *
>> + * Copyright (C) 2014 Red Hat, Inc.
>> + *
>> + * Authors:
>> + *  Markus Armbruster <armbru@redhat.com>,
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or
>> + * later.  See the COPYING file in the top-level directory.
>> + */
>> +
>> +#ifndef BLOCK_BACKEND_H
>> +#define BLOCK_BACKEND_H
>> +
>> +#include "qemu/typedefs.h"
>> +#include "qapi/error.h"
>> +
>> +BlockBackend *blk_new(const char *name, Error **errp);
>> +void blk_ref(BlockBackend *blk);
>> +void blk_unref(BlockBackend *blk);
>> +const char *blk_name(BlockBackend *blk);
>> +BlockBackend *blk_by_name(const char *name);
>> +BlockBackend *blk_next(BlockBackend *blk);
>> +
>> +#endif
>> diff --git a/qemu-img.c b/qemu-img.c
>> index 4490a22..bad3f64 100644
>> --- a/qemu-img.c
>> +++ b/qemu-img.c
>
> Won't comment on each hunk in qemu-img, but in many cases, on
> bdrv_new_open() failure, blk is leaked.

I'll check them systematically.

>> diff --git a/qemu-nbd.c b/qemu-nbd.c
>> index a56ebfc..94b9b49 100644
>> --- a/qemu-nbd.c
>> +++ b/qemu-nbd.c
>> @@ -17,7 +17,7 @@
>>   */
>>  
>>  #include "qemu-common.h"
>> -#include "block/block.h"
>> +#include "sysemu/block-backend.h"
>>  #include "block/block_int.h"
>>  #include "block/nbd.h"
>>  #include "qemu/main-loop.h"
>> @@ -687,6 +687,7 @@ int main(int argc, char **argv)
>>          drv = NULL;
>>      }
>>  
>> +    blk_new("hda", &error_abort);
>>      bs = bdrv_new_named("hda", &error_abort);
>>  
>>      srcpath = argv[optind];
>
> Where is the matching blk_unref?

Right next to the bdrv_unref(): nowhere :)

If you like, I can throw in a preliminary patch adding the bdrv_unref().
Then add the matching blk_unref() in patch.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10 11:34   ` Benoît Canet
  2014-09-10 11:44     ` Kevin Wolf
@ 2014-09-11 10:11     ` Markus Armbruster
  1 sibling, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 10:11 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> The Wednesday 10 Sep 2014  10:13:31 (+0200), Markus Armbruster wrote :
>> A block device consists of a frontend device model and a backend.
>> 
>> A block backend has a tree of block drivers doing the actual work.
>> The tree is managed by the block layer.
>> 
>> We currently use a single abstraction BlockDriverState both for tree
>> nodes and the backend as a whole.  Drawbacks:
>> 
>> * Its API includes both stuff that makes sense only at the block
>>   backend level (root of the tree) and stuff that's only for use
>>   within the block layer.  This makes the API bigger and more complex
>>   than necessary.  Moreover, it's not obvious which interfaces are
>>   meant for device models, and which really aren't.
>> 
>> * Since device models keep a reference to their backend, the backend
>>   object can't just be destroyed.  But for media change, we need to
>>   replace the tree.  Our solution is to make the BlockDriverState
>>   generic, with actual driver state in a separate object, pointed to
>>   by member opaque.  That lets us replace the tree by deinitializing
>>   and reinitializing its root.  This special need of the root makes
>>   the data structure awkward everywhere in the tree.
>> 
>> The general plan is to separate the APIs into "block backend", for use
>> by device models, monitor and whatever other code dealing with block
>> backends, and "block driver", for use by the block layer and whatever
>> other code (if any) dealing with trees and tree nodes.
>> 
>> Code dealing with block backends, device models in particular, should
>> become completely oblivious of BlockDriverState.  This should let us
>> clean up both APIs, and the tree data structures.
>> 
>> This commit is a first step.  It creates a minimal "block backend"
>> API: type BlockBackend and functions to create, destroy and find them.
>> BlockBackend objects are created and destroyed, but not yet used for
>> anything; that'll come shortly.
>> 
>> BlockBackend is reference-counted.  Its reference count never exceeds
>> one so far, but that's going to change.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  block/Makefile.objs            |   2 +-
>>  block/block-backend.c          | 110 +++++++++++++++++++++++++++++++++++++++++
>>  blockdev.c                     |  10 +++-
>>  hw/block/xen_disk.c            |  11 +++++
>>  include/qemu/typedefs.h        |   1 +
>>  include/sysemu/block-backend.h |  26 ++++++++++
>>  qemu-img.c                     |  46 +++++++++++++++++
>>  qemu-io.c                      |   8 +++
>>  qemu-nbd.c                     |   3 +-
>>  9 files changed, 214 insertions(+), 3 deletions(-)
>>  create mode 100644 block/block-backend.c
>>  create mode 100644 include/sysemu/block-backend.h
>> 
>> diff --git a/block/Makefile.objs b/block/Makefile.objs
>> index f45f939..a70140b 100644
>> --- a/block/Makefile.objs
>> +++ b/block/Makefile.objs
>> @@ -5,7 +5,7 @@ block-obj-y += qed-check.o
>>  block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
>>  block-obj-$(CONFIG_QUORUM) += quorum.o
>>  block-obj-y += parallels.o blkdebug.o blkverify.o
>> -block-obj-y += snapshot.o qapi.o
>> +block-obj-y += block-backend.o snapshot.o qapi.o
>>  block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
>>  block-obj-$(CONFIG_POSIX) += raw-posix.o
>>  block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> new file mode 100644
>> index 0000000..833f7d9
>> --- /dev/null
>> +++ b/block/block-backend.c
>> @@ -0,0 +1,110 @@
>> +/*
>> + * QEMU Block backends
>> + *
>> + * Copyright (C) 2014 Red Hat, Inc.
>> + *
>> + * Authors:
>> + *  Markus Armbruster <armbru@redhat.com>,
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or
>> + * later.  See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "sysemu/block-backend.h"
>> +#include "block/block_int.h"
>> +
>> +struct BlockBackend {
>> +    char *name;
>> +    int refcnt;
>> +    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
>> +};
>> +
>> +static QTAILQ_HEAD(, BlockBackend) blk_backends =
>> +    QTAILQ_HEAD_INITIALIZER(blk_backends);
>> +
>> +/**
>> + * blk_new:
>> + * @name: name, must not be %NULL or empty
>> + * @errp: return location for an error to be set on failure, or %NULL
>> + *
>> + * Create a new BlockBackend, with a reference count of one.  Fail if
>> + * @name already exists.
>> + *
>> + * Returns: the BlockBackend on success, %NULL on failure
>> + */
>> +BlockBackend *blk_new(const char *name, Error **errp)
>
> I am responding for the easy part first.
>
> So here the blockbackend is identified by a name
>
>> +{
>> +    BlockBackend *blk = g_new0(BlockBackend, 1);
>> +
>> +    assert(name && name[0]);
>> +    if (blk_by_name(name)) {
>
>> +        error_setg(errp, "Device with id '%s' already exists", name);
>
> But here is it an id or a name ?
> Do we need to make a choice everywhere in the code between id and name ?

If we can agree on a convention to use within the block layer, I'll be
happy to follow it.

Right now, we mix "id", "device", "device name" freely.  My patch
mimicks existing usage: "id" in QemuOpts and some error messages,
"device name" and its abbreviated variations in the code, the schema,
and some other error messages.

>> +        return NULL;
>> +    }
>> +    blk->name = g_strdup(name);
>> +    blk->refcnt = 1;
>> +    QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
>> +    return blk;
>> +}
>> +
>> +static void blk_delete(BlockBackend *blk)
>> +{
>> +    assert(!blk->refcnt);
>> +    QTAILQ_REMOVE(&blk_backends, blk, link);
>> +    g_free(blk->name);
>> +    g_free(blk);
>> +}
>> +
>> +/**
>> + * blk_ref:
>> + *
>> + * Increment @blk's reference count.
>> + */
>> +void blk_ref(BlockBackend *blk)
>> +{
>
> if blk_unref you take care of doing
> +    if (blk) {
> to make sur the user does not pass a NULL pointer.
> Transforming blk into a NULL pointer is not a side effect
> of blk_unref so this test is designed to prevent a user
> brain damage.
>
> If the user can be brain damaged to pass a NULL to blk_unref he
> could be equally stupid passing a NULL to blk_ref.
> Why not adding the same test here ?

Kevin already explained this one.

[...]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10 12:40   ` Benoît Canet
  2014-09-10 12:46     ` Benoît Canet
@ 2014-09-11 10:21     ` Markus Armbruster
  1 sibling, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 10:21 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> The Wednesday 10 Sep 2014 à 10:13:31 (+0200), Markus Armbruster wrote :
>> A block device consists of a frontend device model and a backend.
>> 
>> A block backend has a tree of block drivers doing the actual work.
>> The tree is managed by the block layer.
>> 
>> We currently use a single abstraction BlockDriverState both for tree
>> nodes and the backend as a whole.  Drawbacks:
>> 
>> * Its API includes both stuff that makes sense only at the block
>>   backend level (root of the tree) and stuff that's only for use
>>   within the block layer.  This makes the API bigger and more complex
>>   than necessary.  Moreover, it's not obvious which interfaces are
>>   meant for device models, and which really aren't.
>> 
>> * Since device models keep a reference to their backend, the backend
>>   object can't just be destroyed.  But for media change, we need to
>>   replace the tree.  Our solution is to make the BlockDriverState
>>   generic, with actual driver state in a separate object, pointed to
>>   by member opaque.  That lets us replace the tree by deinitializing
>>   and reinitializing its root.  This special need of the root makes
>>   the data structure awkward everywhere in the tree.
>> 
>> The general plan is to separate the APIs into "block backend", for use
>> by device models, monitor and whatever other code dealing with block
>> backends, and "block driver", for use by the block layer and whatever
>> other code (if any) dealing with trees and tree nodes.
>> 
>> Code dealing with block backends, device models in particular, should
>> become completely oblivious of BlockDriverState.  This should let us
>> clean up both APIs, and the tree data structures.
>> 
>> This commit is a first step.  It creates a minimal "block backend"
>> API: type BlockBackend and functions to create, destroy and find them.
>> BlockBackend objects are created and destroyed, but not yet used for
>> anything; that'll come shortly.
>> 
>> BlockBackend is reference-counted.  Its reference count never exceeds
>> one so far, but that's going to change.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  block/Makefile.objs            |   2 +-
>>  block/block-backend.c          | 110 +++++++++++++++++++++++++++++++++++++++++
>>  blockdev.c                     |  10 +++-
>>  hw/block/xen_disk.c            |  11 +++++
>>  include/qemu/typedefs.h        |   1 +
>>  include/sysemu/block-backend.h |  26 ++++++++++
>>  qemu-img.c                     |  46 +++++++++++++++++
>>  qemu-io.c                      |   8 +++
>>  qemu-nbd.c                     |   3 +-
>>  9 files changed, 214 insertions(+), 3 deletions(-)
>>  create mode 100644 block/block-backend.c
>>  create mode 100644 include/sysemu/block-backend.h
>> 
>> diff --git a/block/Makefile.objs b/block/Makefile.objs
>> index f45f939..a70140b 100644
>> --- a/block/Makefile.objs
>> +++ b/block/Makefile.objs
>> @@ -5,7 +5,7 @@ block-obj-y += qed-check.o
>>  block-obj-$(CONFIG_VHDX) += vhdx.o vhdx-endian.o vhdx-log.o
>>  block-obj-$(CONFIG_QUORUM) += quorum.o
>>  block-obj-y += parallels.o blkdebug.o blkverify.o
>> -block-obj-y += snapshot.o qapi.o
>> +block-obj-y += block-backend.o snapshot.o qapi.o
>>  block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
>>  block-obj-$(CONFIG_POSIX) += raw-posix.o
>>  block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> new file mode 100644
>> index 0000000..833f7d9
>> --- /dev/null
>> +++ b/block/block-backend.c
>> @@ -0,0 +1,110 @@
>> +/*
>> + * QEMU Block backends
>> + *
>> + * Copyright (C) 2014 Red Hat, Inc.
>> + *
>> + * Authors:
>> + *  Markus Armbruster <armbru@redhat.com>,
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or
>> + * later.  See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "sysemu/block-backend.h"
>> +#include "block/block_int.h"
>> +
>> +struct BlockBackend {
>> +    char *name;
>> +    int refcnt;
>> +    QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
>> +};
>> +
>> +static QTAILQ_HEAD(, BlockBackend) blk_backends =
>> +    QTAILQ_HEAD_INITIALIZER(blk_backends);
>> +
>> +/**
>> + * blk_new:
>> + * @name: name, must not be %NULL or empty
>> + * @errp: return location for an error to be set on failure, or %NULL
>> + *
>> + * Create a new BlockBackend, with a reference count of one.  Fail if
>> + * @name already exists.
>> + *
>> + * Returns: the BlockBackend on success, %NULL on failure
>> + */
>> +BlockBackend *blk_new(const char *name, Error **errp)
>> +{
>> +    BlockBackend *blk = g_new0(BlockBackend, 1);
>> +
>> +    assert(name && name[0]);
>> +    if (blk_by_name(name)) {
>> +        error_setg(errp, "Device with id '%s' already exists", name);
>> +        return NULL;
>> +    }
>> +    blk->name = g_strdup(name);
>> +    blk->refcnt = 1;
>> +    QTAILQ_INSERT_TAIL(&blk_backends, blk, link);
>> +    return blk;
>> +}
>> +
>> +static void blk_delete(BlockBackend *blk)
>> +{
>> +    assert(!blk->refcnt);
>> +    QTAILQ_REMOVE(&blk_backends, blk, link);
>> +    g_free(blk->name);
>> +    g_free(blk);
>> +}
>> +
>> +/**
>> + * blk_ref:
>> + *
>> + * Increment @blk's reference count.
>> + */
>> +void blk_ref(BlockBackend *blk)
>> +{
>> +    blk->refcnt++;
>> +}
>> +
>> +/**
>> + * blk_unref:
>> + *
>> + * Decrement @blk's reference count.  If this drops it to zero,
>> + * destroy @blk.
>> + */
>> +void blk_unref(BlockBackend *blk)
>> +{
>> +    if (blk) {
>> +        g_assert(blk->refcnt > 0);
>> +        if (!--blk->refcnt) {
>> +            blk_delete(blk);
>> +        }
>> +    }
>> +}
>> +
>> +const char *blk_name(BlockBackend *blk)
>> +{
>> +    return blk->name;
>> +}
>> +
>> +BlockBackend *blk_by_name(const char *name)
>> +{
>> +    BlockBackend *blk;
>> +
>> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
>> +        if (!strcmp(name, blk->name)) {
>> +            return blk;
>> +        }
>> +    }
>> +    return NULL;
>> +}
>> +
>> +/**
>> + * blk_next:
>> + *
>> + * Returns: the first BlockBackend if @blk is null, else @blk's next
>> + * sibling, which is %NULL for the last BlockBackend
>> + */
>> +BlockBackend *blk_next(BlockBackend *blk)
>> +{
>> +    return blk ? QTAILQ_NEXT(blk, link) : QTAILQ_FIRST(&blk_backends);
>> +}
>> diff --git a/blockdev.c b/blockdev.c
>> index 9fbd888..86596bc 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -30,6 +30,7 @@
>>   * THE SOFTWARE.
>>   */
>>  
>> +#include "sysemu/block-backend.h"
>>  #include "sysemu/blockdev.h"
>>  #include "hw/block/block.h"
>>  #include "block/blockjob.h"
>> @@ -221,6 +222,7 @@ void drive_del(DriveInfo *dinfo)
>>      }
>>  
>>      bdrv_unref(dinfo->bdrv);
>> +    blk_unref(blk_by_name(dinfo->id));
>>      g_free(dinfo->id);
>>      QTAILQ_REMOVE(&drives, dinfo, next);
>>      g_free(dinfo->serial);
>> @@ -301,6 +303,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      int ro = 0;
>>      int bdrv_flags = 0;
>>      int on_read_error, on_write_error;
>> +    BlockBackend *blk;
>>      DriveInfo *dinfo;
>>      ThrottleConfig cfg;
>>      int snapshot = 0;
>> @@ -456,6 +459,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      }
>>  
>>      /* init */
>> +    blk = blk_new(qemu_opts_id(opts), errp);
>> +    if (!blk) {
>> +        goto early_err;
>> +    }
>
> Here you create a new block backend.
> And you don't attach it to anything in any way yet.

Yes.  Right before creating the root BDS.

> So down in the code the following test will leak it:
>     if (!file || !*file) {                                                      
>         if (has_driver_specific_opts) {                                         
>             file = NULL;                                                        
>         } else {                                                                
>             QDECREF(bs_opts);                                                   
>             qemu_opts_del(opts);                                                
>             return dinfo;                                                       
>         }                                                                       
>     } 

The root BDS isn't destroyed here, and therefore the BB isn't, either.

The BB will be destroyed right when the root BDS is.

> I am sure one of your next patchs fixes this but for this
> precise commit this do look like a leak.
>
>>      dinfo = g_malloc0(sizeof(*dinfo));
>>      dinfo->id = g_strdup(qemu_opts_id(opts));
>>      dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
>> @@ -525,6 +532,7 @@ err:
>>  bdrv_new_err:
>>      g_free(dinfo->id);
>>      g_free(dinfo);
>> +    blk_unref(blk);
>>  early_err:
>>      qemu_opts_del(opts);
>>  err_no_opts:
>> @@ -1770,7 +1778,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>>       */
>>      if (bdrv_get_attached_dev(bs)) {
>>          bdrv_make_anon(bs);
>> -
>> +        blk_unref(blk_by_name(id));
>>          /* Further I/O must not pause the guest */
>>          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
>>                            BLOCKDEV_ON_ERROR_REPORT);
>> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
>> index 8bac7ff..730a021 100644
>> --- a/hw/block/xen_disk.c
>> +++ b/hw/block/xen_disk.c
>> @@ -39,6 +39,7 @@
>>  #include "hw/xen/xen_backend.h"
>>  #include "xen_blkif.h"
>>  #include "sysemu/blockdev.h"
>> +#include "sysemu/block-backend.h"
>>  
>>  /* ------------------------------------------------------------- */
>>  
>> @@ -852,12 +853,18 @@ static int blk_connect(struct XenDevice *xendev)
>>      blkdev->dinfo = drive_get(IF_XEN, 0, index);
>>      if (!blkdev->dinfo) {
>>          Error *local_err = NULL;
>> +        BlockBackend *blk;
>>          BlockDriver *drv;
>>  
>>          /* setup via xenbus -> create new block driver instance */
>>          xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
>> +        blk = blk_new(blkdev->dev, NULL);
>> +        if (!blk) {
>> +            return -1;
>> +        }
>>          blkdev->bs = bdrv_new_named(blkdev->dev, NULL);
>>          if (!blkdev->bs) {
>> +            blk_unref(blk);
>>              return -1;
>>          }
>>  
>> @@ -868,6 +875,7 @@ static int blk_connect(struct XenDevice *xendev)
>>                            error_get_pretty(local_err));
>>              error_free(local_err);
>>              bdrv_unref(blkdev->bs);
>> +            blk_unref(blk);
>>              blkdev->bs = NULL;
>>              return -1;
>>          }
>> @@ -983,6 +991,9 @@ static void blk_disconnect(struct XenDevice *xendev)
>>      if (blkdev->bs) {
>>          bdrv_detach_dev(blkdev->bs, blkdev);
>>          bdrv_unref(blkdev->bs);
>> +        if (!blkdev->dinfo) {
>> +            blk_unref(blk_by_name(blkdev->dev));
>> +        }
>>          blkdev->bs = NULL;
>>      }
>>      xen_be_unbind_evtchn(&blkdev->xendev);
>> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
>> index 5f20b0e..198da2e 100644
>> --- a/include/qemu/typedefs.h
>> +++ b/include/qemu/typedefs.h
>> @@ -35,6 +35,7 @@ typedef struct MachineClass MachineClass;
>>  typedef struct NICInfo NICInfo;
>>  typedef struct HCIInfo HCIInfo;
>>  typedef struct AudioState AudioState;
>> +typedef struct BlockBackend BlockBackend;
>>  typedef struct BlockDriverState BlockDriverState;
>>  typedef struct DriveInfo DriveInfo;
>>  typedef struct DisplayState DisplayState;
>> diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
>> new file mode 100644
>> index 0000000..3f8371c
>> --- /dev/null
>> +++ b/include/sysemu/block-backend.h
>> @@ -0,0 +1,26 @@
>> +/*
>> + * QEMU Block backends
>> + *
>> + * Copyright (C) 2014 Red Hat, Inc.
>> + *
>> + * Authors:
>> + *  Markus Armbruster <armbru@redhat.com>,
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or
>> + * later.  See the COPYING file in the top-level directory.
>> + */
>> +
>> +#ifndef BLOCK_BACKEND_H
>> +#define BLOCK_BACKEND_H
>> +
>> +#include "qemu/typedefs.h"
>> +#include "qapi/error.h"
>> +
>> +BlockBackend *blk_new(const char *name, Error **errp);
>> +void blk_ref(BlockBackend *blk);
>> +void blk_unref(BlockBackend *blk);
>> +const char *blk_name(BlockBackend *blk);
>> +BlockBackend *blk_by_name(const char *name);
>> +BlockBackend *blk_next(BlockBackend *blk);
>> +
>> +#endif
>> diff --git a/qemu-img.c b/qemu-img.c
>> index 4490a22..bad3f64 100644
>> --- a/qemu-img.c
>> +++ b/qemu-img.c
>> @@ -29,6 +29,7 @@
>>  #include "qemu/error-report.h"
>>  #include "qemu/osdep.h"
>>  #include "sysemu/sysemu.h"
>> +#include "sysemu/block-backend.h"
>>  #include "block/block_int.h"
>>  #include "block/qapi.h"
>>  #include <getopt.h>
>> @@ -575,6 +576,7 @@ static int img_check(int argc, char **argv)
>>      int c, ret;
>>      OutputFormat output_format = OFORMAT_HUMAN;
>>      const char *filename, *fmt, *output, *cache;
>> +    BlockBackend *blk;
>>      BlockDriverState *bs;
>>      int fix = 0;
>>      int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
>> @@ -649,6 +651,7 @@ static int img_check(int argc, char **argv)
>>          return 1;
>>      }
>>  
>
>> +    blk = blk_new("image", &error_abort);
> Hmm we are so sure this will work that we don't do if (!block) ?

Matches what bdrv_new_open() does:

    bs = bdrv_new_named(id, &error_abort);

As you noted further down, the tools treat these failures as programming
errors.  That's appropriate.

>>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>>      if (!bs) {
>>          return 1;
>> @@ -710,6 +713,7 @@ static int img_check(int argc, char **argv)
>>  fail:
>>      qapi_free_ImageCheck(check);
>>      bdrv_unref(bs);
>> +    blk_unref(blk);
>>  
>>      return ret;
>>  }
>> @@ -718,6 +722,7 @@ static int img_commit(int argc, char **argv)
>>  {
>>      int c, ret, flags;
>>      const char *filename, *fmt, *cache;
>> +    BlockBackend *blk;
>>      BlockDriverState *bs;
>>      bool quiet = false;
>>  
>> @@ -756,6 +761,7 @@ static int img_commit(int argc, char **argv)
>>          return 1;
>>      }
>>  
>> +    blk = blk_new("image", &error_abort);
>>      bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
>>      if (!bs) {
>>          return 1;
>> @@ -780,6 +786,7 @@ static int img_commit(int argc, char **argv)
>>      }
>>  
>>      bdrv_unref(bs);
>> +    blk_unref(blk);
>>      if (ret) {
>>          return 1;
>>      }
>> @@ -942,6 +949,7 @@ static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
>>  static int img_compare(int argc, char **argv)
>>  {
>>      const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
>> +    BlockBackend *blk1, *blk2;
>>      BlockDriverState *bs1, *bs2;
>>      int64_t total_sectors1, total_sectors2;
>>      uint8_t *buf1 = NULL, *buf2 = NULL;
>> @@ -1011,6 +1019,7 @@ static int img_compare(int argc, char **argv)
>>          goto out3;
>>      }
>>  
>> +    blk1 = blk_new("image 1", &error_abort);
>>      bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
>>      if (!bs1) {
>>          error_report("Can't open file %s", filename1);
>> @@ -1018,6 +1027,7 @@ static int img_compare(int argc, char **argv)
>>          goto out3;
>>      }
>>  
>> +    blk2 = blk_new("image 2", &error_abort);
>>      bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
>>      if (!bs2) {
>>          error_report("Can't open file %s", filename2);
>> @@ -1184,10 +1194,12 @@ static int img_compare(int argc, char **argv)
>>  
>>  out:
>>      bdrv_unref(bs2);
>> +    blk_unref(blk2);
>>      qemu_vfree(buf1);
>>      qemu_vfree(buf2);
>>  out2:
>>      bdrv_unref(bs1);
>> +    blk_unref(blk1);
>>  out3:
>>      qemu_progress_end();
>>      return ret;
>> @@ -1200,6 +1212,7 @@ static int img_convert(int argc, char **argv)
>>      int progress = 0, flags, src_flags;
>>      const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
>>      BlockDriver *drv, *proto_drv;
>> +    BlockBackend **blk = NULL, *out_blk = NULL;
>>      BlockDriverState **bs = NULL, *out_bs = NULL;
>>      int64_t total_sectors, nb_sectors, sector_num, bs_offset;
>>      int64_t *bs_sectors = NULL;
>> @@ -1354,6 +1367,7 @@ static int img_convert(int argc, char **argv)
>>  
>>      qemu_progress_print(0, 100);
>>  
>> +    blk = g_new0(BlockBackend *, bs_n);
>>      bs = g_new0(BlockDriverState *, bs_n);
>>      bs_sectors = g_new(int64_t, bs_n);
>>  
>> @@ -1361,6 +1375,7 @@ static int img_convert(int argc, char **argv)
>>      for (bs_i = 0; bs_i < bs_n; bs_i++) {
>>          char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
>>                              : g_strdup("source");
>> +        blk[bs_i] = blk_new(id, &error_abort);
>>          bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
>>                                   true, quiet);
>>          g_free(id);
>> @@ -1486,6 +1501,7 @@ static int img_convert(int argc, char **argv)
>>          goto out;
>>      }
>>  
>> +    out_blk = blk_new("target", &error_abort);
>>      out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
>>      if (!out_bs) {
>>          ret = -1;
>> @@ -1742,6 +1758,7 @@ out:
>>      if (out_bs) {
>>          bdrv_unref(out_bs);
>>      }
>> +    blk_unref(out_blk);
>>      if (bs) {
>>          for (bs_i = 0; bs_i < bs_n; bs_i++) {
>>              if (bs[bs_i]) {
>> @@ -1750,6 +1767,12 @@ out:
>>          }
>>          g_free(bs);
>>      }
>> +    if (blk) {
>> +        for (bs_i = 0; bs_i < bs_n; bs_i++) {
>> +            blk_unref(blk[bs_i]);
>> +        }
>> +        g_free(blk);
>> +    }
>>      g_free(bs_sectors);
>>  fail_getopt:
>>      g_free(options);
>> @@ -1858,6 +1881,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>>      filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
>>  
>>      while (filename) {
>> +        BlockBackend *blk;
>>          BlockDriverState *bs;
>>          ImageInfo *info;
>>          ImageInfoList *elem;
>> @@ -1869,6 +1893,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
>>          }
>>          g_hash_table_insert(filenames, (gpointer)filename, NULL);
>>  
>> +        blk = blk_new("image", &error_abort);
>>          bs = bdrv_new_open("image", filename, fmt,
>>                             BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
>>          if (!bs) {
>
> I think it misses an 
>> +            blk_unref(blk);
> in if(!bs) branch.

Yes.  Kevin noted that, too.  I'll fix it.

[...]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-10 12:46     ` Benoît Canet
@ 2014-09-11 10:22       ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 10:22 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> The Wednesday 10 Sep 2014 à 14:40:42 (+0200), Benoît Canet wrote :
>> The Wednesday 10 Sep 2014 à 10:13:31 (+0200), Markus Armbruster wrote :
[...]
>> > diff --git a/qemu-img.c b/qemu-img.c
>> > index 4490a22..bad3f64 100644
>> > --- a/qemu-img.c
>> > +++ b/qemu-img.c
>> > @@ -29,6 +29,7 @@
>> >  #include "qemu/error-report.h"
>> >  #include "qemu/osdep.h"
>> >  #include "sysemu/sysemu.h"
>> > +#include "sysemu/block-backend.h"
>> >  #include "block/block_int.h"
>> >  #include "block/qapi.h"
>> >  #include <getopt.h>
>> > @@ -575,6 +576,7 @@ static int img_check(int argc, char **argv)
>> >      int c, ret;
>> >      OutputFormat output_format = OFORMAT_HUMAN;
>> >      const char *filename, *fmt, *output, *cache;
>> > +    BlockBackend *blk;
>> >      BlockDriverState *bs;
>> >      int fix = 0;
>> >      int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
>> > @@ -649,6 +651,7 @@ static int img_check(int argc, char **argv)
>> >          return 1;
>> >      }
>> >  
>> 
>> > +    blk = blk_new("image", &error_abort);
>> Hmm we are so sure this will work that we don't do if (!block) ?
>
> Ok I understood we are sure because we control the id and won't use twice the same.

Exactly!

[...]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 06/23] block: Eliminate bdrv_states, use block_next() instead
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 06/23] block: Eliminate bdrv_states, use block_next() instead Markus Armbruster
@ 2014-09-11 10:25   ` Benoît Canet
  0 siblings, 0 replies; 76+ messages in thread
From: Benoît Canet @ 2014-09-11 10:25 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:35 (+0200), Markus Armbruster wrote :
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block.c                   | 43 +++++++++++++++++++------------------------
>  block/block-backend.c     |  4 ++++
>  include/block/block_int.h |  2 --
>  3 files changed, 23 insertions(+), 26 deletions(-)
> 
> diff --git a/block.c b/block.c
> index a6c03da..89f9cf0 100644
> --- a/block.c
> +++ b/block.c
> @@ -24,6 +24,7 @@
>  #include "config-host.h"
>  #include "qemu-common.h"
>  #include "trace.h"
> +#include "sysemu/block-backend.h"
>  #include "block/block_int.h"
>  #include "block/blockjob.h"
>  #include "qemu/module.h"
> @@ -90,9 +91,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);
>  
> @@ -355,9 +353,6 @@ BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
>      bs = bdrv_new();
>  
>      pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
> -    if (device_name[0] != '\0') {
> -        QTAILQ_INSERT_TAIL(&bdrv_states, bs, device_list);
> -    }
>  
>      return bs;
>  }
> @@ -1888,7 +1883,7 @@ void bdrv_close_all(void)
>  {
>      BlockDriverState *bs;
>  
> -    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>          AioContext *aio_context = bdrv_get_aio_context(bs);
>  
>          aio_context_acquire(aio_context);
> @@ -1939,7 +1934,7 @@ void bdrv_drain_all(void)
>      while (busy) {
>          busy = false;
>  
> -        QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
> +        for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>              AioContext *aio_context = bdrv_get_aio_context(bs);
>              bool bs_busy;
>  
> @@ -1960,9 +1955,6 @@ void bdrv_drain_all(void)
>     Also, NULL terminate the device_name to prevent double remove */
>  void bdrv_make_anon(BlockDriverState *bs)
>  {
> -    if (bs->device_name[0] != '\0') {
> -        QTAILQ_REMOVE(&bdrv_states, bs, device_list);
> -    }
>      bs->device_name[0] = '\0';
>      if (bs->node_name[0] != '\0') {
>          QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list);
> @@ -2016,10 +2008,9 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
>      /* job */
>      bs_dest->job                = bs_src->job;
>  
> -    /* keep the same entry in bdrv_states */
>      pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
>              bs_src->device_name);
> -    bs_dest->device_list = bs_src->device_list;
> +
>      memcpy(bs_dest->op_blockers, bs_src->op_blockers,
>             sizeof(bs_dest->op_blockers));
>  }
> @@ -2363,7 +2354,7 @@ int bdrv_commit_all(void)
>  {
>      BlockDriverState *bs;
>  
> -    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>          AioContext *aio_context = bdrv_get_aio_context(bs);
>  
>          aio_context_acquire(aio_context);
> @@ -3807,7 +3798,7 @@ BlockDriverState *bdrv_find(const char *name)
>  {
>      BlockDriverState *bs;
>  
> -    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>          if (!strcmp(name, bs->device_name)) {
>              return bs;
>          }
> @@ -3888,17 +3879,21 @@ bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base)
>  
>  BlockDriverState *bdrv_next(BlockDriverState *bs)
>  {
> -    if (!bs) {
> -        return QTAILQ_FIRST(&bdrv_states);
> -    }
> -    return QTAILQ_NEXT(bs, device_list);

> +    BlockBackend *blk;
> +
> +    for (blk = blk_next(bs ? bs->blk : NULL);
> +         blk && !blk_bs(blk);
> +         blk = blk_next(blk))
> +        ;
> +
> +    return blk ? blk_bs(blk) : NULL;

I find ?: hard to read and I know at least one maintainer
prefers simples ifs to it.

BlockDriverState *bdrv_next(BlockDriverState *bs)
{
    BlockBackend *blk = NULL;

    /* if a BDS is provided use it's block backend as a starting point */
    if (bs) {
        blk = bl->blk;
    }

    /* looking for the next block backend having a BDS attached */
    for (blk = blk_next(blk);
         blk && !blk_bs(blk);
         blk = blk_next(blk))
         ;

   /* the search was successfull */
   if (blk) {
       return blk_bs(blk);
   }

   return NULL;
}

I think getting rid of ?: spread the brain load sequentially by being less compact
but anyway your code is correct so it's up to you.

>  }
>  
>  void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
>  {
>      BlockDriverState *bs;
>  
> -    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>          it(opaque, bs);
>      }
>  }
> @@ -3918,7 +3913,7 @@ int bdrv_flush_all(void)
>      BlockDriverState *bs;
>      int result = 0;
>  
> -    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>          AioContext *aio_context = bdrv_get_aio_context(bs);
>          int ret;
>  
> @@ -5065,7 +5060,7 @@ void bdrv_invalidate_cache_all(Error **errp)
>      BlockDriverState *bs;
>      Error *local_err = NULL;
>  
> -    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>          AioContext *aio_context = bdrv_get_aio_context(bs);
>  
>          aio_context_acquire(aio_context);
> @@ -5082,7 +5077,7 @@ void bdrv_clear_incoming_migration_all(void)
>  {
>      BlockDriverState *bs;
>  
> -    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>          AioContext *aio_context = bdrv_get_aio_context(bs);
>  
>          aio_context_acquire(aio_context);
> @@ -5918,7 +5913,7 @@ bool bdrv_is_first_non_filter(BlockDriverState *candidate)
>      BlockDriverState *bs;
>  
>      /* walk down the bs forest recursively */
> -    QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>          bool perm;
>  
>          /* try to recurse in this top level bs */
> diff --git a/block/block-backend.c b/block/block-backend.c
> index ae51f7f..c0876fa 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -191,6 +191,10 @@ BlockDriverState *blk_detach_bs(BlockBackend *blk)
>  {
>      BlockDriverState *bs = blk->bs;
>  
> +    /*
> +     * Must bdrv_unref() before zapping bs->blk, or else
> +     * bdrv_drain_all() will miss bs.
> +     */
>      if (bs) {
>          bs->blk = NULL;
>          blk->bs = NULL;
> diff --git a/include/block/block_int.h b/include/block/block_int.h
> index a04c852..d5de08b 100644
> --- a/include/block/block_int.h
> +++ b/include/block/block_int.h
> @@ -396,8 +396,6 @@ struct BlockDriverState {
>      QTAILQ_ENTRY(BlockDriverState) node_list;
>      /* Device name is the name associated with the "drive" the guest sees */
>      char device_name[32];
> -    /* element of the list of "drives" the guest sees */
> -    QTAILQ_ENTRY(BlockDriverState) device_list;
>      QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
>      int refcnt;
>  
> -- 
> 1.9.3
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 07/23] block: Eliminate bdrv_iterate(), use bdrv_next()
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 07/23] block: Eliminate bdrv_iterate(), use bdrv_next() Markus Armbruster
@ 2014-09-11 10:46   ` Benoît Canet
  2014-09-11 18:44     ` Markus Armbruster
  0 siblings, 1 reply; 76+ messages in thread
From: Benoît Canet @ 2014-09-11 10:46 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:36 (+0200), Markus Armbruster wrote :
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block-migration.c     | 30 +++++++++++++++---------------
>  block.c               |  9 ---------
>  blockdev.c            | 31 +++++++++++++------------------
>  include/block/block.h |  2 --
>  monitor.c             | 33 +++++++++------------------------
>  5 files changed, 37 insertions(+), 68 deletions(-)
> 
> diff --git a/block-migration.c b/block-migration.c
> index 3ad31a2..cb3e16c 100644
> --- a/block-migration.c
> +++ b/block-migration.c
> @@ -343,12 +343,25 @@ static void unset_dirty_tracking(void)
>      }
>  }
>  
> -static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
> +static void init_blk_migration(QEMUFile *f)
>  {
> +    BlockDriverState *bs;
>      BlkMigDevState *bmds;
>      int64_t sectors;
>  
> -    if (!bdrv_is_read_only(bs)) {
> +    block_mig_state.submitted = 0;
> +    block_mig_state.read_done = 0;
> +    block_mig_state.transferred = 0;
> +    block_mig_state.total_sector_sum = 0;
> +    block_mig_state.prev_progress = -1;
> +    block_mig_state.bulk_completed = 0;
> +    block_mig_state.zero_blocks = migrate_zero_blocks();
> +
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
> +        if (bdrv_is_read_only(bs)) {
> +            continue;
> +        }
> +
>          sectors = bdrv_nb_sectors(bs);
>          if (sectors <= 0) {
>              return;
> @@ -378,19 +391,6 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
>      }
>  }
>  
> -static void init_blk_migration(QEMUFile *f)
> -{
> -    block_mig_state.submitted = 0;
> -    block_mig_state.read_done = 0;
> -    block_mig_state.transferred = 0;
> -    block_mig_state.total_sector_sum = 0;
> -    block_mig_state.prev_progress = -1;
> -    block_mig_state.bulk_completed = 0;
> -    block_mig_state.zero_blocks = migrate_zero_blocks();
> -
> -    bdrv_iterate(init_blk_migration_it, NULL);
> -}
> -
>  /* Called with no lock taken.  */
>  
>  static int blk_mig_save_bulked_block(QEMUFile *f)
> diff --git a/block.c b/block.c
> index 89f9cf0..593d89b 100644
> --- a/block.c
> +++ b/block.c
> @@ -3889,15 +3889,6 @@ BlockDriverState *bdrv_next(BlockDriverState *bs)
>      return blk ? blk_bs(blk) : NULL;
>  }
>  
> -void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
> -{
> -    BlockDriverState *bs;
> -
> -    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
> -        it(opaque, bs);
> -    }
> -}
> -
>  const char *bdrv_get_device_name(BlockDriverState *bs)
>  {
>      return bs->device_name;
> diff --git a/blockdev.c b/blockdev.c
> index 791f6d9..353563e 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -2520,26 +2520,21 @@ fail:
>      qmp_output_visitor_cleanup(ov);
>  }
>  
> -static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs)
> -{
> -    BlockJobInfoList **prev = opaque;
> -    BlockJob *job = bs->job;
> -
> -    if (job) {
> -        BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1);
> -        elem->value = block_job_query(bs->job);
> -        (*prev)->next = elem;
> -        *prev = elem;
> -    }
> -}
> -
>  BlockJobInfoList *qmp_query_block_jobs(Error **errp)
>  {
> -    /* Dummy is a fake list element for holding the head pointer */
> -    BlockJobInfoList dummy = {};
> -    BlockJobInfoList *prev = &dummy;
> -    bdrv_iterate(do_qmp_query_block_jobs_one, &prev);
> -    return dummy.next;
> +    BlockJobInfoList *head = NULL, **p_next = &head;
> +    BlockDriverState *bs;
> +
> +    for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
> +        if (bs->job) {
> +            BlockJobInfoList *elem = g_new0(BlockJobInfoList, 1);
> +            elem->value = block_job_query(bs->job);
> +            *p_next = elem;
> +            p_next = &elem->next;
> +        }
> +    }
> +
> +    return head;
>  }
>  
>  QemuOptsList qemu_common_drive_opts = {
> diff --git a/include/block/block.h b/include/block/block.h
> index 95139c0..8cf9ea3 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -409,8 +409,6 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
>                                   Error **errp);
>  bool bdrv_chain_contains(BlockDriverState *top, BlockDriverState *base);
>  BlockDriverState *bdrv_next(BlockDriverState *bs);
> -void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs),
> -                  void *opaque);
>  int bdrv_is_encrypted(BlockDriverState *bs);
>  int bdrv_key_required(BlockDriverState *bs);
>  int bdrv_set_key(BlockDriverState *bs, const char *key);
> diff --git a/monitor.c b/monitor.c
> index 34cee74..4ae66df 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -4208,24 +4208,6 @@ static void file_completion(Monitor *mon, const char *input)
>      closedir(ffs);
>  }
>  
> -typedef struct MonitorBlockComplete {
> -    Monitor *mon;
> -    const char *input;
> -} MonitorBlockComplete;
> -
> -static void block_completion_it(void *opaque, BlockDriverState *bs)
> -{
> -    const char *name = bdrv_get_device_name(bs);
> -    MonitorBlockComplete *mbc = opaque;
> -    Monitor *mon = mbc->mon;
> -    const char *input = mbc->input;
> -
> -    if (input[0] == '\0' ||
> -        !strncmp(name, (char *)input, strlen(input))) {
> -        readline_add_completion(mon->rs, name);
> -    }
> -}
> -
>  static const char *next_arg_type(const char *typestr)
>  {
>      const char *p = strchr(typestr, ':');
> @@ -4663,9 +4645,9 @@ static void monitor_find_completion_by_table(Monitor *mon,
>  {
>      const char *cmdname;
>      int i;
> -    const char *ptype, *str;
> +    const char *ptype, *str, *name;
>      const mon_cmd_t *cmd;
> -    MonitorBlockComplete mbs;
> +    BlockDriverState *bs;
>  
>      if (nb_args <= 1) {
>          /* command completion */
> @@ -4717,10 +4699,13 @@ static void monitor_find_completion_by_table(Monitor *mon,
>              break;
>          case 'B':
>              /* block device name completion */
> -            mbs.mon = mon;
> -            mbs.input = str;

> -            readline_set_completion_index(mon->rs, strlen(str));

Why is this line removed ?
In monitor readline_set_completion_index seems to work in pair with readline_add_completion.
Either this line should be removed and readline_add_completion too or the oposite.

> -            bdrv_iterate(block_completion_it, &mbs);
> +            for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
> +                name = bdrv_get_device_name(bs);
> +                if (str[0] == '\0' ||
> +                    !strncmp(name, str, strlen(str))) {
> +                    readline_add_completion(mon->rs, name);
> +                }
> +            }
>              break;
>          case 's':
>          case 'S':
> -- 
> 1.9.3
> 
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState
  2014-09-10 11:55   ` Benoît Canet
@ 2014-09-11 10:52     ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 10:52 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> The Wednesday 10 Sep 2014 à 10:13:32 (+0200), Markus Armbruster wrote :
>> The pointer from BlockBackend to BlockDriverState is a strong
>> reference, managed with bdrv_ref() / bdrv_unref(), the back-pointer is
>> a weak one.
>> 
>> Convenience function blk_new_with_bs() creates a BlockBackend with its
>> BlockDriverState.  Callers have to unref both.  The commit after next
>> will relieve them of the need to unref the BlockDriverState.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  block.c                        |  10 ++--
>>  block/block-backend.c          |  79 +++++++++++++++++++++++++++++++
>>  blockdev.c                     |  49 +++++++++++---------
>>  hw/block/xen_disk.c            |   8 +---
>>  include/block/block_int.h      |   2 +
>>  include/sysemu/block-backend.h |   5 ++
>>  qemu-img.c                     | 103 +++++++++++++++++++++--------------------
>>  qemu-io.c                      |   4 +-
>>  qemu-nbd.c                     |   3 +-
>>  9 files changed, 175 insertions(+), 88 deletions(-)
>> 
>> diff --git a/block.c b/block.c
>> index 4b3bcd4..a6c03da 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -2032,7 +2032,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
>>   * This will modify the BlockDriverState fields, and swap contents
>>   * between bs_new and bs_old. Both bs_new and bs_old are modified.
>>   *
>> - * bs_new is required to be anonymous.
>> + * bs_new must be nameless and not attached to a BlockBackend.
>
> 1)
> Does "nameless" refer to device_name or node_name ?
> From the code I see it's device_name but the wording can be confusing.

Yes.  It's slightly better than "anonymous", because that really means
both device_name and node_name (since commit dc364f4).

The "nameless" part will go away in PATCH 08, so I'm inclined not to
worry about it now.

> maybe:
> + * bs_new must have an empty device_name and not be attached to a BlockBackend.

Can do if you think it's necessary.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[]
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[] Markus Armbruster
  2014-09-10 16:09   ` Eric Blake
@ 2014-09-11 11:34   ` Benoît Canet
  2014-09-11 11:43     ` Benoît Canet
                       ` (2 more replies)
  1 sibling, 3 replies; 76+ messages in thread
From: Benoît Canet @ 2014-09-11 11:34 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:37 (+0200), Markus Armbruster wrote :
> device_name[] is can become non-empty only in bdrv_new_named() and
> bdrv_move_feature_fields().  The latter is used only to undo damage
> done by bdrv_swap().  The former is called only by blk_new_with_bs().
> Therefore, when a BlockDriverState's device_name[] is non-empty, then
> it's owned by a BlockBackend.
> 
> The converse is also true, because blk_attach_bs() is called only by
> blk_new_with_bs() so far.
> 
> Furthermore, blk_new_with_bs() keeps the two names equal.
> 
> Therefore, device_name[] is redundant.  Eliminate it.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block-migration.c         | 12 +++++----
>  block.c                   | 63 ++++++++++++++---------------------------------
>  block/block-backend.c     | 12 ++++-----
>  block/cow.c               |  2 +-
>  block/mirror.c            |  3 ++-
>  block/qapi.c              |  6 ++---
>  block/qcow.c              |  4 +--
>  block/qcow2.c             |  4 +--
>  block/qed.c               |  2 +-
>  block/quorum.c            |  4 +--
>  block/vdi.c               |  2 +-
>  block/vhdx.c              |  2 +-
>  block/vmdk.c              |  4 +--
>  block/vpc.c               |  2 +-
>  block/vvfat.c             |  2 +-
>  blockjob.c                |  3 ++-
>  include/block/block.h     |  3 +--
>  include/block/block_int.h |  2 --
>  18 files changed, 53 insertions(+), 79 deletions(-)
> 
> diff --git a/block-migration.c b/block-migration.c
> index cb3e16c..da30e93 100644
> --- a/block-migration.c
> +++ b/block-migration.c
> @@ -14,7 +14,9 @@
>   */
>  
>  #include "qemu-common.h"
> -#include "block/block_int.h"
> +#include "block/block.h"
> +#include "qemu/error-report.h"
> +#include "qemu/main-loop.h"
>  #include "hw/hw.h"
>  #include "qemu/queue.h"
>  #include "qemu/timer.h"
> @@ -130,9 +132,9 @@ static void blk_send(QEMUFile *f, BlkMigBlock * blk)
>                       | flags);
>  
>      /* device name */
> -    len = strlen(blk->bmds->bs->device_name);
> +    len = strlen(bdrv_get_device_name(blk->bmds->bs));
>      qemu_put_byte(f, len);
> -    qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len);
> +    qemu_put_buffer(f, (uint8_t *)bdrv_get_device_name(blk->bmds->bs), len);
>  
>      /* if a block is zero we need to flush here since the network
>       * bandwidth is now a lot higher than the storage device bandwidth.
> @@ -382,9 +384,9 @@ static void init_blk_migration(QEMUFile *f)
>  
>          if (bmds->shared_base) {
>              DPRINTF("Start migration for %s with shared base image\n",
> -                    bs->device_name);
> +                    bdrv_get_device_name(bs));
>          } else {
> -            DPRINTF("Start full migration for %s\n", bs->device_name);
> +            DPRINTF("Start full migration for %s\n", bdrv_get_device_name(bs));
>          }
>  
>          QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
> diff --git a/block.c b/block.c
> index 593d89b..61ea15d 100644
> --- a/block.c
> +++ b/block.c
> @@ -332,31 +332,6 @@ void bdrv_register(BlockDriver *bdrv)
>      QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
>  }
>  
> -/* create a new block device (by default it is empty) */
> -BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
> -{
> -    BlockDriverState *bs;
> -
> -    assert(*device_name);
> -
> -    if (bdrv_find(device_name)) {
> -        error_setg(errp, "Device with id '%s' already exists",
> -                   device_name);
> -        return NULL;
> -    }
> -    if (bdrv_find_node(device_name)) {
> -        error_setg(errp, "Device with node-name '%s' already exists",
> -                   device_name);
> -        return NULL;
> -    }
> -
> -    bs = bdrv_new();
> -
> -    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
> -
> -    return bs;
> -}
> -
>  BlockDriverState *bdrv_new(void)
>  {
>      BlockDriverState *bs;
> @@ -1159,7 +1134,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
>      } else if (backing_hd) {
>          error_setg(&bs->backing_blocker,
>                     "device is used as backing hd of '%s'",
> -                   bs->device_name);
> +                   bdrv_get_device_name(bs));
>      }
>  
>      bs->backing_hd = backing_hd;
> @@ -1533,7 +1508,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
>          } else {
>              error_setg(errp, "Block format '%s' used by device '%s' doesn't "
>                         "support the option '%s'", drv->format_name,
> -                       bs->device_name, entry->key);
> +                       bdrv_get_device_name(bs), entry->key);
>          }
>  
>          ret = -EINVAL;
> @@ -1740,7 +1715,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
>      if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) &&
>          reopen_state->flags & BDRV_O_RDWR) {
>          error_set(errp, QERR_DEVICE_IS_READ_ONLY,
> -                  reopen_state->bs->device_name);
> +                  bdrv_get_device_name(reopen_state->bs));
>          goto error;
>      }
>  
> @@ -1767,7 +1742,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
>          /* It is currently mandatory to have a bdrv_reopen_prepare()
>           * handler for each supported drv. */
>          error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> -                  drv->format_name, reopen_state->bs->device_name,
> +                  drv->format_name, bdrv_get_device_name(reopen_state->bs),
>                   "reopening of file");
>          ret = -1;
>          goto error;
> @@ -1955,7 +1930,6 @@ void bdrv_drain_all(void)
>     Also, NULL terminate the device_name to prevent double remove */
>  void bdrv_make_anon(BlockDriverState *bs)
>  {
> -    bs->device_name[0] = '\0';
>      if (bs->node_name[0] != '\0') {
>          QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list);
>      }
> @@ -2008,9 +1982,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
>      /* job */
>      bs_dest->job                = bs_src->job;
>  
> -    pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
> -            bs_src->device_name);
> -
>      memcpy(bs_dest->op_blockers, bs_src->op_blockers,
>             sizeof(bs_dest->op_blockers));
>  }
> @@ -2023,7 +1994,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
>   * This will modify the BlockDriverState fields, and swap contents
>   * between bs_new and bs_old. Both bs_new and bs_old are modified.
>   *
> - * bs_new must be nameless and not attached to a BlockBackend.
> + * bs_new must not be attached to a BlockBackend.
>   *
>   * This function does not create any image files.
>   */
> @@ -2042,8 +2013,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
>          QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list);
>      }
>  
> -    /* bs_new must be nameless and shouldn't have anything fancy enabled */
> -    assert(bs_new->device_name[0] == '\0');
> +    /* bs_new must be unattached and shouldn't have anything fancy enabled */
>      assert(!bs_new->blk);
>      assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
>      assert(bs_new->job == NULL);
> @@ -2060,8 +2030,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
>      bdrv_move_feature_fields(bs_old, bs_new);
>      bdrv_move_feature_fields(bs_new, &tmp);
>  
> -    /* bs_new must remain nameless and unattached */
> -    assert(bs_new->device_name[0] == '\0');
> +    /* bs_new must remain unattached */
>      assert(!bs_new->blk);
>  
>      /* Check a few fields that should remain attached to the device */
> @@ -2089,7 +2058,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
>   * This will modify the BlockDriverState fields, and swap contents
>   * between bs_new and bs_top. Both bs_new and bs_top are modified.
>   *
> - * bs_new must be nameless and not attached to a BlockBackend.
> + * bs_new must not be attached to a BlockBackend.
>   *
>   * This function does not create any image files.
>   */
> @@ -3799,7 +3768,7 @@ BlockDriverState *bdrv_find(const char *name)
>      BlockDriverState *bs;
>  
>      for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
> -        if (!strcmp(name, bs->device_name)) {
> +        if (!strcmp(name, bdrv_get_device_name(bs))) {
>              return bs;
>          }
>      }
> @@ -3889,9 +3858,10 @@ BlockDriverState *bdrv_next(BlockDriverState *bs)
>      return blk ? blk_bs(blk) : NULL;
>  }
>  
> -const char *bdrv_get_device_name(BlockDriverState *bs)
> +const char *bdrv_get_device_name(const BlockDriverState *bs)
>  {
> -    return bs->device_name;
> +    const char *name = bs->blk ? blk_name(bs->blk) : NULL;
> +    return name ?: "";
>  }

Why not ?

    return bs->blk ? blk_name(bs->blk) : "";

or 

    if (bs->blk) {
        return blk_name(bs->blk);
    }

    return "";

Would it fail to do the job ?

Also we could have made sure that bdrv_get_device_name return either
a non empty string or NULL.

(We know blk_name will return a non empty string it's asserted)

This would need to change a few test all around the code but the final
code logic would be less convoluted:
-convert NULL to "" then test for not ""
would turn into
-return NULL test for not NULL

>  
>  int bdrv_get_flags(BlockDriverState *bs)
> @@ -5253,13 +5223,15 @@ int bdrv_media_changed(BlockDriverState *bs)
>  void bdrv_eject(BlockDriverState *bs, bool eject_flag)
>  {
>      BlockDriver *drv = bs->drv;
> +    const char *device_name;
>  
>      if (drv && drv->bdrv_eject) {
>          drv->bdrv_eject(bs, eject_flag);
>      }
>  
> -    if (bs->device_name[0] != '\0') {
> -        qapi_event_send_device_tray_moved(bdrv_get_device_name(bs),

> +    device_name = bdrv_get_device_name(bs);
> +        qapi_event_send_device_tray_moved(device_name,
>                                            eject_flag, &error_abort);
>      }
>  }
> @@ -5469,7 +5441,8 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
>          blocker = QLIST_FIRST(&bs->op_blockers[op]);
>          if (errp) {
>              error_setg(errp, "Device '%s' is busy: %s",
> -                       bs->device_name, error_get_pretty(blocker->reason));
> +                       bdrv_get_device_name(bs),
> +                       error_get_pretty(blocker->reason));
>          }
>          return true;
>      }
> diff --git a/block/block-backend.c b/block/block-backend.c
> index c0876fa..2f10d6a 100644
> --- a/block/block-backend.c
> +++ b/block/block-backend.c
> @@ -67,17 +67,17 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp)
>      BlockBackend *blk;
>      BlockDriverState *bs;
>  
> +    if (bdrv_find_node(name)) {
> +        error_setg(errp, "Device with node-name '%s' already exists", name);

Maybe the message written by the person who contributed the initial code (me) mislead you.
I think the intent is good but the wording is wrong.
node-name is associated with a regular BDS. A device cannot have a node name.

Maybe something in the vein of:
        error_setg(errp, "Device name '%s' would conflict with the node-name of an existing block driver state", name);

> +        return NULL;
> +    }
> +
>      blk = blk_new(name, errp);
>      if (!blk) {
>          return NULL;
>      }
>  
> -    bs = bdrv_new_named(name, errp);
> -    if (!bs) {
> -        blk_unref(blk);
> -        return NULL;
> -    }
> -
> +    bs = bdrv_new();
>      blk_attach_bs(blk, bs);
>      return blk;
>  }
> diff --git a/block/cow.c b/block/cow.c
> index 6ee4833..dda1e17 100644
> --- a/block/cow.c
> +++ b/block/cow.c
> @@ -84,7 +84,7 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
>          snprintf(version, sizeof(version),
>                 "COW version %" PRIu32, cow_header.version);
>          error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> -            bs->device_name, "cow", version);
> +            bdrv_get_device_name(bs), "cow", version);
>          ret = -ENOTSUP;
>          goto fail;
>      }
> diff --git a/block/mirror.c b/block/mirror.c
> index 18b18e0..829be2f 100644
> --- a/block/mirror.c
> +++ b/block/mirror.c
> @@ -567,7 +567,8 @@ static void mirror_complete(BlockJob *job, Error **errp)
>          return;
>      }
>      if (!s->synced) {
> -        error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
> +        error_set(errp, QERR_BLOCK_JOB_NOT_READY,
> +                  bdrv_get_device_name(job->bs));
>          return;
>      }
>  
> diff --git a/block/qapi.c b/block/qapi.c
> index 79d1e6a..cc8f711 100644
> --- a/block/qapi.c
> +++ b/block/qapi.c
> @@ -272,7 +272,7 @@ void bdrv_query_info(BlockDriverState *bs,
>      BlockDriverState *bs0;
>      ImageInfo **p_image_info;
>      Error *local_err = NULL;
> -    info->device = g_strdup(bs->device_name);
> +    info->device = g_strdup(bdrv_get_device_name(bs));
>      info->type = g_strdup("unknown");
>      info->locked = bdrv_dev_is_medium_locked(bs);
>      info->removable = bdrv_dev_has_removable_media(bs);
> @@ -327,9 +327,9 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs)
>  
>      s = g_malloc0(sizeof(*s));
>  
> -    if (bs->device_name[0]) {
> +    if (bdrv_get_device_name(bs)[0]) {
>          s->has_device = true;
> -        s->device = g_strdup(bs->device_name);
> +        s->device = g_strdup(bdrv_get_device_name(bs));
>      }
>  
>      s->stats = g_malloc0(sizeof(*s->stats));
> diff --git a/block/qcow.c b/block/qcow.c
> index 67c237f..2d803ac 100644
> --- a/block/qcow.c
> +++ b/block/qcow.c
> @@ -124,7 +124,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
>          snprintf(version, sizeof(version), "QCOW version %" PRIu32,
>                   header.version);
>          error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> -                  bs->device_name, "qcow", version);
> +                  bdrv_get_device_name(bs), "qcow", version);
>          ret = -ENOTSUP;
>          goto fail;
>      }
> @@ -231,7 +231,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
>      /* Disable migration when qcow images are used */
>      error_set(&s->migration_blocker,
>                QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> -              "qcow", bs->device_name, "live migration");
> +              "qcow", bdrv_get_device_name(bs), "live migration");
>      migrate_add_blocker(s->migration_blocker);
>  
>      qemu_co_mutex_init(&s->lock);
> diff --git a/block/qcow2.c b/block/qcow2.c
> index f9e045f..0ab455e 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -203,8 +203,8 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs,
>      vsnprintf(msg, sizeof(msg), fmt, ap);
>      va_end(ap);
>  
> -    error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, bs->device_name, "qcow2",
> -              msg);
> +    error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> +              bdrv_get_device_name(bs), "qcow2", msg);
>  }
>  
>  static void report_unsupported_feature(BlockDriverState *bs,
> diff --git a/block/qed.c b/block/qed.c
> index ba395af..f20ffb3 100644
> --- a/block/qed.c
> +++ b/block/qed.c
> @@ -422,7 +422,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
>          snprintf(buf, sizeof(buf), "%" PRIx64,
>              s->header.features & ~QED_FEATURE_MASK);
>          error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> -            bs->device_name, "QED", buf);
> +            bdrv_get_device_name(bs), "QED", buf);
>          return -ENOTSUP;
>      }
>      if (!qed_is_cluster_size_valid(s->header.cluster_size)) {
> diff --git a/block/quorum.c b/block/quorum.c
> index 093382e..f958269 100644
> --- a/block/quorum.c
> +++ b/block/quorum.c
> @@ -227,8 +227,8 @@ static void quorum_report_bad(QuorumAIOCB *acb, char *node_name, int ret)
>  
>  static void quorum_report_failure(QuorumAIOCB *acb)
>  {
> -    const char *reference = acb->common.bs->device_name[0] ?
> -                            acb->common.bs->device_name :
> +    const char *reference = bdrv_get_device_name(acb->common.bs)[0] ?
> +                            bdrv_get_device_name(acb->common.bs) :
>                              acb->common.bs->node_name;
>  
>      qapi_event_send_quorum_failure(reference, acb->sector_num,
> diff --git a/block/vdi.c b/block/vdi.c
> index 4b10aac..2e6f31c 100644
> --- a/block/vdi.c
> +++ b/block/vdi.c
> @@ -490,7 +490,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
>      /* Disable migration when vdi images are used */
>      error_set(&s->migration_blocker,
>                QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> -              "vdi", bs->device_name, "live migration");
> +              "vdi", bdrv_get_device_name(bs), "live migration");
>      migrate_add_blocker(s->migration_blocker);
>  
>      return 0;
> diff --git a/block/vhdx.c b/block/vhdx.c
> index 87c99fc..8bf1af1 100644
> --- a/block/vhdx.c
> +++ b/block/vhdx.c
> @@ -1003,7 +1003,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
>      /* Disable migration when VHDX images are used */
>      error_set(&s->migration_blocker,
>              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> -            "vhdx", bs->device_name, "live migration");
> +            "vhdx", bdrv_get_device_name(bs), "live migration");
>      migrate_add_blocker(s->migration_blocker);
>  
>      return 0;
> diff --git a/block/vmdk.c b/block/vmdk.c
> index a1cb911..7bc1474 100644
> --- a/block/vmdk.c
> +++ b/block/vmdk.c
> @@ -657,7 +657,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
>          snprintf(buf, sizeof(buf), "VMDK version %" PRId32,
>                   le32_to_cpu(header.version));
>          error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> -                  bs->device_name, "vmdk", buf);
> +                  bdrv_get_device_name(bs), "vmdk", buf);
>          return -ENOTSUP;
>      } else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR)) {
>          /* VMware KB 2064959 explains that version 3 added support for
> @@ -939,7 +939,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
>      /* Disable migration when VMDK images are used */
>      error_set(&s->migration_blocker,
>                QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> -              "vmdk", bs->device_name, "live migration");
> +              "vmdk", bdrv_get_device_name(bs), "live migration");
>      migrate_add_blocker(s->migration_blocker);
>      g_free(buf);
>      return 0;
> diff --git a/block/vpc.c b/block/vpc.c
> index 055efc4..7bb90d5 100644
> --- a/block/vpc.c
> +++ b/block/vpc.c
> @@ -320,7 +320,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
>      /* Disable migration when VHD images are used */
>      error_set(&s->migration_blocker,
>                QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> -              "vpc", bs->device_name, "live migration");
> +              "vpc", bdrv_get_device_name(bs), "live migration");
>      migrate_add_blocker(s->migration_blocker);
>  
>      return 0;
> diff --git a/block/vvfat.c b/block/vvfat.c
> index 6c9fde0..cefe3a4 100644
> --- a/block/vvfat.c
> +++ b/block/vvfat.c
> @@ -1182,7 +1182,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
>      if (s->qcow) {
>          error_set(&s->migration_blocker,
>                    QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> -                  "vvfat (rw)", bs->device_name, "live migration");
> +                  "vvfat (rw)", bdrv_get_device_name(bs), "live migration");
>          migrate_add_blocker(s->migration_blocker);
>      }
>  
> diff --git a/blockjob.c b/blockjob.c
> index 0689fdd..3af0f6c 100644
> --- a/blockjob.c
> +++ b/blockjob.c
> @@ -107,7 +107,8 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
>  void block_job_complete(BlockJob *job, Error **errp)
>  {
>      if (job->paused || job->cancelled || !job->driver->complete) {
> -        error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
> +        error_set(errp, QERR_BLOCK_JOB_NOT_READY,
> +                  bdrv_get_device_name(job->bs));
>          return;
>      }
>  
> diff --git a/include/block/block.h b/include/block/block.h
> index 8cf9ea3..fb4fff9 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -203,7 +203,6 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
>  int bdrv_create(BlockDriver *drv, const char* filename,
>                  QemuOpts *opts, Error **errp);
>  int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
> -BlockDriverState *bdrv_new_named(const char *device_name, Error **errp);
>  BlockDriverState *bdrv_new(void);
>  void bdrv_make_anon(BlockDriverState *bs);
>  void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
> @@ -415,7 +414,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key);
>  int bdrv_query_missing_keys(void);
>  void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
>                           void *opaque);
> -const char *bdrv_get_device_name(BlockDriverState *bs);
> +const char *bdrv_get_device_name(const BlockDriverState *bs);
>  int bdrv_get_flags(BlockDriverState *bs);
>  int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
>                            const uint8_t *buf, int nb_sectors);
> diff --git a/include/block/block_int.h b/include/block/block_int.h
> index d5de08b..08ccb27 100644
> --- a/include/block/block_int.h
> +++ b/include/block/block_int.h
> @@ -394,8 +394,6 @@ struct BlockDriverState {
>      char node_name[32];
>      /* element of the list of named nodes building the graph */
>      QTAILQ_ENTRY(BlockDriverState) node_list;
> -    /* Device name is the name associated with the "drive" the guest sees */
> -    char device_name[32];
>      QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
>      int refcnt;
>  
> -- 
> 1.9.3
> 
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[]
  2014-09-11 11:34   ` Benoît Canet
@ 2014-09-11 11:43     ` Benoît Canet
  2014-09-11 13:00     ` Eric Blake
  2014-09-11 19:01     ` Markus Armbruster
  2 siblings, 0 replies; 76+ messages in thread
From: Benoît Canet @ 2014-09-11 11:43 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, Markus Armbruster, stefanha, qemu-devel

The Thursday 11 Sep 2014 à 13:34:33 (+0200), Benoît Canet wrote :
> The Wednesday 10 Sep 2014 à 10:13:37 (+0200), Markus Armbruster wrote :
> > device_name[] is can become non-empty only in bdrv_new_named() and
> > bdrv_move_feature_fields().  The latter is used only to undo damage
> > done by bdrv_swap().  The former is called only by blk_new_with_bs().
> > Therefore, when a BlockDriverState's device_name[] is non-empty, then
> > it's owned by a BlockBackend.
> > 
> > The converse is also true, because blk_attach_bs() is called only by
> > blk_new_with_bs() so far.
> > 
> > Furthermore, blk_new_with_bs() keeps the two names equal.
> > 
> > Therefore, device_name[] is redundant.  Eliminate it.
> > 
> > Signed-off-by: Markus Armbruster <armbru@redhat.com>
> > ---
> >  block-migration.c         | 12 +++++----
> >  block.c                   | 63 ++++++++++++++---------------------------------
> >  block/block-backend.c     | 12 ++++-----
> >  block/cow.c               |  2 +-
> >  block/mirror.c            |  3 ++-
> >  block/qapi.c              |  6 ++---
> >  block/qcow.c              |  4 +--
> >  block/qcow2.c             |  4 +--
> >  block/qed.c               |  2 +-
> >  block/quorum.c            |  4 +--
> >  block/vdi.c               |  2 +-
> >  block/vhdx.c              |  2 +-
> >  block/vmdk.c              |  4 +--
> >  block/vpc.c               |  2 +-
> >  block/vvfat.c             |  2 +-
> >  blockjob.c                |  3 ++-
> >  include/block/block.h     |  3 +--
> >  include/block/block_int.h |  2 --
> >  18 files changed, 53 insertions(+), 79 deletions(-)
> > 
> > diff --git a/block-migration.c b/block-migration.c
> > index cb3e16c..da30e93 100644
> > --- a/block-migration.c
> > +++ b/block-migration.c
> > @@ -14,7 +14,9 @@
> >   */
> >  
> >  #include "qemu-common.h"
> > -#include "block/block_int.h"
> > +#include "block/block.h"
> > +#include "qemu/error-report.h"
> > +#include "qemu/main-loop.h"
> >  #include "hw/hw.h"
> >  #include "qemu/queue.h"
> >  #include "qemu/timer.h"
> > @@ -130,9 +132,9 @@ static void blk_send(QEMUFile *f, BlkMigBlock * blk)
> >                       | flags);
> >  
> >      /* device name */
> > -    len = strlen(blk->bmds->bs->device_name);
> > +    len = strlen(bdrv_get_device_name(blk->bmds->bs));
> >      qemu_put_byte(f, len);
> > -    qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len);
> > +    qemu_put_buffer(f, (uint8_t *)bdrv_get_device_name(blk->bmds->bs), len);
> >  
> >      /* if a block is zero we need to flush here since the network
> >       * bandwidth is now a lot higher than the storage device bandwidth.
> > @@ -382,9 +384,9 @@ static void init_blk_migration(QEMUFile *f)
> >  
> >          if (bmds->shared_base) {
> >              DPRINTF("Start migration for %s with shared base image\n",
> > -                    bs->device_name);
> > +                    bdrv_get_device_name(bs));
> >          } else {
> > -            DPRINTF("Start full migration for %s\n", bs->device_name);
> > +            DPRINTF("Start full migration for %s\n", bdrv_get_device_name(bs));
> >          }
> >  
> >          QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
> > diff --git a/block.c b/block.c
> > index 593d89b..61ea15d 100644
> > --- a/block.c
> > +++ b/block.c
> > @@ -332,31 +332,6 @@ void bdrv_register(BlockDriver *bdrv)
> >      QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
> >  }
> >  
> > -/* create a new block device (by default it is empty) */
> > -BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
> > -{
> > -    BlockDriverState *bs;
> > -
> > -    assert(*device_name);
> > -
> > -    if (bdrv_find(device_name)) {
> > -        error_setg(errp, "Device with id '%s' already exists",
> > -                   device_name);
> > -        return NULL;
> > -    }
> > -    if (bdrv_find_node(device_name)) {
> > -        error_setg(errp, "Device with node-name '%s' already exists",
> > -                   device_name);
> > -        return NULL;
> > -    }
> > -
> > -    bs = bdrv_new();
> > -
> > -    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
> > -
> > -    return bs;
> > -}
> > -
> >  BlockDriverState *bdrv_new(void)
> >  {
> >      BlockDriverState *bs;
> > @@ -1159,7 +1134,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
> >      } else if (backing_hd) {
> >          error_setg(&bs->backing_blocker,
> >                     "device is used as backing hd of '%s'",
> > -                   bs->device_name);
> > +                   bdrv_get_device_name(bs));
> >      }
> >  
> >      bs->backing_hd = backing_hd;
> > @@ -1533,7 +1508,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
> >          } else {
> >              error_setg(errp, "Block format '%s' used by device '%s' doesn't "
> >                         "support the option '%s'", drv->format_name,
> > -                       bs->device_name, entry->key);
> > +                       bdrv_get_device_name(bs), entry->key);
> >          }
> >  
> >          ret = -EINVAL;
> > @@ -1740,7 +1715,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
> >      if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) &&
> >          reopen_state->flags & BDRV_O_RDWR) {
> >          error_set(errp, QERR_DEVICE_IS_READ_ONLY,
> > -                  reopen_state->bs->device_name);
> > +                  bdrv_get_device_name(reopen_state->bs));
> >          goto error;
> >      }
> >  
> > @@ -1767,7 +1742,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
> >          /* It is currently mandatory to have a bdrv_reopen_prepare()
> >           * handler for each supported drv. */
> >          error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> > -                  drv->format_name, reopen_state->bs->device_name,
> > +                  drv->format_name, bdrv_get_device_name(reopen_state->bs),
> >                   "reopening of file");
> >          ret = -1;
> >          goto error;
> > @@ -1955,7 +1930,6 @@ void bdrv_drain_all(void)
> >     Also, NULL terminate the device_name to prevent double remove */
> >  void bdrv_make_anon(BlockDriverState *bs)
> >  {
> > -    bs->device_name[0] = '\0';
> >      if (bs->node_name[0] != '\0') {
> >          QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list);
> >      }
> > @@ -2008,9 +1982,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
> >      /* job */
> >      bs_dest->job                = bs_src->job;
> >  
> > -    pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
> > -            bs_src->device_name);
> > -
> >      memcpy(bs_dest->op_blockers, bs_src->op_blockers,
> >             sizeof(bs_dest->op_blockers));
> >  }
> > @@ -2023,7 +1994,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
> >   * This will modify the BlockDriverState fields, and swap contents
> >   * between bs_new and bs_old. Both bs_new and bs_old are modified.
> >   *
> > - * bs_new must be nameless and not attached to a BlockBackend.
> > + * bs_new must not be attached to a BlockBackend.
> >   *
> >   * This function does not create any image files.
> >   */
> > @@ -2042,8 +2013,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
> >          QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list);
> >      }
> >  
> > -    /* bs_new must be nameless and shouldn't have anything fancy enabled */
> > -    assert(bs_new->device_name[0] == '\0');
> > +    /* bs_new must be unattached and shouldn't have anything fancy enabled */
> >      assert(!bs_new->blk);
> >      assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
> >      assert(bs_new->job == NULL);
> > @@ -2060,8 +2030,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
> >      bdrv_move_feature_fields(bs_old, bs_new);
> >      bdrv_move_feature_fields(bs_new, &tmp);
> >  
> > -    /* bs_new must remain nameless and unattached */
> > -    assert(bs_new->device_name[0] == '\0');
> > +    /* bs_new must remain unattached */
> >      assert(!bs_new->blk);
> >  
> >      /* Check a few fields that should remain attached to the device */
> > @@ -2089,7 +2058,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
> >   * This will modify the BlockDriverState fields, and swap contents
> >   * between bs_new and bs_top. Both bs_new and bs_top are modified.
> >   *
> > - * bs_new must be nameless and not attached to a BlockBackend.
> > + * bs_new must not be attached to a BlockBackend.
> >   *
> >   * This function does not create any image files.
> >   */
> > @@ -3799,7 +3768,7 @@ BlockDriverState *bdrv_find(const char *name)
> >      BlockDriverState *bs;
> >  
> >      for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
> > -        if (!strcmp(name, bs->device_name)) {
> > +        if (!strcmp(name, bdrv_get_device_name(bs))) {
> >              return bs;
> >          }
> >      }
> > @@ -3889,9 +3858,10 @@ BlockDriverState *bdrv_next(BlockDriverState *bs)
> >      return blk ? blk_bs(blk) : NULL;
> >  }
> >  
> > -const char *bdrv_get_device_name(BlockDriverState *bs)
> > +const char *bdrv_get_device_name(const BlockDriverState *bs)
> >  {
> > -    return bs->device_name;
> > +    const char *name = bs->blk ? blk_name(bs->blk) : NULL;
> > +    return name ?: "";
> >  }
> 
> Why not ?
> 
>     return bs->blk ? blk_name(bs->blk) : "";
> 
> or 
> 
>     if (bs->blk) {
>         return blk_name(bs->blk);
>     }
> 
>     return "";
> 
> Would it fail to do the job ?
> 
> Also we could have made sure that bdrv_get_device_name return either
> a non empty string or NULL.
> 
> (We know blk_name will return a non empty string it's asserted)
> 
> This would need to change a few test all around the code but the final
> code logic would be less convoluted:
> -convert NULL to "" then test for not ""
> would turn into
> -return NULL test for not NULL
> 
> >  
> >  int bdrv_get_flags(BlockDriverState *bs)
> > @@ -5253,13 +5223,15 @@ int bdrv_media_changed(BlockDriverState *bs)
> >  void bdrv_eject(BlockDriverState *bs, bool eject_flag)
> >  {
> >      BlockDriver *drv = bs->drv;
> > +    const char *device_name;
> >  
> >      if (drv && drv->bdrv_eject) {
> >          drv->bdrv_eject(bs, eject_flag);
> >      }
> >  
> > -    if (bs->device_name[0] != '\0') {
> > -        qapi_event_send_device_tray_moved(bdrv_get_device_name(bs),
> 
> > +    device_name = bdrv_get_device_name(bs);
> > +        qapi_event_send_device_tray_moved(device_name,
> >                                            eject_flag, &error_abort);
> >      }
> >  }
> > @@ -5469,7 +5441,8 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
> >          blocker = QLIST_FIRST(&bs->op_blockers[op]);
> >          if (errp) {
> >              error_setg(errp, "Device '%s' is busy: %s",
> > -                       bs->device_name, error_get_pretty(blocker->reason));
> > +                       bdrv_get_device_name(bs),
> > +                       error_get_pretty(blocker->reason));
> >          }
> >          return true;
> >      }
> > diff --git a/block/block-backend.c b/block/block-backend.c
> > index c0876fa..2f10d6a 100644
> > --- a/block/block-backend.c
> > +++ b/block/block-backend.c
> > @@ -67,17 +67,17 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp)
> >      BlockBackend *blk;
> >      BlockDriverState *bs;
> >  
> > +    if (bdrv_find_node(name)) {
> > +        error_setg(errp, "Device with node-name '%s' already exists", name);
> 
> Maybe the message written by the person who contributed the initial code (me) mislead you.
> I think the intent is good but the wording is wrong.
> node-name is associated with a regular BDS. A device cannot have a node name.
> 
> Maybe something in the vein of:
>         error_setg(errp, "Device name '%s' would conflict with the node-name of an existing block driver state", name);
> 
> > +        return NULL;
> > +    }
> > +

I re read the patch and saw you just moved it around.
Maybe a followup patch fixing the message would be a good idea.

> >      blk = blk_new(name, errp);
> >      if (!blk) {
> >          return NULL;
> >      }
> >  
> > -    bs = bdrv_new_named(name, errp);
> > -    if (!bs) {
> > -        blk_unref(blk);
> > -        return NULL;
> > -    }
> > -
> > +    bs = bdrv_new();
> >      blk_attach_bs(blk, bs);
> >      return blk;
> >  }
> > diff --git a/block/cow.c b/block/cow.c
> > index 6ee4833..dda1e17 100644
> > --- a/block/cow.c
> > +++ b/block/cow.c
> > @@ -84,7 +84,7 @@ static int cow_open(BlockDriverState *bs, QDict *options, int flags,
> >          snprintf(version, sizeof(version),
> >                 "COW version %" PRIu32, cow_header.version);
> >          error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> > -            bs->device_name, "cow", version);
> > +            bdrv_get_device_name(bs), "cow", version);
> >          ret = -ENOTSUP;
> >          goto fail;
> >      }
> > diff --git a/block/mirror.c b/block/mirror.c
> > index 18b18e0..829be2f 100644
> > --- a/block/mirror.c
> > +++ b/block/mirror.c
> > @@ -567,7 +567,8 @@ static void mirror_complete(BlockJob *job, Error **errp)
> >          return;
> >      }
> >      if (!s->synced) {
> > -        error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
> > +        error_set(errp, QERR_BLOCK_JOB_NOT_READY,
> > +                  bdrv_get_device_name(job->bs));
> >          return;
> >      }
> >  
> > diff --git a/block/qapi.c b/block/qapi.c
> > index 79d1e6a..cc8f711 100644
> > --- a/block/qapi.c
> > +++ b/block/qapi.c
> > @@ -272,7 +272,7 @@ void bdrv_query_info(BlockDriverState *bs,
> >      BlockDriverState *bs0;
> >      ImageInfo **p_image_info;
> >      Error *local_err = NULL;
> > -    info->device = g_strdup(bs->device_name);
> > +    info->device = g_strdup(bdrv_get_device_name(bs));
> >      info->type = g_strdup("unknown");
> >      info->locked = bdrv_dev_is_medium_locked(bs);
> >      info->removable = bdrv_dev_has_removable_media(bs);
> > @@ -327,9 +327,9 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs)
> >  
> >      s = g_malloc0(sizeof(*s));
> >  
> > -    if (bs->device_name[0]) {
> > +    if (bdrv_get_device_name(bs)[0]) {
> >          s->has_device = true;
> > -        s->device = g_strdup(bs->device_name);
> > +        s->device = g_strdup(bdrv_get_device_name(bs));
> >      }
> >  
> >      s->stats = g_malloc0(sizeof(*s->stats));
> > diff --git a/block/qcow.c b/block/qcow.c
> > index 67c237f..2d803ac 100644
> > --- a/block/qcow.c
> > +++ b/block/qcow.c
> > @@ -124,7 +124,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
> >          snprintf(version, sizeof(version), "QCOW version %" PRIu32,
> >                   header.version);
> >          error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> > -                  bs->device_name, "qcow", version);
> > +                  bdrv_get_device_name(bs), "qcow", version);
> >          ret = -ENOTSUP;
> >          goto fail;
> >      }
> > @@ -231,7 +231,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
> >      /* Disable migration when qcow images are used */
> >      error_set(&s->migration_blocker,
> >                QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> > -              "qcow", bs->device_name, "live migration");
> > +              "qcow", bdrv_get_device_name(bs), "live migration");
> >      migrate_add_blocker(s->migration_blocker);
> >  
> >      qemu_co_mutex_init(&s->lock);
> > diff --git a/block/qcow2.c b/block/qcow2.c
> > index f9e045f..0ab455e 100644
> > --- a/block/qcow2.c
> > +++ b/block/qcow2.c
> > @@ -203,8 +203,8 @@ static void GCC_FMT_ATTR(3, 4) report_unsupported(BlockDriverState *bs,
> >      vsnprintf(msg, sizeof(msg), fmt, ap);
> >      va_end(ap);
> >  
> > -    error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, bs->device_name, "qcow2",
> > -              msg);
> > +    error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> > +              bdrv_get_device_name(bs), "qcow2", msg);
> >  }
> >  
> >  static void report_unsupported_feature(BlockDriverState *bs,
> > diff --git a/block/qed.c b/block/qed.c
> > index ba395af..f20ffb3 100644
> > --- a/block/qed.c
> > +++ b/block/qed.c
> > @@ -422,7 +422,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
> >          snprintf(buf, sizeof(buf), "%" PRIx64,
> >              s->header.features & ~QED_FEATURE_MASK);
> >          error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> > -            bs->device_name, "QED", buf);
> > +            bdrv_get_device_name(bs), "QED", buf);
> >          return -ENOTSUP;
> >      }
> >      if (!qed_is_cluster_size_valid(s->header.cluster_size)) {
> > diff --git a/block/quorum.c b/block/quorum.c
> > index 093382e..f958269 100644
> > --- a/block/quorum.c
> > +++ b/block/quorum.c
> > @@ -227,8 +227,8 @@ static void quorum_report_bad(QuorumAIOCB *acb, char *node_name, int ret)
> >  
> >  static void quorum_report_failure(QuorumAIOCB *acb)
> >  {
> > -    const char *reference = acb->common.bs->device_name[0] ?
> > -                            acb->common.bs->device_name :
> > +    const char *reference = bdrv_get_device_name(acb->common.bs)[0] ?
> > +                            bdrv_get_device_name(acb->common.bs) :
> >                              acb->common.bs->node_name;
> >  
> >      qapi_event_send_quorum_failure(reference, acb->sector_num,
> > diff --git a/block/vdi.c b/block/vdi.c
> > index 4b10aac..2e6f31c 100644
> > --- a/block/vdi.c
> > +++ b/block/vdi.c
> > @@ -490,7 +490,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
> >      /* Disable migration when vdi images are used */
> >      error_set(&s->migration_blocker,
> >                QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> > -              "vdi", bs->device_name, "live migration");
> > +              "vdi", bdrv_get_device_name(bs), "live migration");
> >      migrate_add_blocker(s->migration_blocker);
> >  
> >      return 0;
> > diff --git a/block/vhdx.c b/block/vhdx.c
> > index 87c99fc..8bf1af1 100644
> > --- a/block/vhdx.c
> > +++ b/block/vhdx.c
> > @@ -1003,7 +1003,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
> >      /* Disable migration when VHDX images are used */
> >      error_set(&s->migration_blocker,
> >              QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> > -            "vhdx", bs->device_name, "live migration");
> > +            "vhdx", bdrv_get_device_name(bs), "live migration");
> >      migrate_add_blocker(s->migration_blocker);
> >  
> >      return 0;
> > diff --git a/block/vmdk.c b/block/vmdk.c
> > index a1cb911..7bc1474 100644
> > --- a/block/vmdk.c
> > +++ b/block/vmdk.c
> > @@ -657,7 +657,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
> >          snprintf(buf, sizeof(buf), "VMDK version %" PRId32,
> >                   le32_to_cpu(header.version));
> >          error_set(errp, QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
> > -                  bs->device_name, "vmdk", buf);
> > +                  bdrv_get_device_name(bs), "vmdk", buf);
> >          return -ENOTSUP;
> >      } else if (le32_to_cpu(header.version) == 3 && (flags & BDRV_O_RDWR)) {
> >          /* VMware KB 2064959 explains that version 3 added support for
> > @@ -939,7 +939,7 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
> >      /* Disable migration when VMDK images are used */
> >      error_set(&s->migration_blocker,
> >                QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> > -              "vmdk", bs->device_name, "live migration");
> > +              "vmdk", bdrv_get_device_name(bs), "live migration");
> >      migrate_add_blocker(s->migration_blocker);
> >      g_free(buf);
> >      return 0;
> > diff --git a/block/vpc.c b/block/vpc.c
> > index 055efc4..7bb90d5 100644
> > --- a/block/vpc.c
> > +++ b/block/vpc.c
> > @@ -320,7 +320,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
> >      /* Disable migration when VHD images are used */
> >      error_set(&s->migration_blocker,
> >                QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> > -              "vpc", bs->device_name, "live migration");
> > +              "vpc", bdrv_get_device_name(bs), "live migration");
> >      migrate_add_blocker(s->migration_blocker);
> >  
> >      return 0;
> > diff --git a/block/vvfat.c b/block/vvfat.c
> > index 6c9fde0..cefe3a4 100644
> > --- a/block/vvfat.c
> > +++ b/block/vvfat.c
> > @@ -1182,7 +1182,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
> >      if (s->qcow) {
> >          error_set(&s->migration_blocker,
> >                    QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
> > -                  "vvfat (rw)", bs->device_name, "live migration");
> > +                  "vvfat (rw)", bdrv_get_device_name(bs), "live migration");
> >          migrate_add_blocker(s->migration_blocker);
> >      }
> >  
> > diff --git a/blockjob.c b/blockjob.c
> > index 0689fdd..3af0f6c 100644
> > --- a/blockjob.c
> > +++ b/blockjob.c
> > @@ -107,7 +107,8 @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
> >  void block_job_complete(BlockJob *job, Error **errp)
> >  {
> >      if (job->paused || job->cancelled || !job->driver->complete) {
> > -        error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
> > +        error_set(errp, QERR_BLOCK_JOB_NOT_READY,
> > +                  bdrv_get_device_name(job->bs));
> >          return;
> >      }
> >  
> > diff --git a/include/block/block.h b/include/block/block.h
> > index 8cf9ea3..fb4fff9 100644
> > --- a/include/block/block.h
> > +++ b/include/block/block.h
> > @@ -203,7 +203,6 @@ BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
> >  int bdrv_create(BlockDriver *drv, const char* filename,
> >                  QemuOpts *opts, Error **errp);
> >  int bdrv_create_file(const char *filename, QemuOpts *opts, Error **errp);
> > -BlockDriverState *bdrv_new_named(const char *device_name, Error **errp);
> >  BlockDriverState *bdrv_new(void);
> >  void bdrv_make_anon(BlockDriverState *bs);
> >  void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old);
> > @@ -415,7 +414,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key);
> >  int bdrv_query_missing_keys(void);
> >  void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
> >                           void *opaque);
> > -const char *bdrv_get_device_name(BlockDriverState *bs);
> > +const char *bdrv_get_device_name(const BlockDriverState *bs);
> >  int bdrv_get_flags(BlockDriverState *bs);
> >  int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
> >                            const uint8_t *buf, int nb_sectors);
> > diff --git a/include/block/block_int.h b/include/block/block_int.h
> > index d5de08b..08ccb27 100644
> > --- a/include/block/block_int.h
> > +++ b/include/block/block_int.h
> > @@ -394,8 +394,6 @@ struct BlockDriverState {
> >      char node_name[32];
> >      /* element of the list of named nodes building the graph */
> >      QTAILQ_ENTRY(BlockDriverState) node_list;
> > -    /* Device name is the name associated with the "drive" the guest sees */
> > -    char device_name[32];
> >      QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
> >      int refcnt;
> >  
> > -- 
> > 1.9.3
> > 
> > 
> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-11 10:03     ` Markus Armbruster
@ 2014-09-11 11:45       ` Markus Armbruster
  2014-09-11 14:38       ` Markus Armbruster
  1 sibling, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 11:45 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: benoit.canet, famz, qemu-devel, stefanha

Markus Armbruster <armbru@redhat.com> writes:

> Kevin Wolf <kwolf@redhat.com> writes:
[...]
>>> diff --git a/qemu-img.c b/qemu-img.c
>>> index 4490a22..bad3f64 100644
>>> --- a/qemu-img.c
>>> +++ b/qemu-img.c
>>
>> Won't comment on each hunk in qemu-img, but in many cases, on
>> bdrv_new_open() failure, blk is leaked.
>
> I'll check them systematically.

The leaks all go away in PATCH 03.  Fixing PATCH 02 anyway, of course.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo() Markus Armbruster
@ 2014-09-11 12:07   ` Benoît Canet
  2014-09-11 19:20     ` Markus Armbruster
  2014-09-11 17:06   ` Benoît Canet
  1 sibling, 1 reply; 76+ messages in thread
From: Benoît Canet @ 2014-09-11 12:07 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:39 (+0200), Markus Armbruster wrote :
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  blockdev.c                               |  3 +--
>  hw/arm/collie.c                          |  9 +++++----
>  hw/arm/gumstix.c                         |  5 +++--
>  hw/arm/mainstone.c                       |  8 ++++----
>  hw/arm/musicpal.c                        | 11 ++++++-----
>  hw/arm/nseries.c                         |  6 ++++--
>  hw/arm/omap1.c                           |  4 +++-
>  hw/arm/omap2.c                           |  4 +++-
>  hw/arm/omap_sx1.c                        |  9 +++++----
>  hw/arm/pxa2xx.c                          |  7 +++++--
>  hw/arm/spitz.c                           |  4 +++-
>  hw/arm/versatilepb.c                     |  4 +++-
>  hw/arm/vexpress.c                        |  4 +++-
>  hw/arm/xilinx_zynq.c                     |  4 +++-
>  hw/arm/z2.c                              |  7 ++++---
>  hw/block/fdc.c                           | 16 +++++++++++-----
>  hw/block/m25p80.c                        |  5 +++--
>  hw/block/xen_disk.c                      |  2 +-
>  hw/cris/axis_dev88.c                     |  3 ++-
>  hw/display/tc6393xb.c                    |  4 +++-
>  hw/i386/pc_sysfw.c                       |  3 ++-
>  hw/ide/piix.c                            |  6 ++++--
>  hw/ide/qdev.c                            |  4 +++-
>  hw/isa/pc87312.c                         |  7 +++++--
>  hw/lm32/lm32_boards.c                    | 13 +++++++------
>  hw/lm32/milkymist.c                      |  7 ++++---
>  hw/microblaze/petalogix_ml605_mmu.c      |  5 +++--
>  hw/microblaze/petalogix_s3adsp1800_mmu.c |  5 +++--
>  hw/mips/mips_malta.c                     |  4 +++-
>  hw/mips/mips_r4k.c                       |  5 +++--
>  hw/pci/pci-hotplug-old.c                 |  9 ++++++---
>  hw/ppc/ppc405_boards.c                   | 25 ++++++++++++++++---------
>  hw/ppc/spapr.c                           |  4 +++-
>  hw/ppc/virtex_ml507.c                    |  5 +++--
>  hw/scsi/scsi-bus.c                       |  5 +++--
>  hw/sd/milkymist-memcard.c                |  7 +++++--
>  hw/sd/pl181.c                            |  3 ++-
>  hw/sd/sdhci.c                            |  3 ++-
>  hw/sd/ssi-sd.c                           |  3 ++-
>  hw/sh4/r2d.c                             |  5 +++--
>  hw/usb/dev-storage.c                     |  4 +++-
>  hw/xtensa/xtfpga.c                       |  4 +++-
>  include/sysemu/blockdev.h                |  1 -
>  43 files changed, 163 insertions(+), 93 deletions(-)
> 
> diff --git a/blockdev.c b/blockdev.c
> index 353563e..5c75abd 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -219,7 +219,7 @@ static void bdrv_format_print(void *opaque, const char *name)
>  
>  void drive_del(DriveInfo *dinfo)
>  {
> -    blk_unref(dinfo->bdrv->blk);
> +    blk_unref(blk_by_legacy_dinfo(dinfo));
>  }
>  
>  typedef struct {
> @@ -472,7 +472,6 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
>  
>      dinfo = g_malloc0(sizeof(*dinfo));
>      dinfo->id = g_strdup(qemu_opts_id(opts));
> -    dinfo->bdrv = bs;
>      blk_set_legacy_dinfo(blk, dinfo);
>  
>      if (!file || !*file) {
> diff --git a/hw/arm/collie.c b/hw/arm/collie.c
> index ed7851f..0247290 100644
> --- a/hw/arm/collie.c
> +++ b/hw/arm/collie.c
> @@ -15,6 +15,7 @@
>  #include "strongarm.h"
>  #include "hw/arm/arm.h"
>  #include "hw/block/flash.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  
> @@ -41,13 +42,13 @@ static void collie_init(MachineState *machine)
>  
>      dinfo = drive_get(IF_PFLASH, 0, 0);
>      pflash_cfi01_register(SA_CS0, NULL, "collie.fl1", 0x02000000,
> -                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
> -                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
> +                    dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                    (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
>  
>      dinfo = drive_get(IF_PFLASH, 0, 1);
>      pflash_cfi01_register(SA_CS1, NULL, "collie.fl2", 0x02000000,
> -                    dinfo ? dinfo->bdrv : NULL, (64 * 1024),
> -                    512, 4, 0x00, 0x00, 0x00, 0x00, 0);
> +                    dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                    (64 * 1024), 512, 4, 0x00, 0x00, 0x00, 0x00, 0);
>  
>      sysbus_create_simple("scoop", 0x40800000, NULL);
>  
> diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
> index 3f8465e..49f9339 100644
> --- a/hw/arm/gumstix.c
> +++ b/hw/arm/gumstix.c
> @@ -40,6 +40,7 @@
>  #include "hw/block/flash.h"
>  #include "hw/devices.h"
>  #include "hw/boards.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  #include "sysemu/qtest.h"
> @@ -71,7 +72,7 @@ static void connex_init(MachineState *machine)
>      be = 0;
>  #endif
>      if (!pflash_cfi01_register(0x00000000, NULL, "connext.rom", connex_rom,
> -                               dinfo ? dinfo->bdrv : NULL,
> +                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
>                                 sector_len, connex_rom / sector_len,
>                                 2, 0, 0, 0, 0, be)) {
>          fprintf(stderr, "qemu: Error registering flash memory.\n");
> @@ -109,7 +110,7 @@ static void verdex_init(MachineState *machine)
>      be = 0;
>  #endif
>      if (!pflash_cfi01_register(0x00000000, NULL, "verdex.rom", verdex_rom,
> -                               dinfo ? dinfo->bdrv : NULL,
> +                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
>                                 sector_len, verdex_rom / sector_len,
>                                 2, 0, 0, 0, 0, be)) {
>          fprintf(stderr, "qemu: Error registering flash memory.\n");
> diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
> index 44f1873..fb17d85 100644
> --- a/hw/arm/mainstone.c
> +++ b/hw/arm/mainstone.c
> @@ -18,7 +18,7 @@
>  #include "hw/devices.h"
>  #include "hw/boards.h"
>  #include "hw/block/flash.h"
> -#include "sysemu/blockdev.h"
> +#include "sysemu/block-backend.h"
>  #include "hw/sysbus.h"
>  #include "exec/address-spaces.h"
>  #include "sysemu/qtest.h"
> @@ -148,9 +148,9 @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
>          if (!pflash_cfi01_register(mainstone_flash_base[i], NULL,
>                                     i ? "mainstone.flash1" : "mainstone.flash0",
>                                     MAINSTONE_FLASH,
> -                                   dinfo->bdrv, sector_len,
> -                                   MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
> -                                   be)) {
> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
> +                                   sector_len, MAINSTONE_FLASH / sector_len,
> +                                   4, 0, 0, 0, 0, be)) {
>              fprintf(stderr, "qemu: Error registering flash memory.\n");
>              exit(1);
>          }
> diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
> index 6a134f2..6a41d9c 100644
> --- a/hw/arm/musicpal.c
> +++ b/hw/arm/musicpal.c
> @@ -22,6 +22,7 @@
>  #include "hw/block/flash.h"
>  #include "ui/console.h"
>  #include "hw/i2c/i2c.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  #include "ui/pixel_ops.h"
> @@ -1630,7 +1631,9 @@ static void musicpal_init(MachineState *machine)
>      /* Register flash */
>      dinfo = drive_get(IF_PFLASH, 0, 0);
>      if (dinfo) {
> -        flash_size = bdrv_getlength(dinfo->bdrv);
> +        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
> +
> +        flash_size = bdrv_getlength(bs);
>          if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
>              flash_size != 32*1024*1024) {
>              fprintf(stderr, "Invalid flash image size\n");
> @@ -1645,16 +1648,14 @@ static void musicpal_init(MachineState *machine)
>  #ifdef TARGET_WORDS_BIGENDIAN
>          pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
>                                "musicpal.flash", flash_size,
> -                              dinfo->bdrv, 0x10000,
> -                              (flash_size + 0xffff) >> 16,
> +                              bs, 0x10000, (flash_size + 0xffff) >> 16,
>                                MP_FLASH_SIZE_MAX / flash_size,
>                                2, 0x00BF, 0x236D, 0x0000, 0x0000,
>                                0x5555, 0x2AAA, 1);
>  #else
>          pflash_cfi02_register(0x100000000ULL-MP_FLASH_SIZE_MAX, NULL,
>                                "musicpal.flash", flash_size,
> -                              dinfo->bdrv, 0x10000,
> -                              (flash_size + 0xffff) >> 16,
> +                              bs, 0x10000, (flash_size + 0xffff) >> 16,
>                                MP_FLASH_SIZE_MAX / flash_size,
>                                2, 0x00BF, 0x236D, 0x0000, 0x0000,
>                                0x5555, 0x2AAA, 0);
> diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
> index 4f092d6..2536078 100644
> --- a/hw/arm/nseries.c
> +++ b/hw/arm/nseries.c
> @@ -31,6 +31,7 @@
>  #include "hw/hw.h"
>  #include "hw/bt.h"
>  #include "hw/loader.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/sysbus.h"
>  #include "exec/address-spaces.h"
> @@ -172,8 +173,9 @@ static void n8x0_nand_setup(struct n800_s *s)
>      qdev_prop_set_uint16(s->nand, "version_id", 0);
>      qdev_prop_set_int32(s->nand, "shift", 1);
>      dinfo = drive_get(IF_MTD, 0, 0);
> -    if (dinfo && dinfo->bdrv) {
> -        qdev_prop_set_drive_nofail(s->nand, "drive", dinfo->bdrv);
> +    if (dinfo) {
> +        qdev_prop_set_drive_nofail(s->nand, "drive",
> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
>      }
>      qdev_init_nofail(s->nand);
>      sysbus_connect_irq(SYS_BUS_DEVICE(s->nand), 0,
> diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
> index e7cc5d7..e38e07f 100644
> --- a/hw/arm/omap1.c
> +++ b/hw/arm/omap1.c
> @@ -21,6 +21,7 @@
>  #include "hw/arm/omap.h"
>  #include "sysemu/sysemu.h"
>  #include "hw/arm/soc_dma.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "qemu/range.h"
>  #include "hw/sysbus.h"
> @@ -3976,7 +3977,8 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory,
>          fprintf(stderr, "qemu: missing SecureDigital device\n");
>          exit(1);
>      }
> -    s->mmc = omap_mmc_init(0xfffb7800, system_memory, dinfo->bdrv,
> +    s->mmc = omap_mmc_init(0xfffb7800, system_memory,
> +                           blk_bs(blk_by_legacy_dinfo(dinfo)),
>                             qdev_get_gpio_in(s->ih[1], OMAP_INT_OQN),
>                             &s->drq[OMAP_DMA_MMC_TX],
>                      omap_findclk(s, "mmc_ck"));
> diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
> index dc53a7a..e47dd63 100644
> --- a/hw/arm/omap2.c
> +++ b/hw/arm/omap2.c
> @@ -18,6 +18,7 @@
>   * with this program; if not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/hw.h"
>  #include "hw/arm/arm.h"
> @@ -2459,7 +2460,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
>          fprintf(stderr, "qemu: missing SecureDigital device\n");
>          exit(1);
>      }
> -    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), dinfo->bdrv,
> +    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9),
> +                    blk_bs(blk_by_legacy_dinfo(dinfo)),
>                      qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
>                      &s->drq[OMAP24XX_DMA_MMC1_TX],
>                      omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
> diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
> index b4f6da6..f475afc 100644
> --- a/hw/arm/omap_sx1.c
> +++ b/hw/arm/omap_sx1.c
> @@ -31,6 +31,7 @@
>  #include "hw/boards.h"
>  #include "hw/arm/arm.h"
>  #include "hw/block/flash.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "sysemu/qtest.h"
>  #include "exec/address-spaces.h"
> @@ -153,8 +154,8 @@ static void sx1_init(MachineState *machine, const int version)
>      if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
>          if (!pflash_cfi01_register(OMAP_CS0_BASE, NULL,
>                                     "omap_sx1.flash0-1", flash_size,
> -                                   dinfo->bdrv, sector_size,
> -                                   flash_size / sector_size,
> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
> +                                   sector_size, flash_size / sector_size,
>                                     4, 0, 0, 0, 0, be)) {
>              fprintf(stderr, "qemu: Error registering flash memory %d.\n",
>                             fl_idx);
> @@ -176,8 +177,8 @@ static void sx1_init(MachineState *machine, const int version)
>  
>          if (!pflash_cfi01_register(OMAP_CS1_BASE, NULL,
>                                     "omap_sx1.flash1-1", flash1_size,
> -                                   dinfo->bdrv, sector_size,
> -                                   flash1_size / sector_size,
> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
> +                                   sector_size, flash1_size / sector_size,
>                                     4, 0, 0, 0, 0, be)) {
>              fprintf(stderr, "qemu: Error registering flash memory %d.\n",
>                             fl_idx);
> diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
> index 557e0f1..7ec0da8 100644
> --- a/hw/arm/pxa2xx.c
> +++ b/hw/arm/pxa2xx.c
> @@ -14,6 +14,7 @@
>  #include "hw/i2c/i2c.h"
>  #include "hw/ssi.h"
>  #include "sysemu/char.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  
>  static struct {
> @@ -2083,7 +2084,8 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
>          fprintf(stderr, "qemu: missing SecureDigital device\n");
>          exit(1);
>      }
> -    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
> +    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
> +                    blk_bs(blk_by_legacy_dinfo(dinfo)),
>                      qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
>                      qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
>                      qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
> @@ -2214,7 +2216,8 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
>          fprintf(stderr, "qemu: missing SecureDigital device\n");
>          exit(1);
>      }
> -    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000, dinfo->bdrv,
> +    s->mmc = pxa2xx_mmci_init(address_space, 0x41100000,
> +                    blk_bs(blk_by_legacy_dinfo(dinfo)),
>                      qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
>                      qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
>                      qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
> diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
> index 03cc6ce..5d684a2 100644
> --- a/hw/arm/spitz.c
> +++ b/hw/arm/spitz.c
> @@ -25,6 +25,7 @@
>  #include "block/block.h"
>  #include "audio/audio.h"
>  #include "hw/boards.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/sysbus.h"
>  #include "exec/address-spaces.h"
> @@ -170,7 +171,8 @@ static int sl_nand_init(SysBusDevice *dev)
>  
>      s->ctl = 0;
>      nand = drive_get(IF_MTD, 0, 0);
> -    s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
> +    s->nand = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,
> +                        s->manf_id, s->chip_id);
>  
>      memory_region_init_io(&s->iomem, OBJECT(s), &sl_ops, s, "sl", 0x40);
>      sysbus_init_mmio(dev, &s->iomem);
> diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
> index dea5fc7..c88be6b 100644
> --- a/hw/arm/versatilepb.c
> +++ b/hw/arm/versatilepb.c
> @@ -15,6 +15,7 @@
>  #include "hw/pci/pci.h"
>  #include "hw/i2c/i2c.h"
>  #include "hw/boards.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  #include "hw/block/flash.h"
> @@ -337,7 +338,8 @@ static void versatile_init(MachineState *machine, int board_id)
>  
>      dinfo = drive_get(IF_PFLASH, 0, 0);
>      if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, NULL, "versatile.flash",
> -                          VERSATILE_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL,
> +                          VERSATILE_FLASH_SIZE,
> +                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
>                            VERSATILE_FLASH_SECT_SIZE,
>                            VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE,
>                            4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
> diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
> index a88732c..a492c22 100644
> --- a/hw/arm/vexpress.c
> +++ b/hw/arm/vexpress.c
> @@ -30,6 +30,7 @@
>  #include "hw/boards.h"
>  #include "hw/loader.h"
>  #include "exec/address-spaces.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/block/flash.h"
>  #include "sysemu/device_tree.h"
> @@ -488,7 +489,8 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
>  {
>      DeviceState *dev = qdev_create(NULL, "cfi.pflash01");
>  
> -    if (di && qdev_prop_set_drive(dev, "drive", di->bdrv)) {
> +    if (di && qdev_prop_set_drive(dev, "drive",
> +                                  blk_bs(blk_by_legacy_dinfo(di)))) {
>          abort();
>      }
>  
> diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
> index ba5aa82..78e6934 100644
> --- a/hw/arm/xilinx_zynq.c
> +++ b/hw/arm/xilinx_zynq.c
> @@ -22,6 +22,7 @@
>  #include "sysemu/sysemu.h"
>  #include "hw/boards.h"
>  #include "hw/block/flash.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/loader.h"
>  #include "hw/ssi.h"
> @@ -162,7 +163,8 @@ static void zynq_init(MachineState *machine)
>  
>      /* AMD */
>      pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
> -                          dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE,
> +                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                          FLASH_SECTOR_SIZE,
>                            FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
>                            1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
>                                0);
> diff --git a/hw/arm/z2.c b/hw/arm/z2.c
> index 36b3b50..9b38a2b 100644
> --- a/hw/arm/z2.c
> +++ b/hw/arm/z2.c
> @@ -20,6 +20,7 @@
>  #include "hw/boards.h"
>  #include "sysemu/sysemu.h"
>  #include "hw/block/flash.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "ui/console.h"
>  #include "audio/audio.h"
> @@ -336,9 +337,9 @@ static void z2_init(MachineState *machine)
>  
>      if (!pflash_cfi01_register(Z2_FLASH_BASE,
>                                 NULL, "z2.flash0", Z2_FLASH_SIZE,
> -                               dinfo ? dinfo->bdrv : NULL, sector_len,
> -                               Z2_FLASH_SIZE / sector_len, 4, 0, 0, 0, 0,
> -                               be)) {
> +                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                               sector_len, Z2_FLASH_SIZE / sector_len,
> +                               4, 0, 0, 0, 0, be)) {
>          fprintf(stderr, "qemu: Error registering flash memory.\n");
>          exit(1);
>      }
> diff --git a/hw/block/fdc.c b/hw/block/fdc.c
> index 490d127..19f215f 100644
> --- a/hw/block/fdc.c
> +++ b/hw/block/fdc.c
> @@ -33,6 +33,7 @@
>  #include "qemu/timer.h"
>  #include "hw/isa/isa.h"
>  #include "hw/sysbus.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "sysemu/sysemu.h"
>  #include "qemu/log.h"
> @@ -2033,10 +2034,12 @@ ISADevice *fdctrl_init_isa(ISABus *bus, DriveInfo **fds)
>      dev = DEVICE(isadev);
>  
>      if (fds[0]) {
> -        qdev_prop_set_drive_nofail(dev, "driveA", fds[0]->bdrv);
> +        qdev_prop_set_drive_nofail(dev, "driveA",
> +                                   blk_bs(blk_by_legacy_dinfo(fds[0])));
>      }
>      if (fds[1]) {
> -        qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv);
> +        qdev_prop_set_drive_nofail(dev, "driveB",
> +                                   blk_bs(blk_by_legacy_dinfo(fds[1])));
>      }
>      qdev_init_nofail(dev);
>  
> @@ -2056,10 +2059,12 @@ void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
>      fdctrl = &sys->state;
>      fdctrl->dma_chann = dma_chann; /* FIXME */
>      if (fds[0]) {
> -        qdev_prop_set_drive_nofail(dev, "driveA", fds[0]->bdrv);
> +        qdev_prop_set_drive_nofail(dev, "driveA",
> +                                   blk_bs(blk_by_legacy_dinfo(fds[0])));
>      }
>      if (fds[1]) {
> -        qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv);
> +        qdev_prop_set_drive_nofail(dev, "driveB",
> +                                   blk_bs(blk_by_legacy_dinfo(fds[1])));
>      }
>      qdev_init_nofail(dev);
>      sbd = SYS_BUS_DEVICE(dev);
> @@ -2075,7 +2080,8 @@ void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
>  
>      dev = qdev_create(NULL, "SUNW,fdtwo");
>      if (fds[0]) {
> -        qdev_prop_set_drive_nofail(dev, "drive", fds[0]->bdrv);
> +        qdev_prop_set_drive_nofail(dev, "drive",
> +                                   blk_bs(blk_by_legacy_dinfo(fds[0])));
>      }
>      qdev_init_nofail(dev);
>      sys = SYSBUS_FDC(dev);
> diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
> index 5893773..78280a8 100644
> --- a/hw/block/m25p80.c
> +++ b/hw/block/m25p80.c
> @@ -22,6 +22,7 @@
>   */
>  
>  #include "hw/hw.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/ssi.h"
>  
> @@ -624,9 +625,9 @@ static int m25p80_init(SSISlave *ss)
>  
>      dinfo = drive_get_next(IF_MTD);
>  
> -    if (dinfo && dinfo->bdrv) {
> +    if (dinfo) {
>          DB_PRINT_L(0, "Binding to IF_MTD drive\n");
> -        s->bdrv = dinfo->bdrv;
> +        s->bdrv = blk_bs(blk_by_legacy_dinfo(dinfo));
>  
>          /* FIXME: Move to late init */
>          if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size,
> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
> index 6d474b9..b571bbe 100644
> --- a/hw/block/xen_disk.c
> +++ b/hw/block/xen_disk.c
> @@ -877,7 +877,7 @@ static int blk_connect(struct XenDevice *xendev)
>      } else {
>          /* setup via qemu cmdline -> already setup for us */
>          xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline setup)\n");
> -        blkdev->bs = blkdev->dinfo->bdrv;
> +        blkdev->bs = blk_bs(blk_by_legacy_dinfo(blkdev->dinfo));
>          if (bdrv_is_read_only(blkdev->bs) && !readonly) {
>              xen_be_printf(&blkdev->xendev, 0, "Unexpected read-only drive");
>              blkdev->bs = NULL;
> diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c
> index 1849338..280722d 100644
> --- a/hw/cris/axis_dev88.c
> +++ b/hw/cris/axis_dev88.c
> @@ -30,6 +30,7 @@
>  #include "hw/loader.h"
>  #include "elf.h"
>  #include "boot.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  #include "sysemu/qtest.h"
> @@ -282,7 +283,7 @@ void axisdev88_init(MachineState *machine)
>  
>        /* Attach a NAND flash to CS1.  */
>      nand = drive_get(IF_MTD, 0, 0);
> -    nand_state.nand = nand_init(nand ? nand->bdrv : NULL,
> +    nand_state.nand = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,
>                                  NAND_MFR_STMICRO, 0x39);
>      memory_region_init_io(&nand_state.iomem, NULL, &nand_ops, &nand_state,
>                            "nand", 0x05000000);
> diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
> index f4011d2..62d6663 100644
> --- a/hw/display/tc6393xb.c
> +++ b/hw/display/tc6393xb.c
> @@ -15,6 +15,7 @@
>  #include "hw/block/flash.h"
>  #include "ui/console.h"
>  #include "ui/pixel_ops.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  
>  #define IRQ_TC6393_NAND		0
> @@ -576,7 +577,8 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq)
>      s->sub_irqs = qemu_allocate_irqs(tc6393xb_sub_irq, s, TC6393XB_NR_IRQS);
>  
>      nand = drive_get(IF_MTD, 0, 0);
> -    s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76);
> +    s->flash = nand_init(nand ? blk_bs(blk_by_legacy_dinfo(nand)) : NULL,
> +                         NAND_MFR_TOSHIBA, 0x76);
>  
>      memory_region_init_io(&s->iomem, NULL, &tc6393xb_ops, s, "tc6393xb", 0x10000);
>      memory_region_add_subregion(sysmem, base, &s->iomem);
> diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
> index 75a7ebb..6cd264a 100644
> --- a/hw/i386/pc_sysfw.c
> +++ b/hw/i386/pc_sysfw.c
> @@ -23,6 +23,7 @@
>   * THE SOFTWARE.
>   */
>  
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "qemu/error-report.h"
>  #include "hw/sysbus.h"
> @@ -118,7 +119,7 @@ static void pc_system_flash_init(MemoryRegion *rom_memory)
>           (unit < FLASH_MAP_UNIT_MAX &&
>            (pflash_drv = drive_get(IF_PFLASH, 0, unit)) != NULL);
>           ++unit) {
> -        bdrv = pflash_drv->bdrv;
> +        bdrv = blk_bs(blk_by_legacy_dinfo(pflash_drv));
>          size = bdrv_getlength(bdrv);
>          if (size < 0) {
>              fatal_errmsg = g_strdup_printf("failed to get backing file size");
> diff --git a/hw/ide/piix.c b/hw/ide/piix.c
> index 49e78a7..c6c256f 100644
> --- a/hw/ide/piix.c
> +++ b/hw/ide/piix.c
> @@ -27,6 +27,7 @@
>  #include <hw/i386/pc.h>
>  #include <hw/pci/pci.h>
>  #include <hw/isa/isa.h>
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "sysemu/sysemu.h"
>  #include "sysemu/dma.h"
> @@ -178,9 +179,10 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
>      for (; i < 3; i++) {
>          di = drive_get_by_index(IF_IDE, i);
>          if (di != NULL && !di->media_cd) {
> -            DeviceState *ds = bdrv_get_attached_dev(di->bdrv);
> +            BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(di));
> +            DeviceState *ds = bdrv_get_attached_dev(bs);
>              if (ds) {
> -                bdrv_detach_dev(di->bdrv, ds);
> +                bdrv_detach_dev(bs, ds);
>              }
>              pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
>              drive_del(di);
> diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
> index efab95b..75e8eb3 100644
> --- a/hw/ide/qdev.c
> +++ b/hw/ide/qdev.c
> @@ -20,6 +20,7 @@
>  #include "sysemu/dma.h"
>  #include "qemu/error-report.h"
>  #include <hw/ide/internal.h>
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/block/block.h"
>  #include "sysemu/sysemu.h"
> @@ -116,7 +117,8 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
>  
>      dev = qdev_create(&bus->qbus, drive->media_cd ? "ide-cd" : "ide-hd");
>      qdev_prop_set_uint32(dev, "unit", unit);
> -    qdev_prop_set_drive_nofail(dev, "drive", drive->bdrv);
> +    qdev_prop_set_drive_nofail(dev, "drive",
> +                               blk_bs(blk_by_legacy_dinfo(drive)));
>      qdev_init_nofail(dev);
>      return DO_UPCAST(IDEDevice, qdev, dev);
>  }
> diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c
> index 9327c53..b691a0c 100644
> --- a/hw/isa/pc87312.c
> +++ b/hw/isa/pc87312.c
> @@ -25,6 +25,7 @@
>  
>  #include "hw/isa/pc87312.h"
>  #include "qemu/error-report.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "sysemu/sysemu.h"
>  #include "sysemu/char.h"
> @@ -320,11 +321,13 @@ static void pc87312_realize(DeviceState *dev, Error **errp)
>          qdev_prop_set_uint32(d, "irq", 6);
>          drive = drive_get(IF_FLOPPY, 0, 0);
>          if (drive != NULL) {
> -            qdev_prop_set_drive_nofail(d, "driveA", drive->bdrv);
> +            qdev_prop_set_drive_nofail(d, "driveA",
> +                                       blk_bs(blk_by_legacy_dinfo(drive)));
>          }
>          drive = drive_get(IF_FLOPPY, 0, 1);
>          if (drive != NULL) {
> -            qdev_prop_set_drive_nofail(d, "driveB", drive->bdrv);
> +            qdev_prop_set_drive_nofail(d, "driveB",
> +                                       blk_bs(blk_by_legacy_dinfo(drive)));
>          }
>          qdev_init_nofail(d);
>          s->fdc.dev = isa;
> diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c
> index 0e01340..17c5610 100644
> --- a/hw/lm32/lm32_boards.c
> +++ b/hw/lm32/lm32_boards.c
> @@ -23,6 +23,7 @@
>  #include "hw/devices.h"
>  #include "hw/boards.h"
>  #include "hw/loader.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "elf.h"
>  #include "lm32_hwsetup.h"
> @@ -118,9 +119,9 @@ static void lm32_evr_init(MachineState *machine)
>      dinfo = drive_get(IF_PFLASH, 0, 0);
>      /* Spansion S29NS128P */
>      pflash_cfi02_register(flash_base, NULL, "lm32_evr.flash", flash_size,
> -                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
> -                          flash_size / flash_sector_size, 1, 2,
> -                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
> +                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                          flash_sector_size, flash_size / flash_sector_size,
> +                          1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
>  
>      /* create irq lines */
>      cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1);
> @@ -220,9 +221,9 @@ static void lm32_uclinux_init(MachineState *machine)
>      dinfo = drive_get(IF_PFLASH, 0, 0);
>      /* Spansion S29NS128P */
>      pflash_cfi02_register(flash_base, NULL, "lm32_uclinux.flash", flash_size,
> -                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
> -                          flash_size / flash_sector_size, 1, 2,
> -                          0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
> +                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                          flash_sector_size, flash_size / flash_sector_size,
> +                          1, 2, 0x01, 0x7e, 0x43, 0x00, 0x555, 0x2aa, 1);
>  
>      /* create irq lines */
>      cpu_irq = qemu_allocate_irqs(cpu_irq_handler, env, 1);
> diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
> index 81c3933..904b9c0 100644
> --- a/hw/lm32/milkymist.c
> +++ b/hw/lm32/milkymist.c
> @@ -26,6 +26,7 @@
>  #include "hw/boards.h"
>  #include "hw/loader.h"
>  #include "elf.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "milkymist-hw.h"
>  #include "lm32.h"
> @@ -125,9 +126,9 @@ milkymist_init(MachineState *machine)
>      dinfo = drive_get(IF_PFLASH, 0, 0);
>      /* Numonyx JS28F256J3F105 */
>      pflash_cfi01_register(flash_base, NULL, "milkymist.flash", flash_size,
> -                          dinfo ? dinfo->bdrv : NULL, flash_sector_size,
> -                          flash_size / flash_sector_size, 2,
> -                          0x00, 0x89, 0x00, 0x1d, 1);
> +                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                          flash_sector_size, flash_size / flash_sector_size,
> +                          2, 0x00, 0x89, 0x00, 0x1d, 1);
>  
>      /* create irq lines */
>      cpu_irq = qemu_allocate_irqs(cpu_irq_handler, cpu, 1);
> diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
> index 6843abf..2974791 100644
> --- a/hw/microblaze/petalogix_ml605_mmu.c
> +++ b/hw/microblaze/petalogix_ml605_mmu.c
> @@ -32,6 +32,7 @@
>  #include "sysemu/sysemu.h"
>  #include "hw/devices.h"
>  #include "hw/boards.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/char/serial.h"
>  #include "exec/address-spaces.h"
> @@ -112,8 +113,8 @@ petalogix_ml605_init(MachineState *machine)
>       * 10th paremeter 0 means little-endian */
>      pflash_cfi01_register(FLASH_BASEADDR,
>                            NULL, "petalogix_ml605.flash", FLASH_SIZE,
> -                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
> -                          FLASH_SIZE >> 16,
> +                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                          (64 * 1024), FLASH_SIZE >> 16,
>                            2, 0x89, 0x18, 0x0000, 0x0, 0);
>  
>  
> diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
> index 49dc6d1..a69301f 100644
> --- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
> +++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
> @@ -30,6 +30,7 @@
>  #include "sysemu/sysemu.h"
>  #include "hw/devices.h"
>  #include "hw/boards.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  
> @@ -92,8 +93,8 @@ petalogix_s3adsp1800_init(MachineState *machine)
>      dinfo = drive_get(IF_PFLASH, 0, 0);
>      pflash_cfi01_register(FLASH_BASEADDR,
>                            NULL, "petalogix_s3adsp1800.flash", FLASH_SIZE,
> -                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
> -                          FLASH_SIZE >> 16,
> +                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                          (64 * 1024), FLASH_SIZE >> 16,
>                            1, 0x89, 0x18, 0x0000, 0x0, 1);
>  
>      dev = qdev_create(NULL, "xlnx.xps-intc");
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index cfb60af..9f84ad6 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -44,6 +44,7 @@
>  #include "elf.h"
>  #include "hw/timer/mc146818rtc.h"
>  #include "hw/timer/i8254.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  #include "hw/sysbus.h"             /* SysBusDevice */
> @@ -1035,7 +1036,8 @@ void mips_malta_init(MachineState *machine)
>      }
>  #endif
>      fl = pflash_cfi01_register(FLASH_ADDRESS, NULL, "mips_malta.bios",
> -                               BIOS_SIZE, dinfo ? dinfo->bdrv : NULL,
> +                               BIOS_SIZE,
> +                               dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
>                                 65536, fl_sectors,
>                                 4, 0x0000, 0x0000, 0x0000, 0x0000, be);
>      bios = pflash_cfi01_get_memory(fl);
> diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
> index 7120293..6fd69b9 100644
> --- a/hw/mips/mips_r4k.c
> +++ b/hw/mips/mips_r4k.c
> @@ -24,6 +24,7 @@
>  #include "elf.h"
>  #include "hw/timer/mc146818rtc.h"
>  #include "hw/timer/i8254.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  #include "sysemu/qtest.h"
> @@ -240,8 +241,8 @@ void mips_r4k_init(MachineState *machine)
>      } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
>          uint32_t mips_rom = 0x00400000;
>          if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
> -                                   dinfo->bdrv, sector_len,
> -                                   mips_rom / sector_len,
> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)),
> +                                   sector_len, mips_rom / sector_len,
>                                     4, 0, 0, 0, 0, be)) {
>              fprintf(stderr, "qemu: Error registering flash memory.\n");
>  	}
> diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c
> index cf2caeb..e4d51de 100644
> --- a/hw/pci/pci-hotplug-old.c
> +++ b/hw/pci/pci-hotplug-old.c
> @@ -33,6 +33,7 @@
>  #include "hw/scsi/scsi.h"
>  #include "hw/virtio/virtio-blk.h"
>  #include "qemu/config-file.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "qapi/error.h"
>  
> @@ -126,8 +127,9 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
>       */
>      dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
>      dinfo->bus = scsibus->busnr;
> -    scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
> -                                        false, -1, NULL, NULL);
> +    scsidev = scsi_bus_legacy_add_drive(scsibus,
> +                                        blk_bs(blk_by_legacy_dinfo(dinfo)),
> +                                        dinfo->unit, false, -1, NULL, NULL);
>      if (!scsidev) {
>          return -1;
>      }
> @@ -247,7 +249,8 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
>              return NULL;
>          }
>          dev = pci_create(bus, devfn, "virtio-blk-pci");
> -        if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
> +        if (qdev_prop_set_drive(&dev->qdev, "drive",
> +                                blk_bs(blk_by_legacy_dinfo(dinfo))) < 0) {
>              object_unparent(OBJECT(dev));
>              dev = NULL;
>              break;
> diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
> index 11d3379..7ff5ee5 100644
> --- a/hw/ppc/ppc405_boards.c
> +++ b/hw/ppc/ppc405_boards.c
> @@ -33,6 +33,7 @@
>  #include "qemu/log.h"
>  #include "qemu/error-report.h"
>  #include "hw/loader.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  
> @@ -225,17 +226,19 @@ static void ref405ep_init(MachineState *machine)
>  #ifdef USE_FLASH_BIOS
>      dinfo = drive_get(IF_PFLASH, 0, fl_idx);
>      if (dinfo) {
> -        bios_size = bdrv_getlength(dinfo->bdrv);
> +        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
> +
> +        bios_size = bdrv_getlength(bs);
>          fl_sectors = (bios_size + 65535) >> 16;
>  #ifdef DEBUG_BOARD_INIT
>          printf("Register parallel flash %d size %lx"
>                 " at addr %lx '%s' %d\n",
>                 fl_idx, bios_size, -bios_size,
> -               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
> +               bdrv_get_device_name(bs), fl_sectors);
>  #endif
>          pflash_cfi02_register((uint32_t)(-bios_size),
>                                NULL, "ef405ep.bios", bios_size,
> -                              dinfo->bdrv, 65536, fl_sectors, 1,
> +                              bs, 65536, fl_sectors, 1,
>                                2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
>                                1);
>          fl_idx++;
> @@ -547,7 +550,9 @@ static void taihu_405ep_init(MachineState *machine)
>  #if defined(USE_FLASH_BIOS)
>      dinfo = drive_get(IF_PFLASH, 0, fl_idx);
>      if (dinfo) {
> -        bios_size = bdrv_getlength(dinfo->bdrv);
> +        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
> +
> +        bios_size = bdrv_getlength(bs);
>          /* XXX: should check that size is 2MB */
>          //        bios_size = 2 * 1024 * 1024;
>          fl_sectors = (bios_size + 65535) >> 16;
> @@ -555,11 +560,11 @@ static void taihu_405ep_init(MachineState *machine)
>          printf("Register parallel flash %d size %lx"
>                 " at addr %lx '%s' %d\n",
>                 fl_idx, bios_size, -bios_size,
> -               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
> +               bdrv_get_device_name(bs), fl_sectors);
>  #endif
>          pflash_cfi02_register((uint32_t)(-bios_size),
>                                NULL, "taihu_405ep.bios", bios_size,
> -                              dinfo->bdrv, 65536, fl_sectors, 1,
> +                              bs, 65536, fl_sectors, 1,
>                                4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
>                                1);
>          fl_idx++;
> @@ -593,7 +598,9 @@ static void taihu_405ep_init(MachineState *machine)
>      /* Register Linux flash */
>      dinfo = drive_get(IF_PFLASH, 0, fl_idx);
>      if (dinfo) {
> -        bios_size = bdrv_getlength(dinfo->bdrv);
> +        BlockDriverState *bs = blk_bs(blk_by_legacy_dinfo(dinfo));
> +
> +        bios_size = bdrv_getlength(bs);
>          /* XXX: should check that size is 32MB */
>          bios_size = 32 * 1024 * 1024;
>          fl_sectors = (bios_size + 65535) >> 16;
> @@ -601,10 +608,10 @@ static void taihu_405ep_init(MachineState *machine)
>          printf("Register parallel flash %d size %lx"
>                 " at addr " TARGET_FMT_lx " '%s'\n",
>                 fl_idx, bios_size, (target_ulong)0xfc000000,
> -               bdrv_get_device_name(dinfo->bdrv));
> +               bdrv_get_device_name(bs));
>  #endif
>          pflash_cfi02_register(0xfc000000, NULL, "taihu_405ep.flash", bios_size,
> -                              dinfo->bdrv, 65536, fl_sectors, 1,
> +                              bs, 65536, fl_sectors, 1,
>                                4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA,
>                                1);
>          fl_idx++;
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 2ab4460..a577812 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -29,6 +29,7 @@
>  #include "hw/fw-path-provider.h"
>  #include "elf.h"
>  #include "net/net.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "sysemu/cpus.h"
>  #include "sysemu/kvm.h"
> @@ -925,7 +926,8 @@ static void spapr_create_nvram(sPAPREnvironment *spapr)
>      DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
>  
>      if (dinfo) {
> -        qdev_prop_set_drive_nofail(dev, "drive", dinfo->bdrv);
> +        qdev_prop_set_drive_nofail(dev, "drive",
> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
>      }
>  
>      qdev_init_nofail(dev);
> diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
> index 0de5148..a0ce447 100644
> --- a/hw/ppc/virtex_ml507.c
> +++ b/hw/ppc/virtex_ml507.c
> @@ -39,6 +39,7 @@
>  #include "hw/ppc/ppc4xx.h"
>  #include "ppc405.h"
>  
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "qapi/qmp/qerror.h"
>  
> @@ -227,8 +228,8 @@ static void virtex_init(MachineState *machine)
>  
>      dinfo = drive_get(IF_PFLASH, 0, 0);
>      pflash_cfi01_register(PFLASH_BASEADDR, NULL, "virtex.flash", FLASH_SIZE,
> -                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
> -                          FLASH_SIZE >> 16,
> +                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                          (64 * 1024), FLASH_SIZE >> 16,
>                            1, 0x89, 0x18, 0x0000, 0x0, 1);
>  
>      cpu_irq = (qemu_irq *) &env->irq_inputs[PPC40x_INPUT_INT];
> diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
> index 954c607..f5156ae 100644
> --- a/hw/scsi/scsi-bus.c
> +++ b/hw/scsi/scsi-bus.c
> @@ -3,6 +3,7 @@
>  #include "hw/scsi/scsi.h"
>  #include "block/scsi.h"
>  #include "hw/qdev.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "trace.h"
>  #include "sysemu/dma.h"
> @@ -267,8 +268,8 @@ void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, Error **errp)
>              continue;
>          }
>          qemu_opts_loc_restore(dinfo->opts);
> -        scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL,
> -                                  &err);
> +        scsi_bus_legacy_add_drive(bus, blk_bs(blk_by_legacy_dinfo(dinfo)),
> +                                  unit, false, -1, NULL, &err);
>          if (err != NULL) {
>              error_report("%s", error_get_pretty(err));
>              error_propagate(errp, err);
> diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
> index 2a40f92..501aa3a 100644
> --- a/hw/sd/milkymist-memcard.c
> +++ b/hw/sd/milkymist-memcard.c
> @@ -26,6 +26,7 @@
>  #include "sysemu/sysemu.h"
>  #include "trace.h"
>  #include "qemu/error-report.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/sd.h"
>  
> @@ -252,14 +253,16 @@ static int milkymist_memcard_init(SysBusDevice *dev)
>  {
>      MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
>      DriveInfo *dinfo;
> +    BlockDriverState *bs;
>  
>      dinfo = drive_get_next(IF_SD);
> -    s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false);
> +    bs = dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL;
> +    s->card = sd_init(bs, false);
>      if (s->card == NULL) {
>          return -1;
>      }
>  
> -    s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0;
> +    s->enabled = bs && bdrv_is_inserted(bs);
>  
>      memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s,
>              "milkymist-memcard", R_MAX * 4);
> diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
> index 462558b..0501d40 100644
> --- a/hw/sd/pl181.c
> +++ b/hw/sd/pl181.c
> @@ -7,6 +7,7 @@
>   * This code is licensed under the GPL.
>   */
>  
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/sysbus.h"
>  #include "hw/sd.h"
> @@ -490,7 +491,7 @@ static int pl181_init(SysBusDevice *sbd)
>      sysbus_init_irq(sbd, &s->irq[1]);
>      qdev_init_gpio_out(dev, s->cardstatus, 2);
>      dinfo = drive_get_next(IF_SD);
> -    s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false);
> +    s->card = sd_init(dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL, false);
>      if (s->card == NULL) {
>          return -1;
>      }
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index f9fe700..0b7d754 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -23,6 +23,7 @@
>   */
>  
>  #include "hw/hw.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "sysemu/dma.h"
>  #include "qemu/timer.h"
> @@ -1165,7 +1166,7 @@ static void sdhci_initfn(Object *obj)
>      DriveInfo *di;
>  
>      di = drive_get_next(IF_SD);
> -    s->card = sd_init(di ? di->bdrv : NULL, false);
> +    s->card = sd_init(di ? blk_bs(blk_by_legacy_dinfo(di)) : NULL, false);
>      if (s->card == NULL) {
>          exit(1);
>      }
> diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c
> index b012e57..6ae99e4 100644
> --- a/hw/sd/ssi-sd.c
> +++ b/hw/sd/ssi-sd.c
> @@ -10,6 +10,7 @@
>   * GNU GPL, version 2 or (at your option) any later version.
>   */
>  
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "hw/ssi.h"
>  #include "hw/sd.h"
> @@ -255,7 +256,7 @@ static int ssi_sd_init(SSISlave *d)
>  
>      s->mode = SSI_SD_CMD;
>      dinfo = drive_get_next(IF_SD);
> -    s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, true);
> +    s->sd = sd_init(dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL, true);
>      if (s->sd == NULL) {
>          return -1;
>      }
> diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
> index 95c0246..d652619 100644
> --- a/hw/sh4/r2d.c
> +++ b/hw/sh4/r2d.c
> @@ -36,6 +36,7 @@
>  #include "hw/loader.h"
>  #include "hw/usb.h"
>  #include "hw/block/flash.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "exec/address-spaces.h"
>  
> @@ -290,8 +291,8 @@ static void r2d_init(MachineState *machine)
>      /* onboard flash memory */
>      dinfo = drive_get(IF_PFLASH, 0, 0);
>      pflash_cfi02_register(0x0, NULL, "r2d.flash", FLASH_SIZE,
> -                          dinfo ? dinfo->bdrv : NULL, (16 * 1024),
> -                          FLASH_SIZE >> 16,
> +                          dinfo ? blk_bs(blk_by_legacy_dinfo(dinfo)) : NULL,
> +                          (16 * 1024), FLASH_SIZE >> 16,
>                            1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
>                            0x555, 0x2aa, 0);
>  
> diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
> index ae4efcb..525f657 100644
> --- a/hw/usb/dev-storage.c
> +++ b/hw/usb/dev-storage.c
> @@ -16,6 +16,7 @@
>  #include "ui/console.h"
>  #include "monitor/monitor.h"
>  #include "sysemu/sysemu.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  
>  //#define DEBUG_MSD
> @@ -702,7 +703,8 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
>      if (!dev) {
>          return NULL;
>      }
> -    if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) {
> +    if (qdev_prop_set_drive(&dev->qdev, "drive",
> +                            blk_bs(blk_by_legacy_dinfo(dinfo))) < 0) {
>          object_unparent(OBJECT(dev));
>          return NULL;
>      }
> diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
> index a2dff5a..7c4719e 100644
> --- a/hw/xtensa/xtfpga.c
> +++ b/hw/xtensa/xtfpga.c
> @@ -35,6 +35,7 @@
>  #include "net/net.h"
>  #include "hw/sysbus.h"
>  #include "hw/block/flash.h"
> +#include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "sysemu/char.h"
>  #include "sysemu/device_tree.h"
> @@ -229,7 +230,8 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
>      if (dinfo) {
>          flash = pflash_cfi01_register(board->flash_base,
>                  NULL, "lx60.io.flash", board->flash_size,
> -                dinfo->bdrv, board->flash_sector_size,
> +                blk_bs(blk_by_legacy_dinfo(dinfo)),
> +                board->flash_sector_size,
>                  board->flash_size / board->flash_sector_size,
>                  4, 0x0000, 0x0000, 0x0000, 0x0000, be);
>          if (flash == NULL) {
> diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
> index 2ed297b..75f6ac6 100644
> --- a/include/sysemu/blockdev.h
> +++ b/include/sysemu/blockdev.h
> @@ -30,7 +30,6 @@ typedef enum {
>  } BlockInterfaceType;
>  
>  struct DriveInfo {
> -    BlockDriverState *bdrv;
>      char *id;
>      const char *devaddr;
>      BlockInterfaceType type;
> -- 
> 1.9.3
> 

I have trouble to review this as I don't understand the qdevs parts.
Maybe someone else could have a look at it.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] block: Rename BlockDriverAIOCB* to BlockAIOCB*
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 11/23] block: Rename BlockDriverAIOCB* to BlockAIOCB* Markus Armbruster
@ 2014-09-11 12:15   ` Benoît Canet
  2014-09-11 19:23     ` Markus Armbruster
  0 siblings, 1 reply; 76+ messages in thread
From: Benoît Canet @ 2014-09-11 12:15 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

The Wednesday 10 Sep 2014 à 10:13:40 (+0200), Markus Armbruster wrote :
> I'll use BlockDriverAIOCB with block backends shortly, and the name is
> going to fit badly there.  It's a block layer thing anyway, not just a
> block driver thing.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> ---
>  block-migration.c           |   2 +-
>  block.c                     | 151 ++++++++++++++++++++++----------------------
>  block/archipelago.c         |  30 ++++-----
>  block/backup.c              |   2 +-
>  block/blkdebug.c            |  22 +++----
>  block/blkverify.c           |  20 +++---
>  block/commit.c              |   2 +-
>  block/curl.c                |   8 +--
>  block/iscsi.c               |   8 +--
>  block/linux-aio.c           |   8 +--
>  block/mirror.c              |   6 +-
>  block/qed-gencb.c           |   4 +-
>  block/qed-table.c           |  10 +--
>  block/qed.c                 |  46 +++++++-------
>  block/qed.h                 |  12 ++--
>  block/quorum.c              |  38 +++++------
>  block/raw-aio.h             |   8 +--
>  block/raw-posix.c           |  32 +++++-----
>  block/raw-win32.c           |  16 ++---
>  block/raw_bsd.c             |   8 +--
>  block/rbd.c                 |  58 ++++++++---------
>  block/sheepdog.c            |   4 +-
>  block/stream.c              |   2 +-
>  block/win32-aio.c           |   8 +--
>  blockjob.c                  |   4 +-
>  dma-helpers.c               |  24 +++----
>  hw/block/nvme.h             |   2 +-
>  hw/ide/ahci.c               |   2 +-
>  hw/ide/ahci.h               |   2 +-
>  hw/ide/core.c               |  12 ++--
>  hw/ide/internal.h           |  12 ++--
>  hw/ide/macio.c              |   2 +-
>  hw/ide/pci.c                |   2 +-
>  hw/ide/pci.h                |   2 +-
>  hw/ppc/mac.h                |   2 +-
>  hw/scsi/scsi-generic.c      |   2 +-
>  include/block/aio.h         |  12 ++--
>  include/block/block.h       |  36 +++++------
>  include/block/block_int.h   |  30 ++++-----
>  include/block/blockjob.h    |   4 +-
>  include/block/thread-pool.h |   4 +-
>  include/hw/scsi/scsi.h      |   2 +-
>  include/monitor/monitor.h   |   4 +-
>  include/sysemu/dma.h        |  26 ++++----
>  monitor.c                   |   6 +-
>  tests/test-thread-pool.c    |   2 +-
>  thread-pool.c               |   8 +--
>  47 files changed, 353 insertions(+), 354 deletions(-)
> 
> diff --git a/block-migration.c b/block-migration.c
> index da30e93..08db01a 100644
> --- a/block-migration.c
> +++ b/block-migration.c
> @@ -72,7 +72,7 @@ typedef struct BlkMigBlock {
>      int nr_sectors;
>      struct iovec iov;
>      QEMUIOVector qiov;
> -    BlockDriverAIOCB *aiocb;
> +    BlockAIOCB *aiocb;
>  
>      /* Protected by block migration lock.  */
>      int ret;
> diff --git a/block.c b/block.c
> index 34c8f8c..f71b87c 100644
> --- a/block.c
> +++ b/block.c
> @@ -61,12 +61,12 @@ struct BdrvDirtyBitmap {
>  #define COROUTINE_POOL_RESERVATION 64 /* number of coroutines to reserve */
>  
>  static void bdrv_dev_change_media_cb(BlockDriverState *bs, bool load);
> -static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
> +static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> -static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
> +        BlockCompletionFunc *cb, void *opaque);
> +static BlockAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> +        BlockCompletionFunc *cb, void *opaque);
>  static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs,
>                                           int64_t sector_num, int nb_sectors,
>                                           QEMUIOVector *iov);
> @@ -79,14 +79,14 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs,
>  static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs,
>      int64_t offset, unsigned int bytes, QEMUIOVector *qiov,
>      BdrvRequestFlags flags);
> -static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
> -                                               int64_t sector_num,
> -                                               QEMUIOVector *qiov,
> -                                               int nb_sectors,
> -                                               BdrvRequestFlags flags,
> -                                               BlockDriverCompletionFunc *cb,
> -                                               void *opaque,
> -                                               bool is_write);
> +static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
> +                                         int64_t sector_num,
> +                                         QEMUIOVector *qiov,
> +                                         int nb_sectors,
> +                                         BdrvRequestFlags flags,
> +                                         BlockCompletionFunc *cb,
> +                                         void *opaque,
> +                                         bool is_write);
>  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);
> @@ -4383,9 +4383,9 @@ int bdrv_get_backing_file_depth(BlockDriverState *bs)
>  /**************************************************************/
>  /* async I/Os */
>  
> -BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
> -                                 QEMUIOVector *qiov, int nb_sectors,
> -                                 BlockDriverCompletionFunc *cb, void *opaque)
> +BlockAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
> +                           QEMUIOVector *qiov, int nb_sectors,
> +                           BlockCompletionFunc *cb, void *opaque)
>  {
>      trace_bdrv_aio_readv(bs, sector_num, nb_sectors, opaque);
>  
> @@ -4393,9 +4393,9 @@ BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
>                                   cb, opaque, false);
>  }
>  
> -BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
> -                                  QEMUIOVector *qiov, int nb_sectors,
> -                                  BlockDriverCompletionFunc *cb, void *opaque)
> +BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
> +                            QEMUIOVector *qiov, int nb_sectors,
> +                            BlockCompletionFunc *cb, void *opaque)
>  {
>      trace_bdrv_aio_writev(bs, sector_num, nb_sectors, opaque);
>  
> @@ -4403,9 +4403,9 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
>                                   cb, opaque, true);
>  }
>  
> -BlockDriverAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs,
> +BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs,
>          int64_t sector_num, int nb_sectors, BdrvRequestFlags flags,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      trace_bdrv_aio_write_zeroes(bs, sector_num, nb_sectors, flags, opaque);
>  
> @@ -4420,7 +4420,7 @@ typedef struct MultiwriteCB {
>      int num_requests;
>      int num_callbacks;
>      struct {
> -        BlockDriverCompletionFunc *cb;
> +        BlockCompletionFunc *cb;
>          void *opaque;
>          QEMUIOVector *free_qiov;
>      } callbacks[];
> @@ -4597,7 +4597,7 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs, int num_reqs)
>      return 0;
>  }
>  
> -void bdrv_aio_cancel(BlockDriverAIOCB *acb)
> +void bdrv_aio_cancel(BlockAIOCB *acb)
>  {
>      acb->aiocb_info->cancel(acb);
>  }
> @@ -4605,33 +4605,32 @@ void bdrv_aio_cancel(BlockDriverAIOCB *acb)
>  /**************************************************************/
>  /* async block device emulation */
>  
> -typedef struct BlockDriverAIOCBSync {
> -    BlockDriverAIOCB common;
> +typedef struct BlockAIOCBSync {
> +    BlockAIOCB common;
>      QEMUBH *bh;
>      int ret;
>      /* vector translation state */
>      QEMUIOVector *qiov;
>      uint8_t *bounce;
>      int is_write;
> -} BlockDriverAIOCBSync;
> +} BlockAIOCBSync;
>  
> -static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
> +static void bdrv_aio_cancel_em(BlockAIOCB *blockacb)
>  {
> -    BlockDriverAIOCBSync *acb =
> -        container_of(blockacb, BlockDriverAIOCBSync, common);
> +    BlockAIOCBSync *acb = container_of(blockacb, BlockAIOCBSync, common);
>      qemu_bh_delete(acb->bh);
>      acb->bh = NULL;
>      qemu_aio_release(acb);
>  }
>  
>  static const AIOCBInfo bdrv_em_aiocb_info = {
> -    .aiocb_size         = sizeof(BlockDriverAIOCBSync),
> +    .aiocb_size         = sizeof(BlockAIOCBSync),
>      .cancel             = bdrv_aio_cancel_em,
>  };
>  
>  static void bdrv_aio_bh_cb(void *opaque)
>  {
> -    BlockDriverAIOCBSync *acb = opaque;
> +    BlockAIOCBSync *acb = opaque;
>  
>      if (!acb->is_write && acb->ret >= 0) {
>          qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size);
> @@ -4643,16 +4642,16 @@ static void bdrv_aio_bh_cb(void *opaque)
>      qemu_aio_release(acb);
>  }
>  
> -static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
> -                                            int64_t sector_num,
> -                                            QEMUIOVector *qiov,
> -                                            int nb_sectors,
> -                                            BlockDriverCompletionFunc *cb,
> -                                            void *opaque,
> -                                            int is_write)
> +static BlockAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
> +                                      int64_t sector_num,
> +                                      QEMUIOVector *qiov,
> +                                      int nb_sectors,
> +                                      BlockCompletionFunc *cb,
> +                                      void *opaque,
> +                                      int is_write)
>  
>  {
> -    BlockDriverAIOCBSync *acb;
> +    BlockAIOCBSync *acb;
>  
>      acb = qemu_aio_get(&bdrv_em_aiocb_info, bs, cb, opaque);
>      acb->is_write = is_write;
> @@ -4674,34 +4673,34 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
>      return &acb->common;
>  }
>  
> -static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
> +static BlockAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
>  }
>  
> -static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
> +static BlockAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      return bdrv_aio_rw_vector(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
>  }
>  
>  
> -typedef struct BlockDriverAIOCBCoroutine {
> -    BlockDriverAIOCB common;
> +typedef struct BlockAIOCBCoroutine {
> +    BlockAIOCB common;
>      BlockRequest req;
>      bool is_write;
>      bool *done;
>      QEMUBH* bh;
> -} BlockDriverAIOCBCoroutine;
> +} BlockAIOCBCoroutine;
>  
> -static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
> +static void bdrv_aio_co_cancel_em(BlockAIOCB *blockacb)
>  {
>      AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
> -    BlockDriverAIOCBCoroutine *acb =
> -        container_of(blockacb, BlockDriverAIOCBCoroutine, common);
> +    BlockAIOCBCoroutine *acb =
> +        container_of(blockacb, BlockAIOCBCoroutine, common);
>      bool done = false;
>  
>      acb->done = &done;
> @@ -4711,13 +4710,13 @@ static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
>  }
>  
>  static const AIOCBInfo bdrv_em_co_aiocb_info = {
> -    .aiocb_size         = sizeof(BlockDriverAIOCBCoroutine),
> +    .aiocb_size         = sizeof(BlockAIOCBCoroutine),
>      .cancel             = bdrv_aio_co_cancel_em,
>  };
>  
>  static void bdrv_co_em_bh(void *opaque)
>  {
> -    BlockDriverAIOCBCoroutine *acb = opaque;
> +    BlockAIOCBCoroutine *acb = opaque;
>  
>      acb->common.cb(acb->common.opaque, acb->req.error);
>  
> @@ -4732,7 +4731,7 @@ static void bdrv_co_em_bh(void *opaque)
>  /* Invoke bdrv_co_do_readv/bdrv_co_do_writev */
>  static void coroutine_fn bdrv_co_do_rw(void *opaque)
>  {
> -    BlockDriverAIOCBCoroutine *acb = opaque;
> +    BlockAIOCBCoroutine *acb = opaque;
>      BlockDriverState *bs = acb->common.bs;
>  
>      if (!acb->is_write) {
> @@ -4747,17 +4746,17 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque)
>      qemu_bh_schedule(acb->bh);
>  }
>  
> -static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
> -                                               int64_t sector_num,
> -                                               QEMUIOVector *qiov,
> -                                               int nb_sectors,
> -                                               BdrvRequestFlags flags,
> -                                               BlockDriverCompletionFunc *cb,
> -                                               void *opaque,
> -                                               bool is_write)
> +static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
> +                                         int64_t sector_num,
> +                                         QEMUIOVector *qiov,
> +                                         int nb_sectors,
> +                                         BdrvRequestFlags flags,
> +                                         BlockCompletionFunc *cb,
> +                                         void *opaque,
> +                                         bool is_write)
>  {
>      Coroutine *co;
> -    BlockDriverAIOCBCoroutine *acb;
> +    BlockAIOCBCoroutine *acb;
>  
>      acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
>      acb->req.sector = sector_num;
> @@ -4775,7 +4774,7 @@ static BlockDriverAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
>  
>  static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque)
>  {
> -    BlockDriverAIOCBCoroutine *acb = opaque;
> +    BlockAIOCBCoroutine *acb = opaque;
>      BlockDriverState *bs = acb->common.bs;
>  
>      acb->req.error = bdrv_co_flush(bs);
> @@ -4783,13 +4782,13 @@ static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque)
>      qemu_bh_schedule(acb->bh);
>  }
>  
> -BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +BlockAIOCB *bdrv_aio_flush(BlockDriverState *bs,
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      trace_bdrv_aio_flush(bs, opaque);
>  
>      Coroutine *co;
> -    BlockDriverAIOCBCoroutine *acb;
> +    BlockAIOCBCoroutine *acb;
>  
>      acb = qemu_aio_get(&bdrv_em_co_aiocb_info, bs, cb, opaque);
>      acb->done = NULL;
> @@ -4802,7 +4801,7 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
>  
>  static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque)
>  {
> -    BlockDriverAIOCBCoroutine *acb = opaque;
> +    BlockAIOCBCoroutine *acb = opaque;
>      BlockDriverState *bs = acb->common.bs;
>  
>      acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors);
> @@ -4810,12 +4809,12 @@ static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque)
>      qemu_bh_schedule(acb->bh);
>  }
>  
> -BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
> +BlockAIOCB *bdrv_aio_discard(BlockDriverState *bs,
>          int64_t sector_num, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      Coroutine *co;
> -    BlockDriverAIOCBCoroutine *acb;
> +    BlockAIOCBCoroutine *acb;
>  
>      trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque);
>  
> @@ -4841,9 +4840,9 @@ void bdrv_init_with_whitelist(void)
>  }
>  
>  void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
> -                   BlockDriverCompletionFunc *cb, void *opaque)
> +                   BlockCompletionFunc *cb, void *opaque)
>  {
> -    BlockDriverAIOCB *acb;
> +    BlockAIOCB *acb;
>  
>      acb = g_slice_alloc(aiocb_info->aiocb_size);
>      acb->aiocb_info = aiocb_info;
> @@ -4855,7 +4854,7 @@ void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
>  
>  void qemu_aio_release(void *p)
>  {
> -    BlockDriverAIOCB *acb = p;
> +    BlockAIOCB *acb = p;
>      g_slice_free1(acb->aiocb_info->aiocb_size, acb);
>  }
>  
> @@ -4882,7 +4881,7 @@ static int coroutine_fn bdrv_co_io_em(BlockDriverState *bs, int64_t sector_num,
>      CoroutineIOCompletion co = {
>          .coroutine = qemu_coroutine_self(),
>      };
> -    BlockDriverAIOCB *acb;
> +    BlockAIOCB *acb;
>  
>      if (is_write) {
>          acb = bs->drv->bdrv_aio_writev(bs, sector_num, iov, nb_sectors,
> @@ -4948,7 +4947,7 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
>      if (bs->drv->bdrv_co_flush_to_disk) {
>          ret = bs->drv->bdrv_co_flush_to_disk(bs);
>      } else if (bs->drv->bdrv_aio_flush) {
> -        BlockDriverAIOCB *acb;
> +        BlockAIOCB *acb;
>          CoroutineIOCompletion co = {
>              .coroutine = qemu_coroutine_self(),
>          };
> @@ -5131,7 +5130,7 @@ int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
>          if (bs->drv->bdrv_co_discard) {
>              ret = bs->drv->bdrv_co_discard(bs, sector_num, num);
>          } else {
> -            BlockDriverAIOCB *acb;
> +            BlockAIOCB *acb;
>              CoroutineIOCompletion co = {
>                  .coroutine = qemu_coroutine_self(),
>              };
> @@ -5257,9 +5256,9 @@ int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
>      return -ENOTSUP;
>  }
>  
> -BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
> +BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
>          unsigned long int req, void *buf,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      BlockDriver *drv = bs->drv;
>  
> diff --git a/block/archipelago.c b/block/archipelago.c
> index 22a7daa..9bbae4e 100644
> --- a/block/archipelago.c
> +++ b/block/archipelago.c
> @@ -87,7 +87,7 @@ typedef enum {
>  } ARCHIPCmd;
>  
>  typedef struct ArchipelagoAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      QEMUBH *bh;
>      struct BDRVArchipelagoState *s;
>      QEMUIOVector *qiov;
> @@ -724,7 +724,7 @@ static int qemu_archipelago_create(const char *filename,
>      return ret;
>  }
>  
> -static void qemu_archipelago_aio_cancel(BlockDriverAIOCB *blockacb)
> +static void qemu_archipelago_aio_cancel(BlockAIOCB *blockacb)
>  {
>      ArchipelagoAIOCB *aio_cb = (ArchipelagoAIOCB *) blockacb;
>      aio_cb->cancelled = true;
> @@ -869,13 +869,13 @@ err_exit:
>      return ret;
>  }
>  
> -static BlockDriverAIOCB *qemu_archipelago_aio_rw(BlockDriverState *bs,
> -                                                 int64_t sector_num,
> -                                                 QEMUIOVector *qiov,
> -                                                 int nb_sectors,
> -                                                 BlockDriverCompletionFunc *cb,
> -                                                 void *opaque,
> -                                                 int op)
> +static BlockAIOCB *qemu_archipelago_aio_rw(BlockDriverState *bs,
> +                                           int64_t sector_num,
> +                                           QEMUIOVector *qiov,
> +                                           int nb_sectors,
> +                                           BlockCompletionFunc *cb,
> +                                           void *opaque,
> +                                           int op)
>  {
>      ArchipelagoAIOCB *aio_cb;
>      BDRVArchipelagoState *s = bs->opaque;
> @@ -908,17 +908,17 @@ err_exit:
>      return NULL;
>  }
>  
> -static BlockDriverAIOCB *qemu_archipelago_aio_readv(BlockDriverState *bs,
> +static BlockAIOCB *qemu_archipelago_aio_readv(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      return qemu_archipelago_aio_rw(bs, sector_num, qiov, nb_sectors, cb,
>                                     opaque, ARCHIP_OP_READ);
>  }
>  
> -static BlockDriverAIOCB *qemu_archipelago_aio_writev(BlockDriverState *bs,
> +static BlockAIOCB *qemu_archipelago_aio_writev(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      return qemu_archipelago_aio_rw(bs, sector_num, qiov, nb_sectors, cb,
>                                     opaque, ARCHIP_OP_WRITE);
> @@ -1008,8 +1008,8 @@ static QemuOptsList qemu_archipelago_create_opts = {
>      }
>  };
>  
> -static BlockDriverAIOCB *qemu_archipelago_aio_flush(BlockDriverState *bs,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +static BlockAIOCB *qemu_archipelago_aio_flush(BlockDriverState *bs,
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      return qemu_archipelago_aio_rw(bs, 0, NULL, 0, cb, opaque,
>                                     ARCHIP_OP_FLUSH);
> diff --git a/block/backup.c b/block/backup.c
> index d0b0225..e334740 100644
> --- a/block/backup.c
> +++ b/block/backup.c
> @@ -353,7 +353,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
>                    int64_t speed, MirrorSyncMode sync_mode,
>                    BlockdevOnError on_source_error,
>                    BlockdevOnError on_target_error,
> -                  BlockDriverCompletionFunc *cb, void *opaque,
> +                  BlockCompletionFunc *cb, void *opaque,
>                    Error **errp)
>  {
>      int64_t len;
> diff --git a/block/blkdebug.c b/block/blkdebug.c
> index 69b330e..008d3e3 100644
> --- a/block/blkdebug.c
> +++ b/block/blkdebug.c
> @@ -41,7 +41,7 @@ typedef struct BDRVBlkdebugState {
>  } BDRVBlkdebugState;
>  
>  typedef struct BlkdebugAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      QEMUBH *bh;
>      int ret;
>  } BlkdebugAIOCB;
> @@ -52,7 +52,7 @@ typedef struct BlkdebugSuspendedReq {
>      QLIST_ENTRY(BlkdebugSuspendedReq) next;
>  } BlkdebugSuspendedReq;
>  
> -static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
> +static void blkdebug_aio_cancel(BlockAIOCB *blockacb);
>  
>  static const AIOCBInfo blkdebug_aiocb_info = {
>      .aiocb_size = sizeof(BlkdebugAIOCB),
> @@ -450,7 +450,7 @@ static void error_callback_bh(void *opaque)
>      qemu_aio_release(acb);
>  }
>  
> -static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
> +static void blkdebug_aio_cancel(BlockAIOCB *blockacb)
>  {
>      BlkdebugAIOCB *acb = container_of(blockacb, BlkdebugAIOCB, common);
>      if (acb->bh) {
> @@ -460,8 +460,8 @@ static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
>      qemu_aio_release(acb);
>  }
>  
> -static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
> -    BlockDriverCompletionFunc *cb, void *opaque, BlkdebugRule *rule)
> +static BlockAIOCB *inject_error(BlockDriverState *bs,
> +    BlockCompletionFunc *cb, void *opaque, BlkdebugRule *rule)
>  {
>      BDRVBlkdebugState *s = bs->opaque;
>      int error = rule->options.inject.error;
> @@ -486,9 +486,9 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
>      return &acb->common;
>  }
>  
> -static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
> +static BlockAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
>      int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -    BlockDriverCompletionFunc *cb, void *opaque)
> +    BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVBlkdebugState *s = bs->opaque;
>      BlkdebugRule *rule = NULL;
> @@ -508,9 +508,9 @@ static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
>      return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
>  }
>  
> -static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
> +static BlockAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
>      int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -    BlockDriverCompletionFunc *cb, void *opaque)
> +    BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVBlkdebugState *s = bs->opaque;
>      BlkdebugRule *rule = NULL;
> @@ -530,8 +530,8 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
>      return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
>  }
>  
> -static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
> -    BlockDriverCompletionFunc *cb, void *opaque)
> +static BlockAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
> +    BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVBlkdebugState *s = bs->opaque;
>      BlkdebugRule *rule = NULL;
> diff --git a/block/blkverify.c b/block/blkverify.c
> index 163064c..d4553cc 100644
> --- a/block/blkverify.c
> +++ b/block/blkverify.c
> @@ -19,7 +19,7 @@ typedef struct {
>  
>  typedef struct BlkverifyAIOCB BlkverifyAIOCB;
>  struct BlkverifyAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      QEMUBH *bh;
>  
>      /* Request metadata */
> @@ -38,7 +38,7 @@ struct BlkverifyAIOCB {
>      void (*verify)(BlkverifyAIOCB *acb);
>  };
>  
> -static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
> +static void blkverify_aio_cancel(BlockAIOCB *blockacb)
>  {
>      BlkverifyAIOCB *acb = (BlkverifyAIOCB *)blockacb;
>      AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
> @@ -180,7 +180,7 @@ static int64_t blkverify_getlength(BlockDriverState *bs)
>  static BlkverifyAIOCB *blkverify_aio_get(BlockDriverState *bs, bool is_write,
>                                           int64_t sector_num, QEMUIOVector *qiov,
>                                           int nb_sectors,
> -                                         BlockDriverCompletionFunc *cb,
> +                                         BlockCompletionFunc *cb,
>                                           void *opaque)
>  {
>      BlkverifyAIOCB *acb = qemu_aio_get(&blkverify_aiocb_info, bs, cb, opaque);
> @@ -248,9 +248,9 @@ static void blkverify_verify_readv(BlkverifyAIOCB *acb)
>      }
>  }
>  
> -static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs,
> +static BlockAIOCB *blkverify_aio_readv(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVBlkverifyState *s = bs->opaque;
>      BlkverifyAIOCB *acb = blkverify_aio_get(bs, false, sector_num, qiov,
> @@ -268,9 +268,9 @@ static BlockDriverAIOCB *blkverify_aio_readv(BlockDriverState *bs,
>      return &acb->common;
>  }
>  
> -static BlockDriverAIOCB *blkverify_aio_writev(BlockDriverState *bs,
> +static BlockAIOCB *blkverify_aio_writev(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVBlkverifyState *s = bs->opaque;
>      BlkverifyAIOCB *acb = blkverify_aio_get(bs, true, sector_num, qiov,
> @@ -283,9 +283,9 @@ static BlockDriverAIOCB *blkverify_aio_writev(BlockDriverState *bs,
>      return &acb->common;
>  }
>  
> -static BlockDriverAIOCB *blkverify_aio_flush(BlockDriverState *bs,
> -                                             BlockDriverCompletionFunc *cb,
> -                                             void *opaque)
> +static BlockAIOCB *blkverify_aio_flush(BlockDriverState *bs,
> +                                       BlockCompletionFunc *cb,
> +                                       void *opaque)
>  {
>      BDRVBlkverifyState *s = bs->opaque;
>  
> diff --git a/block/commit.c b/block/commit.c
> index 91517d3..60a2acc 100644
> --- a/block/commit.c
> +++ b/block/commit.c
> @@ -182,7 +182,7 @@ static const BlockJobDriver commit_job_driver = {
>  
>  void commit_start(BlockDriverState *bs, BlockDriverState *base,
>                    BlockDriverState *top, int64_t speed,
> -                  BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
> +                  BlockdevOnError on_error, BlockCompletionFunc *cb,
>                    void *opaque, const char *backing_file_str, Error **errp)
>  {
>      CommitBlockJob *s;
> diff --git a/block/curl.c b/block/curl.c
> index 938f9d9..5e96b05 100644
> --- a/block/curl.c
> +++ b/block/curl.c
> @@ -78,7 +78,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle,
>  struct BDRVCURLState;
>  
>  typedef struct CURLAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      QEMUBH *bh;
>      QEMUIOVector *qiov;
>  
> @@ -613,7 +613,7 @@ out_noclean:
>      return -EINVAL;
>  }
>  
> -static void curl_aio_cancel(BlockDriverAIOCB *blockacb)
> +static void curl_aio_cancel(BlockAIOCB *blockacb)
>  {
>      // Do we have to implement canceling? Seems to work without...
>  }
> @@ -686,9 +686,9 @@ static void curl_readv_bh_cb(void *p)
>      curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
>  }
>  
> -static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
> +static BlockAIOCB *curl_aio_readv(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      CURLAIOCB *acb;
>  
> diff --git a/block/iscsi.c b/block/iscsi.c
> index af3d0f6..1a1a389 100644
> --- a/block/iscsi.c
> +++ b/block/iscsi.c
> @@ -81,7 +81,7 @@ typedef struct IscsiTask {
>  } IscsiTask;
>  
>  typedef struct IscsiAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      QEMUIOVector *qiov;
>      QEMUBH *bh;
>      IscsiLun *iscsilun;
> @@ -231,7 +231,7 @@ iscsi_abort_task_cb(struct iscsi_context *iscsi, int status, void *command_data,
>  }
>  
>  static void
> -iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
> +iscsi_aio_cancel(BlockAIOCB *blockacb)
>  {
>      IscsiAIOCB *acb = (IscsiAIOCB *)blockacb;
>      IscsiLun *iscsilun = acb->iscsilun;
> @@ -669,9 +669,9 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status,
>      iscsi_schedule_bh(acb);
>  }
>  
> -static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
> +static BlockAIOCB *iscsi_aio_ioctl(BlockDriverState *bs,
>          unsigned long int req, void *buf,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      IscsiLun *iscsilun = bs->opaque;
>      struct iscsi_context *iscsi = iscsilun->iscsi;
> diff --git a/block/linux-aio.c b/block/linux-aio.c
> index 9aca758..2436140 100644
> --- a/block/linux-aio.c
> +++ b/block/linux-aio.c
> @@ -28,7 +28,7 @@
>  #define MAX_QUEUED_IO  128
>  
>  struct qemu_laiocb {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      struct qemu_laio_state *ctx;
>      struct iocb iocb;
>      ssize_t ret;
> @@ -147,7 +147,7 @@ static void qemu_laio_completion_cb(EventNotifier *e)
>      }
>  }
>  
> -static void laio_cancel(BlockDriverAIOCB *blockacb)
> +static void laio_cancel(BlockAIOCB *blockacb)
>  {
>      struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb;
>      struct io_event event;
> @@ -257,9 +257,9 @@ int laio_io_unplug(BlockDriverState *bs, void *aio_ctx, bool unplug)
>      return ret;
>  }
>  
> -BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
> +BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque, int type)
> +        BlockCompletionFunc *cb, void *opaque, int type)
>  {
>      struct qemu_laio_state *s = aio_ctx;
>      struct qemu_laiocb *laiocb;
> diff --git a/block/mirror.c b/block/mirror.c
> index 829be2f..e8a43eb 100644
> --- a/block/mirror.c
> +++ b/block/mirror.c
> @@ -613,7 +613,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
>                               int64_t buf_size,
>                               BlockdevOnError on_source_error,
>                               BlockdevOnError on_target_error,
> -                             BlockDriverCompletionFunc *cb,
> +                             BlockCompletionFunc *cb,
>                               void *opaque, Error **errp,
>                               const BlockJobDriver *driver,
>                               bool is_none_mode, BlockDriverState *base)
> @@ -673,7 +673,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
>                    int64_t speed, int64_t granularity, int64_t buf_size,
>                    MirrorSyncMode mode, BlockdevOnError on_source_error,
>                    BlockdevOnError on_target_error,
> -                  BlockDriverCompletionFunc *cb,
> +                  BlockCompletionFunc *cb,
>                    void *opaque, Error **errp)
>  {
>      bool is_none_mode;
> @@ -690,7 +690,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
>  void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
>                           int64_t speed,
>                           BlockdevOnError on_error,
> -                         BlockDriverCompletionFunc *cb,
> +                         BlockCompletionFunc *cb,
>                           void *opaque, Error **errp)
>  {
>      int64_t length, base_length;
> diff --git a/block/qed-gencb.c b/block/qed-gencb.c
> index 7d7ac1f..b817a8b 100644
> --- a/block/qed-gencb.c
> +++ b/block/qed-gencb.c
> @@ -13,7 +13,7 @@
>  
>  #include "qed.h"
>  
> -void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque)
> +void *gencb_alloc(size_t len, BlockCompletionFunc *cb, void *opaque)
>  {
>      GenericCB *gencb = g_malloc(len);
>      gencb->cb = cb;
> @@ -24,7 +24,7 @@ void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque)
>  void gencb_complete(void *opaque, int ret)
>  {
>      GenericCB *gencb = opaque;
> -    BlockDriverCompletionFunc *cb = gencb->cb;
> +    BlockCompletionFunc *cb = gencb->cb;
>      void *user_opaque = gencb->opaque;
>  
>      g_free(gencb);
> diff --git a/block/qed-table.c b/block/qed-table.c
> index f61107a..513aa87 100644
> --- a/block/qed-table.c
> +++ b/block/qed-table.c
> @@ -49,7 +49,7 @@ out:
>  }
>  
>  static void qed_read_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
> -                           BlockDriverCompletionFunc *cb, void *opaque)
> +                           BlockCompletionFunc *cb, void *opaque)
>  {
>      QEDReadTableCB *read_table_cb = gencb_alloc(sizeof(*read_table_cb),
>                                                  cb, opaque);
> @@ -119,7 +119,7 @@ out:
>   */
>  static void qed_write_table(BDRVQEDState *s, uint64_t offset, QEDTable *table,
>                              unsigned int index, unsigned int n, bool flush,
> -                            BlockDriverCompletionFunc *cb, void *opaque)
> +                            BlockCompletionFunc *cb, void *opaque)
>  {
>      QEDWriteTableCB *write_table_cb;
>      unsigned int sector_mask = BDRV_SECTOR_SIZE / sizeof(uint64_t) - 1;
> @@ -180,7 +180,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s)
>  }
>  
>  void qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n,
> -                        BlockDriverCompletionFunc *cb, void *opaque)
> +                        BlockCompletionFunc *cb, void *opaque)
>  {
>      BLKDBG_EVENT(s->bs->file, BLKDBG_L1_UPDATE);
>      qed_write_table(s, s->header.l1_table_offset,
> @@ -235,7 +235,7 @@ static void qed_read_l2_table_cb(void *opaque, int ret)
>  }
>  
>  void qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset,
> -                       BlockDriverCompletionFunc *cb, void *opaque)
> +                       BlockCompletionFunc *cb, void *opaque)
>  {
>      QEDReadL2TableCB *read_l2_table_cb;
>  
> @@ -275,7 +275,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
>  
>  void qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
>                          unsigned int index, unsigned int n, bool flush,
> -                        BlockDriverCompletionFunc *cb, void *opaque)
> +                        BlockCompletionFunc *cb, void *opaque)
>  {
>      BLKDBG_EVENT(s->bs->file, BLKDBG_L2_UPDATE);
>      qed_write_table(s, request->l2_table->offset,
> diff --git a/block/qed.c b/block/qed.c
> index f20ffb3..a0eafa9 100644
> --- a/block/qed.c
> +++ b/block/qed.c
> @@ -18,7 +18,7 @@
>  #include "qapi/qmp/qerror.h"
>  #include "migration/migration.h"
>  
> -static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
> +static void qed_aio_cancel(BlockAIOCB *blockacb)
>  {
>      QEDAIOCB *acb = (QEDAIOCB *)blockacb;
>      AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
> @@ -144,7 +144,7 @@ static void qed_write_header_read_cb(void *opaque, int ret)
>   * This function only updates known header fields in-place and does not affect
>   * extra data after the QED header.
>   */
> -static void qed_write_header(BDRVQEDState *s, BlockDriverCompletionFunc cb,
> +static void qed_write_header(BDRVQEDState *s, BlockCompletionFunc cb,
>                               void *opaque)
>  {
>      /* We must write full sectors for O_DIRECT but cannot necessarily generate
> @@ -772,7 +772,7 @@ static BDRVQEDState *acb_to_s(QEDAIOCB *acb)
>  static void qed_read_backing_file(BDRVQEDState *s, uint64_t pos,
>                                    QEMUIOVector *qiov,
>                                    QEMUIOVector **backing_qiov,
> -                                  BlockDriverCompletionFunc *cb, void *opaque)
> +                                  BlockCompletionFunc *cb, void *opaque)
>  {
>      uint64_t backing_length = 0;
>      size_t size;
> @@ -864,7 +864,7 @@ static void qed_copy_from_backing_file_write(void *opaque, int ret)
>   */
>  static void qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos,
>                                         uint64_t len, uint64_t offset,
> -                                       BlockDriverCompletionFunc *cb,
> +                                       BlockCompletionFunc *cb,
>                                         void *opaque)
>  {
>      CopyFromBackingFileCB *copy_cb;
> @@ -915,7 +915,7 @@ static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
>  static void qed_aio_complete_bh(void *opaque)
>  {
>      QEDAIOCB *acb = opaque;
> -    BlockDriverCompletionFunc *cb = acb->common.cb;
> +    BlockCompletionFunc *cb = acb->common.cb;
>      void *user_opaque = acb->common.opaque;
>      int ret = acb->bh_ret;
>      bool *finished = acb->finished;
> @@ -1083,7 +1083,7 @@ static void qed_aio_write_main(void *opaque, int ret)
>      BDRVQEDState *s = acb_to_s(acb);
>      uint64_t offset = acb->cur_cluster +
>                        qed_offset_into_cluster(s, acb->cur_pos);
> -    BlockDriverCompletionFunc *next_fn;
> +    BlockCompletionFunc *next_fn;
>  
>      trace_qed_aio_write_main(s, acb, ret, offset, acb->cur_qiov.size);
>  
> @@ -1183,7 +1183,7 @@ static void qed_aio_write_zero_cluster(void *opaque, int ret)
>  static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
>  {
>      BDRVQEDState *s = acb_to_s(acb);
> -    BlockDriverCompletionFunc *cb;
> +    BlockCompletionFunc *cb;
>  
>      /* Cancel timer when the first allocating request comes in */
>      if (QSIMPLEQ_EMPTY(&s->allocating_write_reqs)) {
> @@ -1384,11 +1384,11 @@ static void qed_aio_next_io(void *opaque, int ret)
>                        io_fn, acb);
>  }
>  
> -static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs,
> -                                       int64_t sector_num,
> -                                       QEMUIOVector *qiov, int nb_sectors,
> -                                       BlockDriverCompletionFunc *cb,
> -                                       void *opaque, int flags)
> +static BlockAIOCB *qed_aio_setup(BlockDriverState *bs,
> +                                 int64_t sector_num,
> +                                 QEMUIOVector *qiov, int nb_sectors,
> +                                 BlockCompletionFunc *cb,
> +                                 void *opaque, int flags)
>  {
>      QEDAIOCB *acb = qemu_aio_get(&qed_aiocb_info, bs, cb, opaque);
>  
> @@ -1410,20 +1410,20 @@ static BlockDriverAIOCB *qed_aio_setup(BlockDriverState *bs,
>      return &acb->common;
>  }
>  
> -static BlockDriverAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs,
> -                                            int64_t sector_num,
> -                                            QEMUIOVector *qiov, int nb_sectors,
> -                                            BlockDriverCompletionFunc *cb,
> -                                            void *opaque)
> +static BlockAIOCB *bdrv_qed_aio_readv(BlockDriverState *bs,
> +                                      int64_t sector_num,
> +                                      QEMUIOVector *qiov, int nb_sectors,
> +                                      BlockCompletionFunc *cb,
> +                                      void *opaque)
>  {
>      return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
>  }
>  
> -static BlockDriverAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs,
> -                                             int64_t sector_num,
> -                                             QEMUIOVector *qiov, int nb_sectors,
> -                                             BlockDriverCompletionFunc *cb,
> -                                             void *opaque)
> +static BlockAIOCB *bdrv_qed_aio_writev(BlockDriverState *bs,
> +                                       int64_t sector_num,
> +                                       QEMUIOVector *qiov, int nb_sectors,
> +                                       BlockCompletionFunc *cb,
> +                                       void *opaque)
>  {
>      return qed_aio_setup(bs, sector_num, qiov, nb_sectors, cb,
>                           opaque, QED_AIOCB_WRITE);
> @@ -1451,7 +1451,7 @@ static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs,
>                                                   int nb_sectors,
>                                                   BdrvRequestFlags flags)
>  {
> -    BlockDriverAIOCB *blockacb;
> +    BlockAIOCB *blockacb;
>      BDRVQEDState *s = bs->opaque;
>      QEDWriteZeroesCB cb = { .done = false };
>      QEMUIOVector qiov;
> diff --git a/block/qed.h b/block/qed.h
> index 2b0e724..d3934a0 100644
> --- a/block/qed.h
> +++ b/block/qed.h
> @@ -128,7 +128,7 @@ enum {
>  };
>  
>  typedef struct QEDAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      QEMUBH *bh;
>      int bh_ret;                     /* final return status for completion bh */
>      QSIMPLEQ_ENTRY(QEDAIOCB) next;  /* next request */
> @@ -203,11 +203,11 @@ typedef void QEDFindClusterFunc(void *opaque, int ret, uint64_t offset, size_t l
>   * Generic callback for chaining async callbacks
>   */
>  typedef struct {
> -    BlockDriverCompletionFunc *cb;
> +    BlockCompletionFunc *cb;
>      void *opaque;
>  } GenericCB;
>  
> -void *gencb_alloc(size_t len, BlockDriverCompletionFunc *cb, void *opaque);
> +void *gencb_alloc(size_t len, BlockCompletionFunc *cb, void *opaque);
>  void gencb_complete(void *opaque, int ret);
>  
>  /**
> @@ -230,16 +230,16 @@ void qed_commit_l2_cache_entry(L2TableCache *l2_cache, CachedL2Table *l2_table);
>   */
>  int qed_read_l1_table_sync(BDRVQEDState *s);
>  void qed_write_l1_table(BDRVQEDState *s, unsigned int index, unsigned int n,
> -                        BlockDriverCompletionFunc *cb, void *opaque);
> +                        BlockCompletionFunc *cb, void *opaque);
>  int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
>                              unsigned int n);
>  int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
>                             uint64_t offset);
>  void qed_read_l2_table(BDRVQEDState *s, QEDRequest *request, uint64_t offset,
> -                       BlockDriverCompletionFunc *cb, void *opaque);
> +                       BlockCompletionFunc *cb, void *opaque);
>  void qed_write_l2_table(BDRVQEDState *s, QEDRequest *request,
>                          unsigned int index, unsigned int n, bool flush,
> -                        BlockDriverCompletionFunc *cb, void *opaque);
> +                        BlockCompletionFunc *cb, void *opaque);
>  int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
>                              unsigned int index, unsigned int n, bool flush);
>  
> diff --git a/block/quorum.c b/block/quorum.c
> index f958269..26f8dfa 100644
> --- a/block/quorum.c
> +++ b/block/quorum.c
> @@ -92,7 +92,7 @@ typedef struct QuorumAIOCB QuorumAIOCB;
>   * $children_count QuorumChildRequest.
>   */
>  typedef struct QuorumChildRequest {
> -    BlockDriverAIOCB *aiocb;
> +    BlockAIOCB *aiocb;
>      QEMUIOVector qiov;
>      uint8_t *buf;
>      int ret;
> @@ -105,7 +105,7 @@ typedef struct QuorumChildRequest {
>   * used to do operations on each children and track overall progress.
>   */
>  struct QuorumAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>  
>      /* Request metadata */
>      uint64_t sector_num;
> @@ -130,7 +130,7 @@ struct QuorumAIOCB {
>  
>  static bool quorum_vote(QuorumAIOCB *acb);
>  
> -static void quorum_aio_cancel(BlockDriverAIOCB *blockacb)
> +static void quorum_aio_cancel(BlockAIOCB *blockacb)
>  {
>      QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common);
>      BDRVQuorumState *s = acb->common.bs->opaque;
> @@ -187,7 +187,7 @@ static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s,
>                                     QEMUIOVector *qiov,
>                                     uint64_t sector_num,
>                                     int nb_sectors,
> -                                   BlockDriverCompletionFunc *cb,
> +                                   BlockCompletionFunc *cb,
>                                     void *opaque)
>  {
>      QuorumAIOCB *acb = qemu_aio_get(&quorum_aiocb_info, bs, cb, opaque);
> @@ -265,7 +265,7 @@ static void quorum_rewrite_aio_cb(void *opaque, int ret)
>      quorum_aio_finalize(acb);
>  }
>  
> -static BlockDriverAIOCB *read_fifo_child(QuorumAIOCB *acb);
> +static BlockAIOCB *read_fifo_child(QuorumAIOCB *acb);
>  
>  static void quorum_copy_qiov(QEMUIOVector *dest, QEMUIOVector *source)
>  {
> @@ -641,7 +641,7 @@ free_exit:
>      return rewrite;
>  }
>  
> -static BlockDriverAIOCB *read_quorum_children(QuorumAIOCB *acb)
> +static BlockAIOCB *read_quorum_children(QuorumAIOCB *acb)
>  {
>      BDRVQuorumState *s = acb->common.bs->opaque;
>      int i;
> @@ -660,7 +660,7 @@ static BlockDriverAIOCB *read_quorum_children(QuorumAIOCB *acb)
>      return &acb->common;
>  }
>  
> -static BlockDriverAIOCB *read_fifo_child(QuorumAIOCB *acb)
> +static BlockAIOCB *read_fifo_child(QuorumAIOCB *acb)
>  {
>      BDRVQuorumState *s = acb->common.bs->opaque;
>  
> @@ -676,12 +676,12 @@ static BlockDriverAIOCB *read_fifo_child(QuorumAIOCB *acb)
>      return &acb->common;
>  }
>  
> -static BlockDriverAIOCB *quorum_aio_readv(BlockDriverState *bs,
> -                                          int64_t sector_num,
> -                                          QEMUIOVector *qiov,
> -                                          int nb_sectors,
> -                                          BlockDriverCompletionFunc *cb,
> -                                          void *opaque)
> +static BlockAIOCB *quorum_aio_readv(BlockDriverState *bs,
> +                                    int64_t sector_num,
> +                                    QEMUIOVector *qiov,
> +                                    int nb_sectors,
> +                                    BlockCompletionFunc *cb,
> +                                    void *opaque)
>  {
>      BDRVQuorumState *s = bs->opaque;
>      QuorumAIOCB *acb = quorum_aio_get(s, bs, qiov, sector_num,
> @@ -697,12 +697,12 @@ static BlockDriverAIOCB *quorum_aio_readv(BlockDriverState *bs,
>      return read_fifo_child(acb);
>  }
>  
> -static BlockDriverAIOCB *quorum_aio_writev(BlockDriverState *bs,
> -                                          int64_t sector_num,
> -                                          QEMUIOVector *qiov,
> -                                          int nb_sectors,
> -                                          BlockDriverCompletionFunc *cb,
> -                                          void *opaque)
> +static BlockAIOCB *quorum_aio_writev(BlockDriverState *bs,
> +                                     int64_t sector_num,
> +                                     QEMUIOVector *qiov,
> +                                     int nb_sectors,
> +                                     BlockCompletionFunc *cb,
> +                                     void *opaque)
>  {
>      BDRVQuorumState *s = bs->opaque;
>      QuorumAIOCB *acb = quorum_aio_get(s, bs, qiov, sector_num, nb_sectors,
> diff --git a/block/raw-aio.h b/block/raw-aio.h
> index e18c975..80681ce 100644
> --- a/block/raw-aio.h
> +++ b/block/raw-aio.h
> @@ -35,9 +35,9 @@
>  #ifdef CONFIG_LINUX_AIO
>  void *laio_init(void);
>  void laio_cleanup(void *s);
> -BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
> +BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque, int type);
> +        BlockCompletionFunc *cb, void *opaque, int type);
>  void laio_detach_aio_context(void *s, AioContext *old_context);
>  void laio_attach_aio_context(void *s, AioContext *new_context);
>  void laio_io_plug(BlockDriverState *bs, void *aio_ctx);
> @@ -49,10 +49,10 @@ typedef struct QEMUWin32AIOState QEMUWin32AIOState;
>  QEMUWin32AIOState *win32_aio_init(void);
>  void win32_aio_cleanup(QEMUWin32AIOState *aio);
>  int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
> -BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
> +BlockAIOCB *win32_aio_submit(BlockDriverState *bs,
>          QEMUWin32AIOState *aio, HANDLE hfile,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque, int type);
> +        BlockCompletionFunc *cb, void *opaque, int type);
>  void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
>                                    AioContext *old_context);
>  void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
> diff --git a/block/raw-posix.c b/block/raw-posix.c
> index d737f3a..2efbfeb 100644
> --- a/block/raw-posix.c
> +++ b/block/raw-posix.c
> @@ -1040,9 +1040,9 @@ static int paio_submit_co(BlockDriverState *bs, int fd,
>      return thread_pool_submit_co(pool, aio_worker, acb);
>  }
>  
> -static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
> +static BlockAIOCB *paio_submit(BlockDriverState *bs, int fd,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque, int type)
> +        BlockCompletionFunc *cb, void *opaque, int type)
>  {
>      RawPosixAIOData *acb = g_slice_new(RawPosixAIOData);
>      ThreadPool *pool;
> @@ -1065,9 +1065,9 @@ static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, int fd,
>      return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
>  }
>  
> -static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
> +static BlockAIOCB *raw_aio_submit(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque, int type)
> +        BlockCompletionFunc *cb, void *opaque, int type)
>  {
>      BDRVRawState *s = bs->opaque;
>  
> @@ -1124,24 +1124,24 @@ static void raw_aio_flush_io_queue(BlockDriverState *bs)
>  #endif
>  }
>  
> -static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
> +static BlockAIOCB *raw_aio_readv(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
>                            cb, opaque, QEMU_AIO_READ);
>  }
>  
> -static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
> +static BlockAIOCB *raw_aio_writev(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
>                            cb, opaque, QEMU_AIO_WRITE);
>  }
>  
> -static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +static BlockAIOCB *raw_aio_flush(BlockDriverState *bs,
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVRawState *s = bs->opaque;
>  
> @@ -1536,9 +1536,9 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
>      return ret;
>  }
>  
> -static coroutine_fn BlockDriverAIOCB *raw_aio_discard(BlockDriverState *bs,
> +static coroutine_fn BlockAIOCB *raw_aio_discard(BlockDriverState *bs,
>      int64_t sector_num, int nb_sectors,
> -    BlockDriverCompletionFunc *cb, void *opaque)
> +    BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVRawState *s = bs->opaque;
>  
> @@ -1871,9 +1871,9 @@ static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
>      return ioctl(s->fd, req, buf);
>  }
>  
> -static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
> +static BlockAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
>          unsigned long int req, void *buf,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVRawState *s = bs->opaque;
>      RawPosixAIOData *acb;
> @@ -1912,9 +1912,9 @@ static int fd_open(BlockDriverState *bs)
>  
>  #endif /* !linux && !FreeBSD */
>  
> -static coroutine_fn BlockDriverAIOCB *hdev_aio_discard(BlockDriverState *bs,
> +static coroutine_fn BlockAIOCB *hdev_aio_discard(BlockDriverState *bs,
>      int64_t sector_num, int nb_sectors,
> -    BlockDriverCompletionFunc *cb, void *opaque)
> +    BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVRawState *s = bs->opaque;
>  
> diff --git a/block/raw-win32.c b/block/raw-win32.c
> index 902eab6..88a2a33 100644
> --- a/block/raw-win32.c
> +++ b/block/raw-win32.c
> @@ -138,9 +138,9 @@ static int aio_worker(void *arg)
>      return ret;
>  }
>  
> -static BlockDriverAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
> +static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque, int type)
> +        BlockCompletionFunc *cb, void *opaque, int type)
>  {
>      RawWin32AIOData *acb = g_slice_new(RawWin32AIOData);
>      ThreadPool *pool;
> @@ -369,9 +369,9 @@ fail:
>      return ret;
>  }
>  
> -static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
> +static BlockAIOCB *raw_aio_readv(BlockDriverState *bs,
>                           int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -                         BlockDriverCompletionFunc *cb, void *opaque)
> +                         BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVRawState *s = bs->opaque;
>      if (s->aio) {
> @@ -383,9 +383,9 @@ static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
>      }
>  }
>  
> -static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
> +static BlockAIOCB *raw_aio_writev(BlockDriverState *bs,
>                            int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -                          BlockDriverCompletionFunc *cb, void *opaque)
> +                          BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVRawState *s = bs->opaque;
>      if (s->aio) {
> @@ -397,8 +397,8 @@ static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
>      }
>  }
>  
> -static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
> -                         BlockDriverCompletionFunc *cb, void *opaque)
> +static BlockAIOCB *raw_aio_flush(BlockDriverState *bs,
> +                         BlockCompletionFunc *cb, void *opaque)
>  {
>      BDRVRawState *s = bs->opaque;
>      return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
> diff --git a/block/raw_bsd.c b/block/raw_bsd.c
> index f82f4c2..401b967 100644
> --- a/block/raw_bsd.c
> +++ b/block/raw_bsd.c
> @@ -129,10 +129,10 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
>      return bdrv_ioctl(bs->file, req, buf);
>  }
>  
> -static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
> -                                       unsigned long int req, void *buf,
> -                                       BlockDriverCompletionFunc *cb,
> -                                       void *opaque)
> +static BlockAIOCB *raw_aio_ioctl(BlockDriverState *bs,
> +                                 unsigned long int req, void *buf,
> +                                 BlockCompletionFunc *cb,
> +                                 void *opaque)
>  {
>      return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque);
>  }
> diff --git a/block/rbd.c b/block/rbd.c
> index ea969e7..ceddc11 100644
> --- a/block/rbd.c
> +++ b/block/rbd.c
> @@ -68,7 +68,7 @@ typedef enum {
>  } RBDAIOCmd;
>  
>  typedef struct RBDAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      QEMUBH *bh;
>      int64_t ret;
>      QEMUIOVector *qiov;
> @@ -542,7 +542,7 @@ static void qemu_rbd_close(BlockDriverState *bs)
>   * Cancel aio. Since we don't reference acb in a non qemu threads,
>   * it is safe to access it here.
>   */
> -static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
> +static void qemu_rbd_aio_cancel(BlockAIOCB *blockacb)
>  {
>      RBDAIOCB *acb = (RBDAIOCB *) blockacb;
>      acb->cancelled = 1;
> @@ -608,13 +608,13 @@ static int rbd_aio_flush_wrapper(rbd_image_t image,
>  #endif
>  }
>  
> -static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
> -                                       int64_t sector_num,
> -                                       QEMUIOVector *qiov,
> -                                       int nb_sectors,
> -                                       BlockDriverCompletionFunc *cb,
> -                                       void *opaque,
> -                                       RBDAIOCmd cmd)
> +static BlockAIOCB *rbd_start_aio(BlockDriverState *bs,
> +                                 int64_t sector_num,
> +                                 QEMUIOVector *qiov,
> +                                 int nb_sectors,
> +                                 BlockCompletionFunc *cb,
> +                                 void *opaque,
> +                                 RBDAIOCmd cmd)
>  {
>      RBDAIOCB *acb;
>      RADOSCB *rcb = NULL;
> @@ -695,32 +695,32 @@ failed:
>      return NULL;
>  }
>  
> -static BlockDriverAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs,
> -                                            int64_t sector_num,
> -                                            QEMUIOVector *qiov,
> -                                            int nb_sectors,
> -                                            BlockDriverCompletionFunc *cb,
> -                                            void *opaque)
> +static BlockAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs,
> +                                      int64_t sector_num,
> +                                      QEMUIOVector *qiov,
> +                                      int nb_sectors,
> +                                      BlockCompletionFunc *cb,
> +                                      void *opaque)
>  {
>      return rbd_start_aio(bs, sector_num, qiov, nb_sectors, cb, opaque,
>                           RBD_AIO_READ);
>  }
>  
> -static BlockDriverAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
> -                                             int64_t sector_num,
> -                                             QEMUIOVector *qiov,
> -                                             int nb_sectors,
> -                                             BlockDriverCompletionFunc *cb,
> -                                             void *opaque)
> +static BlockAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
> +                                       int64_t sector_num,
> +                                       QEMUIOVector *qiov,
> +                                       int nb_sectors,
> +                                       BlockCompletionFunc *cb,
> +                                       void *opaque)
>  {
>      return rbd_start_aio(bs, sector_num, qiov, nb_sectors, cb, opaque,
>                           RBD_AIO_WRITE);
>  }
>  
>  #ifdef LIBRBD_SUPPORTS_AIO_FLUSH
> -static BlockDriverAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs,
> -                                            BlockDriverCompletionFunc *cb,
> -                                            void *opaque)
> +static BlockAIOCB *qemu_rbd_aio_flush(BlockDriverState *bs,
> +                                      BlockCompletionFunc *cb,
> +                                      void *opaque)
>  {
>      return rbd_start_aio(bs, 0, NULL, 0, cb, opaque, RBD_AIO_FLUSH);
>  }
> @@ -896,11 +896,11 @@ static int qemu_rbd_snap_list(BlockDriverState *bs,
>  }
>  
>  #ifdef LIBRBD_SUPPORTS_DISCARD
> -static BlockDriverAIOCB* qemu_rbd_aio_discard(BlockDriverState *bs,
> -                                              int64_t sector_num,
> -                                              int nb_sectors,
> -                                              BlockDriverCompletionFunc *cb,
> -                                              void *opaque)
> +static BlockAIOCB *qemu_rbd_aio_discard(BlockDriverState *bs,
> +                                        int64_t sector_num,
> +                                        int nb_sectors,
> +                                        BlockCompletionFunc *cb,
> +                                        void *opaque)
>  {
>      return rbd_start_aio(bs, sector_num, NULL, nb_sectors, cb, opaque,
>                           RBD_AIO_DISCARD);
> diff --git a/block/sheepdog.c b/block/sheepdog.c
> index f91afc3..86085d3 100644
> --- a/block/sheepdog.c
> +++ b/block/sheepdog.c
> @@ -301,7 +301,7 @@ enum AIOCBState {
>  };
>  
>  struct SheepdogAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>  
>      QEMUIOVector *qiov;
>  
> @@ -477,7 +477,7 @@ static bool sd_acb_cancelable(const SheepdogAIOCB *acb)
>      return true;
>  }
>  
> -static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
> +static void sd_aio_cancel(BlockAIOCB *blockacb)
>  {
>      SheepdogAIOCB *acb = (SheepdogAIOCB *)blockacb;
>      BDRVSheepdogState *s = acb->common.bs->opaque;
> diff --git a/block/stream.c b/block/stream.c
> index cdea3e8..a1dc8da 100644
> --- a/block/stream.c
> +++ b/block/stream.c
> @@ -220,7 +220,7 @@ static const BlockJobDriver stream_job_driver = {
>  void stream_start(BlockDriverState *bs, BlockDriverState *base,
>                    const char *backing_file_str, int64_t speed,
>                    BlockdevOnError on_error,
> -                  BlockDriverCompletionFunc *cb,
> +                  BlockCompletionFunc *cb,
>                    void *opaque, Error **errp)
>  {
>      StreamBlockJob *s;
> diff --git a/block/win32-aio.c b/block/win32-aio.c
> index 5030e32..de273b8 100644
> --- a/block/win32-aio.c
> +++ b/block/win32-aio.c
> @@ -44,7 +44,7 @@ struct QEMUWin32AIOState {
>  };
>  
>  typedef struct QEMUWin32AIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      struct QEMUWin32AIOState *ctx;
>      int nbytes;
>      OVERLAPPED ov;
> @@ -106,7 +106,7 @@ static void win32_aio_completion_cb(EventNotifier *e)
>      }
>  }
>  
> -static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
> +static void win32_aio_cancel(BlockAIOCB *blockacb)
>  {
>      QEMUWin32AIOCB *waiocb = (QEMUWin32AIOCB *)blockacb;
>  
> @@ -124,10 +124,10 @@ static const AIOCBInfo win32_aiocb_info = {
>      .cancel             = win32_aio_cancel,
>  };
>  
> -BlockDriverAIOCB *win32_aio_submit(BlockDriverState *bs,
> +BlockAIOCB *win32_aio_submit(BlockDriverState *bs,
>          QEMUWin32AIOState *aio, HANDLE hfile,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque, int type)
> +        BlockCompletionFunc *cb, void *opaque, int type)
>  {
>      struct QEMUWin32AIOCB *waiocb;
>      uint64_t offset = sector_num * 512;
> diff --git a/blockjob.c b/blockjob.c
> index 3af0f6c..ff0908a 100644
> --- a/blockjob.c
> +++ b/blockjob.c
> @@ -36,7 +36,7 @@
>  #include "qapi-event.h"
>  
>  void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
> -                       int64_t speed, BlockDriverCompletionFunc *cb,
> +                       int64_t speed, BlockCompletionFunc *cb,
>                         void *opaque, Error **errp)
>  {
>      BlockJob *job;
> @@ -155,7 +155,7 @@ void block_job_iostatus_reset(BlockJob *job)
>  
>  struct BlockCancelData {
>      BlockJob *job;
> -    BlockDriverCompletionFunc *cb;
> +    BlockCompletionFunc *cb;
>      void *opaque;
>      bool cancelled;
>      int ret;
> diff --git a/dma-helpers.c b/dma-helpers.c
> index 499b52b..e7bea06 100644
> --- a/dma-helpers.c
> +++ b/dma-helpers.c
> @@ -67,9 +67,9 @@ void qemu_sglist_destroy(QEMUSGList *qsg)
>  }
>  
>  typedef struct {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      BlockDriverState *bs;
> -    BlockDriverAIOCB *acb;
> +    BlockAIOCB *acb;
>      QEMUSGList *sg;
>      uint64_t sector_num;
>      DMADirection dir;
> @@ -179,14 +179,14 @@ static void dma_bdrv_cb(void *opaque, int ret)
>      assert(dbs->acb);
>  }
>  
> -static void dma_aio_cancel(BlockDriverAIOCB *acb)
> +static void dma_aio_cancel(BlockAIOCB *acb)
>  {
>      DMAAIOCB *dbs = container_of(acb, DMAAIOCB, common);
>  
>      trace_dma_aio_cancel(dbs);
>  
>      if (dbs->acb) {
> -        BlockDriverAIOCB *acb = dbs->acb;
> +        BlockAIOCB *acb = dbs->acb;
>          dbs->acb = NULL;
>          dbs->in_cancel = true;
>          bdrv_aio_cancel(acb);
> @@ -201,9 +201,9 @@ static const AIOCBInfo dma_aiocb_info = {
>      .cancel             = dma_aio_cancel,
>  };
>  
> -BlockDriverAIOCB *dma_bdrv_io(
> +BlockAIOCB *dma_bdrv_io(
>      BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,
> -    DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
> +    DMAIOFunc *io_func, BlockCompletionFunc *cb,
>      void *opaque, DMADirection dir)
>  {
>      DMAAIOCB *dbs = qemu_aio_get(&dma_aiocb_info, bs, cb, opaque);
> @@ -226,17 +226,17 @@ BlockDriverAIOCB *dma_bdrv_io(
>  }
>  
>  
> -BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
> -                                QEMUSGList *sg, uint64_t sector,
> -                                void (*cb)(void *opaque, int ret), void *opaque)
> +BlockAIOCB *dma_bdrv_read(BlockDriverState *bs,
> +                          QEMUSGList *sg, uint64_t sector,
> +                          void (*cb)(void *opaque, int ret), void *opaque)
>  {
>      return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque,
>                         DMA_DIRECTION_FROM_DEVICE);
>  }
>  
> -BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
> -                                 QEMUSGList *sg, uint64_t sector,
> -                                 void (*cb)(void *opaque, int ret), void *opaque)
> +BlockAIOCB *dma_bdrv_write(BlockDriverState *bs,
> +                           QEMUSGList *sg, uint64_t sector,
> +                           void (*cb)(void *opaque, int ret), void *opaque)
>  {
>      return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque,
>                         DMA_DIRECTION_TO_DEVICE);
> diff --git a/hw/block/nvme.h b/hw/block/nvme.h
> index bd8fc3e..993c511 100644
> --- a/hw/block/nvme.h
> +++ b/hw/block/nvme.h
> @@ -636,7 +636,7 @@ typedef struct NvmeAsyncEvent {
>  
>  typedef struct NvmeRequest {
>      struct NvmeSQueue       *sq;
> -    BlockDriverAIOCB        *aiocb;
> +    BlockAIOCB              *aiocb;
>      uint16_t                status;
>      NvmeCqe                 cqe;
>      BlockAcctCookie         acct;
> diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
> index 0ee713b..97c997c 100644
> --- a/hw/ide/ahci.c
> +++ b/hw/ide/ahci.c
> @@ -1104,7 +1104,7 @@ out:
>  }
>  
>  static void ahci_start_dma(IDEDMA *dma, IDEState *s,
> -                           BlockDriverCompletionFunc *dma_cb)
> +                           BlockCompletionFunc *dma_cb)
>  {
>  #ifdef DEBUG_AHCI
>      AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
> diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
> index 1543df7..fe32eab 100644
> --- a/hw/ide/ahci.h
> +++ b/hw/ide/ahci.h
> @@ -241,7 +241,7 @@ typedef struct AHCIDevice AHCIDevice;
>  
>  typedef struct NCQTransferState {
>      AHCIDevice *drive;
> -    BlockDriverAIOCB *aiocb;
> +    BlockAIOCB *aiocb;
>      QEMUSGList sglist;
>      BlockAcctCookie acct;
>      uint16_t sector_count;
> diff --git a/hw/ide/core.c b/hw/ide/core.c
> index 191f893..36df217 100644
> --- a/hw/ide/core.c
> +++ b/hw/ide/core.c
> @@ -360,15 +360,15 @@ static void ide_set_signature(IDEState *s)
>  }
>  
>  typedef struct TrimAIOCB {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      QEMUBH *bh;
>      int ret;
>      QEMUIOVector *qiov;
> -    BlockDriverAIOCB *aiocb;
> +    BlockAIOCB *aiocb;
>      int i, j;
>  } TrimAIOCB;
>  
> -static void trim_aio_cancel(BlockDriverAIOCB *acb)
> +static void trim_aio_cancel(BlockAIOCB *acb)
>  {
>      TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
>  
> @@ -440,9 +440,9 @@ static void ide_issue_trim_cb(void *opaque, int ret)
>      }
>  }
>  
> -BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
> +BlockAIOCB *ide_issue_trim(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      TrimAIOCB *iocb;
>  
> @@ -784,7 +784,7 @@ static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
>      ide_start_dma(s, ide_dma_cb);
>  }
>  
> -void ide_start_dma(IDEState *s, BlockDriverCompletionFunc *cb)
> +void ide_start_dma(IDEState *s, BlockCompletionFunc *cb)
>  {
>      if (s->bus->dma->ops->start_dma) {
>          s->bus->dma->ops->start_dma(s->bus->dma, s, cb);
> diff --git a/hw/ide/internal.h b/hw/ide/internal.h
> index 5c19f79..9314c80 100644
> --- a/hw/ide/internal.h
> +++ b/hw/ide/internal.h
> @@ -319,7 +319,7 @@ typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind;
>  
>  typedef void EndTransferFunc(IDEState *);
>  
> -typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *);
> +typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *);
>  typedef void DMAVoidFunc(IDEDMA *);
>  typedef int DMAIntFunc(IDEDMA *, int);
>  typedef void DMAStopFunc(IDEDMA *, bool);
> @@ -389,7 +389,7 @@ struct IDEState {
>      int cd_sector_size;
>      int atapi_dma; /* true if dma is requested for the packet cmd */
>      BlockAcctCookie acct;
> -    BlockDriverAIOCB *pio_aiocb;
> +    BlockAIOCB *pio_aiocb;
>      struct iovec iov;
>      QEMUIOVector qiov;
>      /* ATA DMA state */
> @@ -442,7 +442,7 @@ struct IDEDMA {
>      const struct IDEDMAOps *ops;
>      struct iovec iov;
>      QEMUIOVector qiov;
> -    BlockDriverAIOCB *aiocb;
> +    BlockAIOCB *aiocb;
>  };
>  
>  struct IDEBus {
> @@ -521,7 +521,7 @@ void ide_bus_reset(IDEBus *bus);
>  int64_t ide_get_sector(IDEState *s);
>  void ide_set_sector(IDEState *s, int64_t sector_num);
>  
> -void ide_start_dma(IDEState *s, BlockDriverCompletionFunc *cb);
> +void ide_start_dma(IDEState *s, BlockCompletionFunc *cb);
>  void ide_dma_error(IDEState *s);
>  
>  void ide_atapi_cmd_ok(IDEState *s);
> @@ -555,9 +555,9 @@ void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
>                          EndTransferFunc *end_transfer_func);
>  void ide_transfer_stop(IDEState *s);
>  void ide_set_inactive(IDEState *s, bool more);
> -BlockDriverAIOCB *ide_issue_trim(BlockDriverState *bs,
> +BlockAIOCB *ide_issue_trim(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> +        BlockCompletionFunc *cb, void *opaque);
>  
>  /* hw/ide/atapi.c */
>  void ide_atapi_cmd(IDEState *s);
> diff --git a/hw/ide/macio.c b/hw/ide/macio.c
> index b0c0d40..371e172 100644
> --- a/hw/ide/macio.c
> +++ b/hw/ide/macio.c
> @@ -555,7 +555,7 @@ static void ide_nop_restart(void *opaque, int x, RunState y)
>  }
>  
>  static void ide_dbdma_start(IDEDMA *dma, IDEState *s,
> -                            BlockDriverCompletionFunc *cb)
> +                            BlockCompletionFunc *cb)
>  {
>      MACIOIDEState *m = container_of(dma, MACIOIDEState, dma);
>  
> diff --git a/hw/ide/pci.c b/hw/ide/pci.c
> index 2397f35..6ff1c58 100644
> --- a/hw/ide/pci.c
> +++ b/hw/ide/pci.c
> @@ -38,7 +38,7 @@
>          IDE_RETRY_READ | IDE_RETRY_FLUSH)
>  
>  static void bmdma_start_dma(IDEDMA *dma, IDEState *s,
> -                            BlockDriverCompletionFunc *dma_cb)
> +                            BlockCompletionFunc *dma_cb)
>  {
>      BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
>  
> diff --git a/hw/ide/pci.h b/hw/ide/pci.h
> index 517711f..2e9314a 100644
> --- a/hw/ide/pci.h
> +++ b/hw/ide/pci.h
> @@ -23,7 +23,7 @@ typedef struct BMDMAState {
>      uint32_t cur_prd_addr;
>      uint32_t cur_prd_len;
>      uint8_t unit;
> -    BlockDriverCompletionFunc *dma_cb;
> +    BlockCompletionFunc *dma_cb;
>      int64_t sector_num;
>      uint32_t nsector;
>      MemoryRegion addr_ioport;
> diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
> index aff2b9a..8bdba30 100644
> --- a/hw/ppc/mac.h
> +++ b/hw/ppc/mac.h
> @@ -131,7 +131,7 @@ typedef struct MACIOIDEState {
>  
>      MemoryRegion mem;
>      IDEBus bus;
> -    BlockDriverAIOCB *aiocb;
> +    BlockAIOCB *aiocb;
>      IDEDMA dma;
>      void *dbdma;
>      bool dma_active;
> diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
> index 20587b4..5301886 100644
> --- a/hw/scsi/scsi-generic.c
> +++ b/hw/scsi/scsi-generic.c
> @@ -157,7 +157,7 @@ static void scsi_cancel_io(SCSIRequest *req)
>  
>  static int execute_command(BlockDriverState *bdrv,
>                             SCSIGenericReq *r, int direction,
> -			   BlockDriverCompletionFunc *complete)
> +                           BlockCompletionFunc *complete)
>  {
>      r->io_header.interface_id = 'S';
>      r->io_header.dxfer_direction = direction;
> diff --git a/include/block/aio.h b/include/block/aio.h
> index 4603c0f..57619ab 100644
> --- a/include/block/aio.h
> +++ b/include/block/aio.h
> @@ -22,23 +22,23 @@
>  #include "qemu/rfifolock.h"
>  #include "qemu/timer.h"
>  
> -typedef struct BlockDriverAIOCB BlockDriverAIOCB;
> -typedef void BlockDriverCompletionFunc(void *opaque, int ret);
> +typedef struct BlockAIOCB BlockAIOCB;
> +typedef void BlockCompletionFunc(void *opaque, int ret);
>  
>  typedef struct AIOCBInfo {
> -    void (*cancel)(BlockDriverAIOCB *acb);
> +    void (*cancel)(BlockAIOCB *acb);
>      size_t aiocb_size;
>  } AIOCBInfo;
>  
> -struct BlockDriverAIOCB {
> +struct BlockAIOCB {
>      const AIOCBInfo *aiocb_info;
>      BlockDriverState *bs;
> -    BlockDriverCompletionFunc *cb;
> +    BlockCompletionFunc *cb;
>      void *opaque;
>  };
>  
>  void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
> -                   BlockDriverCompletionFunc *cb, void *opaque);
> +                   BlockCompletionFunc *cb, void *opaque);
>  void qemu_aio_release(void *p);
>  
>  typedef struct AioHandler AioHandler;
> diff --git a/include/block/block.h b/include/block/block.h
> index fb4fff9..15a5290 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -246,9 +246,9 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
>                 const uint8_t *buf, int nb_sectors);
>  int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
>                 int nb_sectors, BdrvRequestFlags flags);
> -BlockDriverAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, int64_t sector_num,
> -                                        int nb_sectors, BdrvRequestFlags flags,
> -                                        BlockDriverCompletionFunc *cb, void *opaque);
> +BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs, int64_t sector_num,
> +                                  int nb_sectors, BdrvRequestFlags flags,
> +                                  BlockCompletionFunc *cb, void *opaque);
>  int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags);
>  int bdrv_pread(BlockDriverState *bs, int64_t offset,
>                 void *buf, int count);
> @@ -324,18 +324,18 @@ BlockDriverState *check_to_replace_node(const char *node_name, Error **errp);
>  /* async block I/O */
>  typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector,
>                                       int sector_num);
> -BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
> -                                 QEMUIOVector *iov, int nb_sectors,
> -                                 BlockDriverCompletionFunc *cb, void *opaque);
> -BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
> -                                  QEMUIOVector *iov, int nb_sectors,
> -                                  BlockDriverCompletionFunc *cb, void *opaque);
> -BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
> -                                 BlockDriverCompletionFunc *cb, void *opaque);
> -BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
> -                                   int64_t sector_num, int nb_sectors,
> -                                   BlockDriverCompletionFunc *cb, void *opaque);
> -void bdrv_aio_cancel(BlockDriverAIOCB *acb);
> +BlockAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
> +                           QEMUIOVector *iov, int nb_sectors,
> +                           BlockCompletionFunc *cb, void *opaque);
> +BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
> +                            QEMUIOVector *iov, int nb_sectors,
> +                            BlockCompletionFunc *cb, void *opaque);
> +BlockAIOCB *bdrv_aio_flush(BlockDriverState *bs,
> +                           BlockCompletionFunc *cb, void *opaque);
> +BlockAIOCB *bdrv_aio_discard(BlockDriverState *bs,
> +                             int64_t sector_num, int nb_sectors,
> +                             BlockCompletionFunc *cb, void *opaque);
> +void bdrv_aio_cancel(BlockAIOCB *acb);
>  
>  typedef struct BlockRequest {
>      /* Fields to be filled by multiwrite caller */
> @@ -343,7 +343,7 @@ typedef struct BlockRequest {
>      int nb_sectors;
>      int flags;
>      QEMUIOVector *qiov;
> -    BlockDriverCompletionFunc *cb;
> +    BlockCompletionFunc *cb;
>      void *opaque;
>  
>      /* Filled by multiwrite implementation */
> @@ -355,9 +355,9 @@ int bdrv_aio_multiwrite(BlockDriverState *bs, BlockRequest *reqs,
>  
>  /* sg packet commands */
>  int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf);
> -BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
> +BlockAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
>          unsigned long int req, void *buf,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> +        BlockCompletionFunc *cb, void *opaque);
>  
>  /* Invalidate any cached metadata used by image formats */
>  void bdrv_invalidate_cache(BlockDriverState *bs, Error **errp);
> diff --git a/include/block/block_int.h b/include/block/block_int.h
> index 08ccb27..b3246e7 100644
> --- a/include/block/block_int.h
> +++ b/include/block/block_int.h
> @@ -127,17 +127,17 @@ struct BlockDriver {
>      void (*bdrv_refresh_filename)(BlockDriverState *bs);
>  
>      /* aio */
> -    BlockDriverAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs,
> +    BlockAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> -    BlockDriverAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs,
> +        BlockCompletionFunc *cb, void *opaque);
> +    BlockAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs,
>          int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> -    BlockDriverAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> -    BlockDriverAIOCB *(*bdrv_aio_discard)(BlockDriverState *bs,
> +        BlockCompletionFunc *cb, void *opaque);
> +    BlockAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
> +        BlockCompletionFunc *cb, void *opaque);
> +    BlockAIOCB *(*bdrv_aio_discard)(BlockDriverState *bs,
>          int64_t sector_num, int nb_sectors,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> +        BlockCompletionFunc *cb, void *opaque);
>  
>      int coroutine_fn (*bdrv_co_readv)(BlockDriverState *bs,
>          int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
> @@ -217,9 +217,9 @@ struct BlockDriver {
>  
>      /* to control generic scsi devices */
>      int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
> -    BlockDriverAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
> +    BlockAIOCB *(*bdrv_aio_ioctl)(BlockDriverState *bs,
>          unsigned long int req, void *buf,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> +        BlockCompletionFunc *cb, void *opaque);
>  
>      /* List of options for creating images, terminated by name == NULL */
>      QemuOptsList *create_opts;
> @@ -501,7 +501,7 @@ int is_windows_drive(const char *filename);
>   */
>  void stream_start(BlockDriverState *bs, BlockDriverState *base,
>                    const char *base_id, int64_t speed, BlockdevOnError on_error,
> -                  BlockDriverCompletionFunc *cb,
> +                  BlockCompletionFunc *cb,
>                    void *opaque, Error **errp);
>  
>  /**
> @@ -519,7 +519,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
>   */
>  void commit_start(BlockDriverState *bs, BlockDriverState *base,
>                   BlockDriverState *top, int64_t speed,
> -                 BlockdevOnError on_error, BlockDriverCompletionFunc *cb,
> +                 BlockdevOnError on_error, BlockCompletionFunc *cb,
>                   void *opaque, const char *backing_file_str, Error **errp);
>  /**
>   * commit_active_start:
> @@ -535,7 +535,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
>  void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
>                           int64_t speed,
>                           BlockdevOnError on_error,
> -                         BlockDriverCompletionFunc *cb,
> +                         BlockCompletionFunc *cb,
>                           void *opaque, Error **errp);
>  /*
>   * mirror_start:
> @@ -563,7 +563,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
>                    int64_t speed, int64_t granularity, int64_t buf_size,
>                    MirrorSyncMode mode, BlockdevOnError on_source_error,
>                    BlockdevOnError on_target_error,
> -                  BlockDriverCompletionFunc *cb,
> +                  BlockCompletionFunc *cb,
>                    void *opaque, Error **errp);
>  
>  /*
> @@ -584,7 +584,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
>                    int64_t speed, MirrorSyncMode sync_mode,
>                    BlockdevOnError on_source_error,
>                    BlockdevOnError on_target_error,
> -                  BlockDriverCompletionFunc *cb, void *opaque,
> +                  BlockCompletionFunc *cb, void *opaque,
>                    Error **errp);
>  
>  #endif /* BLOCK_INT_H */
> diff --git a/include/block/blockjob.h b/include/block/blockjob.h
> index 60aa835..acb399f 100644
> --- a/include/block/blockjob.h
> +++ b/include/block/blockjob.h
> @@ -104,7 +104,7 @@ struct BlockJob {
>      int64_t speed;
>  
>      /** The completion function that will be called when the job completes.  */
> -    BlockDriverCompletionFunc *cb;
> +    BlockCompletionFunc *cb;
>  
>      /** Block other operations when block job is running */
>      Error *blocker;
> @@ -132,7 +132,7 @@ struct BlockJob {
>   * called from a wrapper that is specific to the job type.
>   */
>  void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs,
> -                       int64_t speed, BlockDriverCompletionFunc *cb,
> +                       int64_t speed, BlockCompletionFunc *cb,
>                         void *opaque, Error **errp);
>  
>  /**
> diff --git a/include/block/thread-pool.h b/include/block/thread-pool.h
> index 4723752..42eb5e8 100644
> --- a/include/block/thread-pool.h
> +++ b/include/block/thread-pool.h
> @@ -27,9 +27,9 @@ typedef struct ThreadPool ThreadPool;
>  ThreadPool *thread_pool_new(struct AioContext *ctx);
>  void thread_pool_free(ThreadPool *pool);
>  
> -BlockDriverAIOCB *thread_pool_submit_aio(ThreadPool *pool,
> +BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
>          ThreadPoolFunc *func, void *arg,
> -        BlockDriverCompletionFunc *cb, void *opaque);
> +        BlockCompletionFunc *cb, void *opaque);
>  int coroutine_fn thread_pool_submit_co(ThreadPool *pool,
>          ThreadPoolFunc *func, void *arg);
>  void thread_pool_submit(ThreadPool *pool, ThreadPoolFunc *func, void *arg);
> diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
> index 2e3a8f9..e3e27cb 100644
> --- a/include/hw/scsi/scsi.h
> +++ b/include/hw/scsi/scsi.h
> @@ -52,7 +52,7 @@ struct SCSIRequest {
>      uint32_t          status;
>      size_t            resid;
>      SCSICommand       cmd;
> -    BlockDriverAIOCB  *aiocb;
> +    BlockAIOCB        *aiocb;
>      QEMUSGList        *sg;
>      bool              dma_started;
>      uint8_t sense[SCSI_SENSE_BUF_SIZE];
> diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
> index 78a5fc8..47606d0 100644
> --- a/include/monitor/monitor.h
> +++ b/include/monitor/monitor.h
> @@ -27,10 +27,10 @@ int monitor_suspend(Monitor *mon);
>  void monitor_resume(Monitor *mon);
>  
>  int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
> -                                BlockDriverCompletionFunc *completion_cb,
> +                                BlockCompletionFunc *completion_cb,
>                                  void *opaque);
>  int monitor_read_block_device_key(Monitor *mon, const char *device,
> -                                  BlockDriverCompletionFunc *completion_cb,
> +                                  BlockCompletionFunc *completion_cb,
>                                    void *opaque);
>  
>  int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp);
> diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
> index 00f21f3..464f9f7 100644
> --- a/include/sysemu/dma.h
> +++ b/include/sysemu/dma.h
> @@ -196,20 +196,20 @@ void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
>  void qemu_sglist_destroy(QEMUSGList *qsg);
>  #endif
>  
> -typedef BlockDriverAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
> -                                 QEMUIOVector *iov, int nb_sectors,
> -                                 BlockDriverCompletionFunc *cb, void *opaque);
> +typedef BlockAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
> +                              QEMUIOVector *iov, int nb_sectors,
> +                              BlockCompletionFunc *cb, void *opaque);
>  
> -BlockDriverAIOCB *dma_bdrv_io(BlockDriverState *bs,
> -                              QEMUSGList *sg, uint64_t sector_num,
> -                              DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
> -                              void *opaque, DMADirection dir);
> -BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
> -                                QEMUSGList *sg, uint64_t sector,
> -                                BlockDriverCompletionFunc *cb, void *opaque);
> -BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
> -                                 QEMUSGList *sg, uint64_t sector,
> -                                 BlockDriverCompletionFunc *cb, void *opaque);
> +BlockAIOCB *dma_bdrv_io(BlockDriverState *bs,
> +                        QEMUSGList *sg, uint64_t sector_num,
> +                        DMAIOFunc *io_func, BlockCompletionFunc *cb,
> +                        void *opaque, DMADirection dir);
> +BlockAIOCB *dma_bdrv_read(BlockDriverState *bs,
> +                          QEMUSGList *sg, uint64_t sector,
> +                          BlockCompletionFunc *cb, void *opaque);
> +BlockAIOCB *dma_bdrv_write(BlockDriverState *bs,
> +                           QEMUSGList *sg, uint64_t sector,
> +                           BlockCompletionFunc *cb, void *opaque);
>  uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
>  uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
>  
> diff --git a/monitor.c b/monitor.c
> index 4ae66df..eaa6de7 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -206,7 +206,7 @@ struct Monitor {
>      ReadLineState *rs;
>      MonitorControl *mc;
>      CPUState *mon_cpu;
> -    BlockDriverCompletionFunc *password_completion_cb;
> +    BlockCompletionFunc *password_completion_cb;
>      void *password_opaque;
>      mon_cmd_t *cmd_table;
>      QError *error;
> @@ -5361,7 +5361,7 @@ ReadLineState *monitor_get_rs(Monitor *mon)
>  }
>  
>  int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
> -                                BlockDriverCompletionFunc *completion_cb,
> +                                BlockCompletionFunc *completion_cb,
>                                  void *opaque)
>  {
>      int err;
> @@ -5393,7 +5393,7 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
>  }
>  
>  int monitor_read_block_device_key(Monitor *mon, const char *device,
> -                                  BlockDriverCompletionFunc *completion_cb,
> +                                  BlockCompletionFunc *completion_cb,
>                                    void *opaque)
>  {
>      BlockDriverState *bs;
> diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
> index f40b7fc..acc911b 100644
> --- a/tests/test-thread-pool.c
> +++ b/tests/test-thread-pool.c
> @@ -10,7 +10,7 @@ static ThreadPool *pool;
>  static int active;
>  
>  typedef struct {
> -    BlockDriverAIOCB *aiocb;
> +    BlockAIOCB *aiocb;
>      int n;
>      int ret;
>  } WorkerTestData;
> diff --git a/thread-pool.c b/thread-pool.c
> index bc07d7a..f9e9901 100644
> --- a/thread-pool.c
> +++ b/thread-pool.c
> @@ -35,7 +35,7 @@ enum ThreadState {
>  };
>  
>  struct ThreadPoolElement {
> -    BlockDriverAIOCB common;
> +    BlockAIOCB common;
>      ThreadPool *pool;
>      ThreadPoolFunc *func;
>      void *arg;
> @@ -201,7 +201,7 @@ restart:
>      }
>  }
>  
> -static void thread_pool_cancel(BlockDriverAIOCB *acb)
> +static void thread_pool_cancel(BlockAIOCB *acb)
>  {
>      ThreadPoolElement *elem = (ThreadPoolElement *)acb;
>      ThreadPool *pool = elem->pool;
> @@ -235,9 +235,9 @@ static const AIOCBInfo thread_pool_aiocb_info = {
>      .cancel             = thread_pool_cancel,
>  };
>  
> -BlockDriverAIOCB *thread_pool_submit_aio(ThreadPool *pool,
> +BlockAIOCB *thread_pool_submit_aio(ThreadPool *pool,
>          ThreadPoolFunc *func, void *arg,
> -        BlockDriverCompletionFunc *cb, void *opaque)
> +        BlockCompletionFunc *cb, void *opaque)
>  {
>      ThreadPoolElement *req;
>  
> -- 
> 1.9.3
> 

I think you should rebase this on top of Fam's null driver.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[]
  2014-09-11 11:34   ` Benoît Canet
  2014-09-11 11:43     ` Benoît Canet
@ 2014-09-11 13:00     ` Eric Blake
  2014-09-11 13:18       ` Benoît Canet
  2014-09-11 19:01     ` Markus Armbruster
  2 siblings, 1 reply; 76+ messages in thread
From: Eric Blake @ 2014-09-11 13:00 UTC (permalink / raw)
  To: Benoît Canet, Markus Armbruster; +Cc: kwolf, famz, qemu-devel, stefanha

[-- Attachment #1: Type: text/plain, Size: 2054 bytes --]

On 09/11/2014 05:34 AM, Benoît Canet wrote:
> The Wednesday 10 Sep 2014 à 10:13:37 (+0200), Markus Armbruster wrote :
>> device_name[] is can become non-empty only in bdrv_new_named() and
>> bdrv_move_feature_fields().  The latter is used only to undo damage
>> done by bdrv_swap().  The former is called only by blk_new_with_bs().
>> Therefore, when a BlockDriverState's device_name[] is non-empty, then
>> it's owned by a BlockBackend.

[lots of lines trimmed - it's not only okay, but desirable to trim out
portions of a patch that you are okay with, in order to call attention
to the problem spots that you are commenting on without making the
reader have to scroll through pages of quoted context]

>>  
>> -const char *bdrv_get_device_name(BlockDriverState *bs)
>> +const char *bdrv_get_device_name(const BlockDriverState *bs)
>>  {
>> -    return bs->device_name;
>> +    const char *name = bs->blk ? blk_name(bs->blk) : NULL;
>> +    return name ?: "";
>>  }
> 
> Why not ?
> 
>     return bs->blk ? blk_name(bs->blk) : "";

If I understand right, it was because blk_name(bs->blk) may return NULL,
but this function is guaranteed to return non-NULL.

> 
> or 
> 
>     if (bs->blk) {
>         return blk_name(bs->blk);
>     }
> 
>     return "";
> 
> Would it fail to do the job ?
> 
> Also we could have made sure that bdrv_get_device_name return either
> a non empty string or NULL.
> 
> (We know blk_name will return a non empty string it's asserted)
> 
> This would need to change a few test all around the code but the final
> code logic would be less convoluted:
> -convert NULL to "" then test for not ""
> would turn into
> -return NULL test for not NULL

Indeed, the logic of NULL vs. string is slightly easier than the logic
of "" vs non-empty string; if we can guarantee that a non-NULL string
will be non-empty.  I'm not sure how much churn it would cause, though.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[]
  2014-09-11 13:00     ` Eric Blake
@ 2014-09-11 13:18       ` Benoît Canet
  2014-09-11 19:11         ` Markus Armbruster
  0 siblings, 1 reply; 76+ messages in thread
From: Benoît Canet @ 2014-09-11 13:18 UTC (permalink / raw)
  To: Eric Blake
  Cc: Benoît Canet, kwolf, famz, Markus Armbruster, qemu-devel, stefanha

The Thursday 11 Sep 2014 à 07:00:41 (-0600), Eric Blake wrote :
> On 09/11/2014 05:34 AM, Benoît Canet wrote:
> > The Wednesday 10 Sep 2014 à 10:13:37 (+0200), Markus Armbruster wrote :
> >> device_name[] is can become non-empty only in bdrv_new_named() and
> >> bdrv_move_feature_fields().  The latter is used only to undo damage
> >> done by bdrv_swap().  The former is called only by blk_new_with_bs().
> >> Therefore, when a BlockDriverState's device_name[] is non-empty, then
> >> it's owned by a BlockBackend.
> 
> [lots of lines trimmed - it's not only okay, but desirable to trim out
> portions of a patch that you are okay with, in order to call attention
> to the problem spots that you are commenting on without making the
> reader have to scroll through pages of quoted context]
> 
> >>  
> >> -const char *bdrv_get_device_name(BlockDriverState *bs)
> >> +const char *bdrv_get_device_name(const BlockDriverState *bs)
> >>  {
> >> -    return bs->device_name;
> >> +    const char *name = bs->blk ? blk_name(bs->blk) : NULL;
> >> +    return name ?: "";
> >>  }
> > 
> > Why not ?
> > 
> >     return bs->blk ? blk_name(bs->blk) : "";
> 
> If I understand right, it was because blk_name(bs->blk) may return NULL,

It think it can't: see patch 2 extract:

> +BlockBackend *blk_new(const char *name, Error **errp)
> +{
> +    BlockBackend *blk = g_new0(BlockBackend, 1);
> +     
> +    assert(name && name[0]);

> but this function is guaranteed to return non-NULL.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] block: New BlockBackend
  2014-09-11 10:03     ` Markus Armbruster
  2014-09-11 11:45       ` Markus Armbruster
@ 2014-09-11 14:38       ` Markus Armbruster
  1 sibling, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 14:38 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: benoit.canet, famz, qemu-devel, stefanha

Markus Armbruster <armbru@redhat.com> writes:

> Kevin Wolf <kwolf@redhat.com> writes:
[...]
>>> diff --git a/blockdev.c b/blockdev.c
>>> index 9fbd888..86596bc 100644
>>> --- a/blockdev.c
>>> +++ b/blockdev.c
[...]
>>> @@ -1770,7 +1778,7 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>>>       */
>>>      if (bdrv_get_attached_dev(bs)) {
>>>          bdrv_make_anon(bs);
>>> -
>>> +        blk_unref(blk_by_name(id));
>>>          /* Further I/O must not pause the guest */
>>>          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
>>>                            BLOCKDEV_ON_ERROR_REPORT);
>>
>> Won't we unref the BB a second time now when unplugging the device?
>> (drive_del() called in blockdev_auto_del())
>
> Short answer: you're right, there's a bug, and I'll fix it.
>
> Long answer: this part is hairy, because the drive_del command is badly
> designed.
[...]
> Simplest possible solution: I hide the BB here, and *leak* it (with a
> fat FIXME comment) until it becomes easy enough to find.  I guess I can
> find it right in the next patch.

Nevermind, I found a tolerable way to avoid the temporary leak.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState
  2014-09-10 12:24   ` Kevin Wolf
@ 2014-09-11 15:27     ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 15:27 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: benoit.canet, famz, qemu-devel, stefanha

Kevin Wolf <kwolf@redhat.com> writes:

> Am 10.09.2014 um 10:13 hat Markus Armbruster geschrieben:
>> The pointer from BlockBackend to BlockDriverState is a strong
>> reference, managed with bdrv_ref() / bdrv_unref(), the back-pointer is
>> a weak one.
>> 
>> Convenience function blk_new_with_bs() creates a BlockBackend with its
>> BlockDriverState.  Callers have to unref both.  The commit after next
>> will relieve them of the need to unref the BlockDriverState.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>
> I'm wondering whether this is the right direction to take. In creating a
> block device, we have the following operations:
>
> 1. Create a BlockBackend
> 2. Create a BlockDriverState
> 3. Open the BlockDriverState
>
> bdrv_open() can do 2 and 3, which is probably what we want to have in
> the end - new/create and delete/close should be a single operation for
> BDSes.

Agreed.

> Combining 1 and 2 into a single function might make it harder to actually
> use bdrv_open() in this way.

Not really.

Before my series, callers all look like:

    bs = bdrv_new(name, errp);
    if (!bs) {
        [bail out]
    }
    [stuff...]
    ret = bdrv_open(&bs, [...]);
    if (ret < 0) {
        [bail out, unreffing blk and bdrv (only blk after PATCH 05]
    }

Fusing bdrv_new() and bdrv_open() into bdrv_open_new() would make it
look like:

    [stuff'...]
    bs = bdrv_open_new([...]);
    if (!bs) {
        [bail out]
    }
    [stuff''...]

Transforming [stuff...] may take some thought.

Now let's consider how my patch affects such a future fusion.  After my
patch, we have:

    blk = blk_new_with_bs(name, errp);
    if (!blk) {
        [bail out]
    }
    bs = blk_bs(blk);
    [stuff...]
    ret = bdrv_open(&bs, [...]);
    if (ret < 0) {
        [bail out, unreffing blk and bdrv (only blk after PATCH 05]
    }

Avoiding the convenience function would make it look like:

    blk = blk_new(name, errp);
    if (!blk) {
        [bail out]
    }
    bs = bdrv_new_named(name, errp);
    if (!bs) {
        [bail out, unreffing blk]
    }
    blk_attach_bs(blk, bs);
    [stuff...]
    ret = bdrv_open(&bs, [...]);
    if (ret < 0) {
        [bail out, unreffing blk and bdrv (only blk after PATCH 05]
    }

More verbose, and more complicated error handling.  Okay if it really
buys us something.  Let's fuse and see:

    [stuff'...]
    blk = blk_new(name, errp);
    if (!blk) {
        [bail out]
    }
    [stuff''...]
    ret = bdrv_open(&bs, [...]);
    if (ret < 0) {
        [bail out, unreffing blk]
    }
    [stuff'''...]

As above, transforming [stuff...] may take some thought.  Having to
inline the convenience function, however, is utterly trivial, and
doesn't make the fusing any harder.

>> diff --git a/blockdev.c b/blockdev.c
>> index 86596bc..0a0b95e 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -304,6 +304,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      int bdrv_flags = 0;
>>      int on_read_error, on_write_error;
>>      BlockBackend *blk;
>> +    BlockDriverState *bs;
>>      DriveInfo *dinfo;
>>      ThrottleConfig cfg;
>>      int snapshot = 0;
>> @@ -459,30 +460,28 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      }
>>  
>>      /* init */
>> -    blk = blk_new(qemu_opts_id(opts), errp);
>> +    blk = blk_new_with_bs(qemu_opts_id(opts), errp);
>>      if (!blk) {
>>          goto early_err;
>>      }
>> +    bs = blk_bs(blk);
>> +    bs->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
>> +    bs->read_only = ro;
>> +    bs->detect_zeroes = detect_zeroes;
>> +
>> +    bdrv_set_on_error(bs, on_read_error, on_write_error);
>> +
>> +    /* disk I/O throttling */
>> +    if (throttle_enabled(&cfg)) {
>> +        bdrv_io_limits_enable(bs);
>> +        bdrv_set_io_limits(bs, &cfg);
>> +    }
>> +
>>      dinfo = g_malloc0(sizeof(*dinfo));
>>      dinfo->id = g_strdup(qemu_opts_id(opts));
>> -    dinfo->bdrv = bdrv_new_named(dinfo->id, &error);
>> -    if (error) {
>> -        error_propagate(errp, error);
>> -        goto bdrv_new_err;
>> -    }
>> -    dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
>> -    dinfo->bdrv->read_only = ro;
>> -    dinfo->bdrv->detect_zeroes = detect_zeroes;
>> +    dinfo->bdrv = bs;
>>      QTAILQ_INSERT_TAIL(&drives, dinfo, next);
>>  
>> -    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
>> -
>> -    /* disk I/O throttling */
>> -    if (throttle_enabled(&cfg)) {
>> -        bdrv_io_limits_enable(dinfo->bdrv);
>> -        bdrv_set_io_limits(dinfo->bdrv, &cfg);
>> -    }
>> -
>>      if (!file || !*file) {
>>          if (has_driver_specific_opts) {
>>              file = NULL;
>
> This looks correct, but it's really doing two things at once (on the one
> hand changing code to use bs instead of dinfo->bdrv and reordering, on
> the other hand introducing blk_new_with_bs()).
>
> Might be worth doing in separate patches.

I'll give it a try.

>> @@ -509,7 +508,8 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
>>  
>>      QINCREF(bs_opts);
>> -    ret = bdrv_open(&dinfo->bdrv, file, NULL, bs_opts, bdrv_flags, drv, &error);
>> +    ret = bdrv_open(&bs, file, NULL, bs_opts, bdrv_flags, drv, &error);
>> +    assert(bs == blk_bs(blk));
>>  
>>      if (ret < 0) {
>>          error_setg(errp, "could not open disk image %s: %s",
>> @@ -518,8 +518,9 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>          goto err;
>>      }
>>  
>> -    if (bdrv_key_required(dinfo->bdrv))
>> +    if (bdrv_key_required(bs)) {
>>          autostart = 0;
>> +    }
>>  
>>      QDECREF(bs_opts);
>>      qemu_opts_del(opts);
>> @@ -529,7 +530,6 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>  err:
>>      bdrv_unref(dinfo->bdrv);
>>      QTAILQ_REMOVE(&drives, dinfo, next);
>> -bdrv_new_err:
>>      g_free(dinfo->id);
>>      g_free(dinfo);
>>      blk_unref(blk);
>> @@ -1746,15 +1746,17 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
>>  int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
>>  {
>>      const char *id = qdict_get_str(qdict, "id");
>> +    BlockBackend *blk;
>>      BlockDriverState *bs;
>>      AioContext *aio_context;
>>      Error *local_err = NULL;
>>  
>> -    bs = bdrv_find(id);
>> -    if (!bs) {
>> +    blk = blk_by_name(id);
>> +    if (!blk) {
>>          error_report("Device '%s' not found", id);
>>          return -1;
>>      }
>> +    bs = blk_bs(blk);
>>  
>>      aio_context = bdrv_get_aio_context(bs);
>>      aio_context_acquire(aio_context);
>> @@ -1777,8 +1779,9 @@ 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 (bdrv_get_attached_dev(bs)) {
>> +        blk_detach_bs(blk);
>> +        blk_unref(blk);
>
> We're not doing real refcounting yet, but if we did, and if the refcount
> didn't drop to zero here, why would detaching the bs still be correct?
>
> blk_delete() already takes care of detaching after this patch, so I
> suppose removing the call here would be right.

I've since reworked this part to address the temporary leak you pointed
out in your review of PATCH 02.  My current tree has this hunk here:

@@ -1791,8 +1787,7 @@ 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 (bdrv_get_attached_dev(bs)) {
-        bdrv_make_anon(bs);
-        blk_unref(blk_by_name(id));
+        blk_make_anon(blk);
         /* Further I/O must not pause the guest */
         bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
                           BLOCKDEV_ON_ERROR_REPORT);

Suggest you take another careful look when you review v2.

>>          bdrv_make_anon(bs);
>> -        blk_unref(blk_by_name(id));
>>          /* Further I/O must not pause the guest */
>>          bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
>>                            BLOCKDEV_ON_ERROR_REPORT);
>
> Kevin

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo() Markus Armbruster
  2014-09-11 12:07   ` Benoît Canet
@ 2014-09-11 17:06   ` Benoît Canet
  2014-09-11 19:12     ` Markus Armbruster
  1 sibling, 1 reply; 76+ messages in thread
From: Benoît Canet @ 2014-09-11 17:06 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha


> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)));

This seems to be a fairly common pattern: "blk_bs(blk_by_legacy_dinfo())".
How about a helper function ?

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo
  2014-09-10 13:30   ` Kevin Wolf
@ 2014-09-11 17:41     ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 17:41 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: benoit.canet, famz, qemu-devel, stefanha

Kevin Wolf <kwolf@redhat.com> writes:

> Am 10.09.2014 um 10:13 hat Markus Armbruster geschrieben:
>> Make the BlockBackend own the DriveInfo.  Change blockdev_init() to
>> return the BlockBackend instead of the DriveInfo.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  block/block-backend.c     | 38 +++++++++++++++++++++++
>>  blockdev.c                | 79 +++++++++++++++++++++--------------------------
>>  include/sysemu/blockdev.h |  4 +++
>>  3 files changed, 78 insertions(+), 43 deletions(-)
>> 
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> index deccb54..2a22660 100644
>> --- a/block/block-backend.c
>> +++ b/block/block-backend.c
>> @@ -12,14 +12,18 @@
>>  
>>  #include "sysemu/block-backend.h"
>>  #include "block/block_int.h"
>> +#include "sysemu/blockdev.h"
>>  
>>  struct BlockBackend {
>>      char *name;
>>      int refcnt;
>>      BlockDriverState *bs;
>> +    DriveInfo *legacy_dinfo;
>>      QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
>>  };
>>  
>> +static void drive_info_del(DriveInfo *dinfo);
>> +
>>  static QTAILQ_HEAD(, BlockBackend) blk_backends =
>>      QTAILQ_HEAD_INITIALIZER(blk_backends);
>>  
>> @@ -87,6 +91,7 @@ static void blk_delete(BlockBackend *blk)
>>      blk_detach_bs(blk);
>>      QTAILQ_REMOVE(&blk_backends, blk, link);
>>      g_free(blk->name);
>> +    drive_info_del(blk->legacy_dinfo);
>>      g_free(blk);
>>  }
>>  
>> @@ -119,6 +124,16 @@ void blk_unref(BlockBackend *blk)
>>      }
>>  }
>>  
>> +static void drive_info_del(DriveInfo *dinfo)
>> +{
>> +    if (dinfo) {
>> +        qemu_opts_del(dinfo->opts);
>> +        g_free(dinfo->id);
>> +        g_free(dinfo->serial);
>> +        g_free(dinfo);
>> +    }
>> +}
>> +
>>  const char *blk_name(BlockBackend *blk)
>>  {
>>      return blk->name;
>> @@ -187,3 +202,26 @@ BlockDriverState *blk_detach_bs(BlockBackend *blk)
>>      }
>>      return bs;
>>  }
>> +
>> +DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
>> +{
>> +    return blk->legacy_dinfo;
>> +}
>> +
>> +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
>> +{
>> +    assert(!blk->legacy_dinfo);
>> +    return blk->legacy_dinfo = dinfo;
>> +}
>> +
>> +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
>> +{
>> +    BlockBackend *blk;
>> +
>> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
>> +        if (blk->legacy_dinfo == dinfo) {
>> +            return blk;
>> +        }
>> +    }
>> +    assert(0);
>> +}
>> diff --git a/blockdev.c b/blockdev.c
>> index 0a0b95e..73e2da9 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -47,8 +47,6 @@
>>  #include "trace.h"
>>  #include "sysemu/arch_init.h"
>>  
>> -static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
>> -
>>  static const char *const if_name[IF_COUNT] = {
>>      [IF_NONE] = "none",
>>      [IF_IDE] = "ide",
>> @@ -89,7 +87,8 @@ static const int if_max_devs[IF_COUNT] = {
>>   */
>>  void blockdev_mark_auto_del(BlockDriverState *bs)
>>  {
>> -    DriveInfo *dinfo = drive_get_by_blockdev(bs);
>> +    BlockBackend *blk = bs->blk;
>> +    DriveInfo *dinfo = blk_legacy_dinfo(blk);
>>  
>>      if (dinfo && !dinfo->enable_auto_del) {
>>          return;
>> @@ -105,7 +104,8 @@ void blockdev_mark_auto_del(BlockDriverState *bs)
>>  
>>  void blockdev_auto_del(BlockDriverState *bs)
>>  {
>> -    DriveInfo *dinfo = drive_get_by_blockdev(bs);
>> +    BlockBackend *blk = bs->blk;
>> +    DriveInfo *dinfo = blk_legacy_dinfo(blk);
>>  
>>      if (dinfo && dinfo->auto_del) {
>>          drive_del(dinfo);
>
> The if condition looks as if there were cases where dinfo was NULL. To
> be precise, this was introduced in commit 0fc0f1fa, so that hot unplug
> after a forced drive_del wouldn't segfault.
>
> Does such a device that doesn't have a dinfo at least have a
> BlockBackend? If it doesn't, we'll segfault in blk_legacy_dinfo(). I
> won't say that I understand that part of the code, but I can't see why
> BlockBackend would still be there when DriveInfo isn't any more.

Ah, our friend drive_del again.

As I explained in my reply to your review of PATCH 02, the initial
implementation of drive_del destroyed the root BDS and the DriveInfo
right away, leaving the device model with a dangling pointer to the root
BDS.  Naturally, this was prone to crash eventually, when the memory
gets reused.  But here, it crashes right away, because the DriveInfo no
longer exists.  Commit 0fc0f1f "fixed" that part.  The real fix is
commit d22b2f4.

However, my PATCH 18 will change blockdev-add not to create a DriveInfo,
and then this test will become necessary again.

>> @@ -153,15 +153,15 @@ QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
>>  
>>  DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
>>  {
>> +    BlockBackend *blk;
>>      DriveInfo *dinfo;
>>  
>> -    /* seek interface, bus and unit */
>> -
>> -    QTAILQ_FOREACH(dinfo, &drives, next) {
>> -        if (dinfo->type == type &&
>> -	    dinfo->bus == bus &&
>> -	    dinfo->unit == unit)
>> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
>> +        dinfo = blk_legacy_dinfo(blk);
>> +        if (dinfo && dinfo->type == type
>> +            && dinfo->bus == bus && dinfo->unit == unit) {
>>              return dinfo;
>> +        }
>>      }
>>  
>>      return NULL;
>> @@ -177,13 +177,15 @@ DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
>>  int drive_get_max_bus(BlockInterfaceType type)
>>  {
>>      int max_bus;
>> +    BlockBackend *blk;
>>      DriveInfo *dinfo;
>>  
>>      max_bus = -1;
>> -    QTAILQ_FOREACH(dinfo, &drives, next) {
>> -        if(dinfo->type == type &&
>> -           dinfo->bus > max_bus)
>> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
>> +        dinfo = blk_legacy_dinfo(blk);
>> +        if (dinfo && dinfo->type == type && dinfo->bus > max_bus) {
>>              max_bus = dinfo->bus;
>> +        }
>>      }
>>      return max_bus;
>>  }
>> @@ -200,11 +202,11 @@ DriveInfo *drive_get_next(BlockInterfaceType type)
>>  
>>  DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
>>  {
>> -    DriveInfo *dinfo;
>> +    BlockBackend *blk;
>>  
>> -    QTAILQ_FOREACH(dinfo, &drives, next) {
>> -        if (dinfo->bdrv == bs) {
>> -            return dinfo;
>> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
>> +        if (blk_bs(blk) == bs) {
>> +            return blk_legacy_dinfo(blk);
>>          }
>>      }
>>      return NULL;
>> @@ -217,16 +219,10 @@ static void bdrv_format_print(void *opaque, const char *name)
>>  
>>  void drive_del(DriveInfo *dinfo)
>>  {
>> -    if (dinfo->opts) {
>> -        qemu_opts_del(dinfo->opts);
>> -    }
>> +    BlockBackend *blk = dinfo->bdrv->blk;
>>  
>>      bdrv_unref(dinfo->bdrv);
>> -    blk_unref(blk_by_name(dinfo->id));
>> -    g_free(dinfo->id);
>> -    QTAILQ_REMOVE(&drives, dinfo, next);
>> -    g_free(dinfo->serial);
>> -    g_free(dinfo);
>> +    blk_unref(blk);
>>  }
>
> Now the dinfo stays alive until the last reference for blk is gone. We
> probably don't care much about the memory that isn't used any more, but
> not freed yet. What about dinfo->opts? Does it block IDs that should be
> available again?

Hmm.

I don't think deleting options and DriveInfo makes the ID available for
reuse.  While you can create new options with the same ID then, you
still can't create a new BDS or BB with the same ID while the old ones
live.

But let's dig deeper.

This hunk changes behavior of drive_del when blk->refcnt > 1: DriveInfo
and the options in qemu_drive_opts stay around.  blk->recfcnt > 1 can't
happen so far, but that's no excuse.

In current master, we have:

    void drive_del(DriveInfo *dinfo)
    {
        if (dinfo->opts) {
            qemu_opts_del(dinfo->opts);
        }

        bdrv_unref(dinfo->bdrv);
        g_free(dinfo->id);
        QTAILQ_REMOVE(&drives, dinfo, next);
        g_free(dinfo->serial);
        g_free(dinfo);
    }

We destroy the DriveInfo and the options unconditionally, but the
BDS only when dinfo->bdrv->refcnt == 1.

Callers:

* drive_hot_add()

  Cleanup on error, thus refcnt == 1; destroys both BDS and DriveInfo.
  Good.

* qmp_blockdev_add() if image is encryped

  Likewise.

* blockdev_auto_del()

  Runs during device model destruction, when we detach it from its BDS.

  If the BDS's refcnt > 0, we destroy the DriveInfo, but not the BDS.
  Code assuming such a BDS always has a DriveInfo could crash.  PATCH 18
  eliminates that assumption, thus shows the code in question: all
  device model initialization.

  If we somehow manage to use the BDS to plug in such a device model
  before the BDS's refcnt drops to zero, we crash.  I figure this is
  possible, because device_add resolves property "drive" via bdrv_find()
  just fine, even when there's no DriveInfo.

* pci_piix3_xen_ide_unplug()

  No idea what this one's supposed to do.  Anyway, it also detaches
  device model from its BDS before drive_del(), so my crash scenario
  should apply.

* do_drive_del() if no device model is attached

  Crash scenario applies.

So my patch is actually a bug fix.  I'll look into separating the bug
fix part into its own patch.

> Do we need a dinfo_attach/detach like for BDSes?

I doubt it.

>>  typedef struct {
>> @@ -296,8 +292,8 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
>>  typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
>>  
>>  /* Takes the ownership of bs_opts */
>> -static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>> -                                Error **errp)
>> +static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
>> +                                   Error **errp)
>>  {
>>      const char *buf;
>>      int ro = 0;
>> @@ -480,7 +476,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      dinfo = g_malloc0(sizeof(*dinfo));
>>      dinfo->id = g_strdup(qemu_opts_id(opts));
>>      dinfo->bdrv = bs;
>> -    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
>> +    blk_set_legacy_dinfo(blk, dinfo);
>>  
>>      if (!file || !*file) {
>>          if (has_driver_specific_opts) {
>> @@ -488,7 +484,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>          } else {
>>              QDECREF(bs_opts);
>>              qemu_opts_del(opts);
>> -            return dinfo;
>> +            return blk;
>>          }
>>      }
>>      if (snapshot) {
>> @@ -525,13 +521,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      QDECREF(bs_opts);
>>      qemu_opts_del(opts);
>>  
>> -    return dinfo;
>> +    return blk;
>>  
>>  err:
>>      bdrv_unref(dinfo->bdrv);
>> -    QTAILQ_REMOVE(&drives, dinfo, next);
>> -    g_free(dinfo->id);
>> -    g_free(dinfo);
>>      blk_unref(blk);
>>  early_err:
>>      qemu_opts_del(opts);
>> @@ -635,6 +628,7 @@ QemuOptsList qemu_legacy_drive_opts = {
>>  DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>>  {
>>      const char *value;
>> +    BlockBackend *blk;
>>      DriveInfo *dinfo = NULL;
>>      QDict *bs_opts;
>>      QemuOpts *legacy_opts;
>> @@ -917,19 +911,17 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>>      }
>>  
>>      /* Actual block device init: Functionality shared with blockdev-add */
>> -    dinfo = blockdev_init(filename, bs_opts, &local_err);
>> +    blk = blockdev_init(filename, bs_opts, &local_err);
>>      bs_opts = NULL;
>> -    if (dinfo == NULL) {
>> -        if (local_err) {
>> -            error_report("%s", error_get_pretty(local_err));
>> -            error_free(local_err);
>> -        }
>> +    if (!blk) {
>> +        error_report("%s", error_get_pretty(local_err));
>
> Now local_err is leaked.

Fixing...

>>          goto fail;
>>      } else {
>>          assert(!local_err);
>>      }
>
> Kevin

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo
  2014-09-10 13:08   ` Benoît Canet
@ 2014-09-11 18:03     ` Markus Armbruster
  2014-09-11 20:43       ` Eric Blake
  0 siblings, 1 reply; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 18:03 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> The Wednesday 10 Sep 2014 à 10:13:33 (+0200), Markus Armbruster wrote :
>> Make the BlockBackend own the DriveInfo.  Change blockdev_init() to
>> return the BlockBackend instead of the DriveInfo.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  block/block-backend.c     | 38 +++++++++++++++++++++++
>>  blockdev.c                | 79 +++++++++++++++++++++--------------------------
>>  include/sysemu/blockdev.h |  4 +++
>>  3 files changed, 78 insertions(+), 43 deletions(-)
>> 
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> index deccb54..2a22660 100644
>> --- a/block/block-backend.c
>> +++ b/block/block-backend.c
>> @@ -12,14 +12,18 @@
>>  
>>  #include "sysemu/block-backend.h"
>>  #include "block/block_int.h"
>> +#include "sysemu/blockdev.h"
>>  
>>  struct BlockBackend {
>>      char *name;
>>      int refcnt;
>>      BlockDriverState *bs;
>> +    DriveInfo *legacy_dinfo;
>>      QTAILQ_ENTRY(BlockBackend) link; /* for blk_backends */
>>  };
>>  
>
>> +static void drive_info_del(DriveInfo *dinfo);
>
> Is there any technical reason not to just put the
> drive_info_del above the blk_delete function ?
> I don't see any possible circular references between the two.
>
> Some people like Eric frown upon static function prototypes
> in final code that's why I am asking.

Placing functions before their callers makes the program easier to read
when you need to see the functions definition before you can understand
their use.

Placing the functions after callers makes the program easier to read
when the gist of what they do is obvious from the call.  You're omitting
unnecessary detail there, to be flesh it own further down.  Saving a
function declaration is immaterial compared to that.

Before I put the function where I don't want it, I'd inline it :)

>> +
>>  static QTAILQ_HEAD(, BlockBackend) blk_backends =
>>      QTAILQ_HEAD_INITIALIZER(blk_backends);
>>  
>> @@ -87,6 +91,7 @@ static void blk_delete(BlockBackend *blk)
>>      blk_detach_bs(blk);
>>      QTAILQ_REMOVE(&blk_backends, blk, link);
>>      g_free(blk->name);
>> +    drive_info_del(blk->legacy_dinfo);
>>      g_free(blk);
>>  }
>>  
>> @@ -119,6 +124,16 @@ void blk_unref(BlockBackend *blk)
>>      }
>>  }
>>  
>> +static void drive_info_del(DriveInfo *dinfo)
>> +{
>> +    if (dinfo) {
>> +        qemu_opts_del(dinfo->opts);
>> +        g_free(dinfo->id);
>> +        g_free(dinfo->serial);
>> +        g_free(dinfo);
>> +    }
>> +}
>> +
>>  const char *blk_name(BlockBackend *blk)
>>  {
>>      return blk->name;
>> @@ -187,3 +202,26 @@ BlockDriverState *blk_detach_bs(BlockBackend *blk)
>>      }
>>      return bs;
>>  }
>> +
>> +DriveInfo *blk_legacy_dinfo(BlockBackend *blk)
>> +{
>> +    return blk->legacy_dinfo;
>> +}
>> +
>> +DriveInfo *blk_set_legacy_dinfo(BlockBackend *blk, DriveInfo *dinfo)
>> +{
>> +    assert(!blk->legacy_dinfo);
>> +    return blk->legacy_dinfo = dinfo;
>> +}
>> +
>> +BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo)
>> +{
>> +    BlockBackend *blk;
>> +
>> +    QTAILQ_FOREACH(blk, &blk_backends, link) {
>> +        if (blk->legacy_dinfo == dinfo) {
>> +            return blk;
>> +        }
>> +    }
>> +    assert(0);
>> +}
>> diff --git a/blockdev.c b/blockdev.c
>> index 0a0b95e..73e2da9 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -47,8 +47,6 @@
>>  #include "trace.h"
>>  #include "sysemu/arch_init.h"
>>  
>> -static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
>> -
>>  static const char *const if_name[IF_COUNT] = {
>>      [IF_NONE] = "none",
>>      [IF_IDE] = "ide",
>> @@ -89,7 +87,8 @@ static const int if_max_devs[IF_COUNT] = {
>>   */
>>  void blockdev_mark_auto_del(BlockDriverState *bs)
>>  {
>> -    DriveInfo *dinfo = drive_get_by_blockdev(bs);
>> +    BlockBackend *blk = bs->blk;
>> +    DriveInfo *dinfo = blk_legacy_dinfo(blk);
>>  
>>      if (dinfo && !dinfo->enable_auto_del) {
>>          return;
>> @@ -105,7 +104,8 @@ void blockdev_mark_auto_del(BlockDriverState *bs)
>>  
>>  void blockdev_auto_del(BlockDriverState *bs)
>>  {
>> -    DriveInfo *dinfo = drive_get_by_blockdev(bs);
>> +    BlockBackend *blk = bs->blk;
>> +    DriveInfo *dinfo = blk_legacy_dinfo(blk);
>>  
>>      if (dinfo && dinfo->auto_del) {
>>          drive_del(dinfo);
>> @@ -153,15 +153,15 @@ QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
>>  
>>  DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
>>  {
>> +    BlockBackend *blk;
>>      DriveInfo *dinfo;
>>  
>> -    /* seek interface, bus and unit */
>> -
>> -    QTAILQ_FOREACH(dinfo, &drives, next) {
>> -        if (dinfo->type == type &&
>> -	    dinfo->bus == bus &&
>> -	    dinfo->unit == unit)
>> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
>
> Here I understand why you didn't made blk_next pure round robin
> circling in a loop.

It works exactly like bdrv_next().

> Maybe the comments of the blk_next function should say it's just an iterator.

I could add example usage to the comment there.

>> +        dinfo = blk_legacy_dinfo(blk);
>> +        if (dinfo && dinfo->type == type
>> +            && dinfo->bus == bus && dinfo->unit == unit) {
>>              return dinfo;
>> +        }
>>      }
>>  
>>      return NULL;
>> @@ -177,13 +177,15 @@ DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
>>  int drive_get_max_bus(BlockInterfaceType type)
>>  {
>>      int max_bus;
>> +    BlockBackend *blk;
>>      DriveInfo *dinfo;
>>  
>>      max_bus = -1;
>> -    QTAILQ_FOREACH(dinfo, &drives, next) {
>> -        if(dinfo->type == type &&
>> -           dinfo->bus > max_bus)
>> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
>> +        dinfo = blk_legacy_dinfo(blk);
>> +        if (dinfo && dinfo->type == type && dinfo->bus > max_bus) {
>>              max_bus = dinfo->bus;
>> +        }
>>      }
>>      return max_bus;
>>  }
>> @@ -200,11 +202,11 @@ DriveInfo *drive_get_next(BlockInterfaceType type)
>>  
>>  DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
>>  {
>> -    DriveInfo *dinfo;
>> +    BlockBackend *blk;
>>  
>> -    QTAILQ_FOREACH(dinfo, &drives, next) {
>> -        if (dinfo->bdrv == bs) {
>> -            return dinfo;
>> +    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
>> +        if (blk_bs(blk) == bs) {
>> +            return blk_legacy_dinfo(blk);
>>          }
>>      }
>>      return NULL;
>> @@ -217,16 +219,10 @@ static void bdrv_format_print(void *opaque, const char *name)
>>  
>>  void drive_del(DriveInfo *dinfo)
>>  {
>> -    if (dinfo->opts) {
>> -        qemu_opts_del(dinfo->opts);
>> -    }
>> +    BlockBackend *blk = dinfo->bdrv->blk;
>>  
>>      bdrv_unref(dinfo->bdrv);
>> -    blk_unref(blk_by_name(dinfo->id));
>> -    g_free(dinfo->id);
>> -    QTAILQ_REMOVE(&drives, dinfo, next);
>> -    g_free(dinfo->serial);
>> -    g_free(dinfo);
>> +    blk_unref(blk);
>>  }
>>  
>>  typedef struct {
>> @@ -296,8 +292,8 @@ static bool check_throttle_config(ThrottleConfig *cfg, Error **errp)
>>  typedef enum { MEDIA_DISK, MEDIA_CDROM } DriveMediaType;
>>  
>>  /* Takes the ownership of bs_opts */
>> -static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>> -                                Error **errp)
>> +static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
>> +                                   Error **errp)
>>  {
>>      const char *buf;
>>      int ro = 0;
>> @@ -480,7 +476,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      dinfo = g_malloc0(sizeof(*dinfo));
>>      dinfo->id = g_strdup(qemu_opts_id(opts));
>>      dinfo->bdrv = bs;
>> -    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
>> +    blk_set_legacy_dinfo(blk, dinfo);
>>  
>>      if (!file || !*file) {
>>          if (has_driver_specific_opts) {
>> @@ -488,7 +484,7 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>          } else {
>>              QDECREF(bs_opts);
>>              qemu_opts_del(opts);
>> -            return dinfo;
>
>> +            return blk;
> Here you fix the leak I found on a previous patch.

I don't think it leaked.

>>          }
>>      }
>>      if (snapshot) {
>> @@ -525,13 +521,10 @@ static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
>>      QDECREF(bs_opts);
>>      qemu_opts_del(opts);
>>  
>> -    return dinfo;
>> +    return blk;
>>  
>>  err:
>>      bdrv_unref(dinfo->bdrv);
>> -    QTAILQ_REMOVE(&drives, dinfo, next);
>> -    g_free(dinfo->id);
>> -    g_free(dinfo);
>>      blk_unref(blk);
>>  early_err:
>>      qemu_opts_del(opts);
>> @@ -635,6 +628,7 @@ QemuOptsList qemu_legacy_drive_opts = {
>>  DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>>  {
>>      const char *value;
>> +    BlockBackend *blk;
>>      DriveInfo *dinfo = NULL;
>>      QDict *bs_opts;
>>      QemuOpts *legacy_opts;
>> @@ -917,19 +911,17 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
>>      }
>>  
>>      /* Actual block device init: Functionality shared with blockdev-add */
>> -    dinfo = blockdev_init(filename, bs_opts, &local_err);
>> +    blk = blockdev_init(filename, bs_opts, &local_err);
>>      bs_opts = NULL;
>> -    if (dinfo == NULL) {
>> -        if (local_err) {
>> -            error_report("%s", error_get_pretty(local_err));
>> -            error_free(local_err);
>> -        }
>
>> +    if (!blk) {
>
> Just down the code an existing test does if (local_err) { after
> blk = blockdev_init(NULL, qdict, &local_err);.
>
> Is the prefered convention checking blk or local_err ?

Both

    foop = foo_new(bar, &local_err);
    if (local_err) {
        assert(!foop);
        error_propagate(errp, local_err)
        goto fail;
    }
    assert(!local_err);

and

    foop = foo_new(bar, &errp);
    if (!foop) {
        assert(!errp || *errp);
        goto fail;
    }
    assert(!errp || *errp);

work.  Of course, nobody bothers with the assertions; the error handling
is enough verbiage as it is.

However, I dislike the first variant intensely.  Not least because it's
prone to get Coverity worry about foop being null in code following it.

>> +        error_report("%s", error_get_pretty(local_err));
>>          goto fail;
>>      } else {
>>          assert(!local_err);
>>      }
>>  
>>      /* Set legacy DriveInfo fields */
>> +    dinfo = blk_legacy_dinfo(blk);
>>      dinfo->enable_auto_del = true;
>>      dinfo->opts = all_opts;
>>  
[...]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 05/23] block: Make BlockBackend own its BlockDriverState
  2014-09-10 10:14   ` Kevin Wolf
@ 2014-09-11 18:38     ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 18:38 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: benoit.canet, famz, qemu-devel, stefanha

Kevin Wolf <kwolf@redhat.com> writes:

> Am 10.09.2014 um 10:13 hat Markus Armbruster geschrieben:
>> On BlockBackend destruction, unref its BlockDriverState.  Replaces the
>> callers' unrefs.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  block/block-backend.c |  9 ++-------
>>  blockdev.c            | 11 +++--------
>>  hw/block/xen_disk.c   |  6 +++---
>>  qemu-img.c            | 35 +----------------------------------
>>  qemu-io.c             |  5 -----
>>  5 files changed, 9 insertions(+), 57 deletions(-)
>> 
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> index 2a22660..ae51f7f 100644
>> --- a/block/block-backend.c
>> +++ b/block/block-backend.c
>> @@ -58,10 +58,7 @@ BlockBackend *blk_new(const char *name, Error **errp)
>>   * @errp: return location for an error to be set on failure, or %NULL
>>   *
>>   * Create a new BlockBackend, with a reference count of one, and
>> - * attach a new BlockDriverState to it, also with a reference count of
>> - * one.  Caller owns *both* references.
>> - * TODO Let caller own only the BlockBackend reference
>> - * Fail if @name already exists.
>> + * a new BlockDriverState attached.  Fail if @name already exists.
>>   *
>>   * Returns: the BlockBackend on success, %NULL on error
>>   */
>> @@ -88,6 +85,7 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp)
>>  static void blk_delete(BlockBackend *blk)
>>  {
>>      assert(!blk->refcnt);
>> +    bdrv_unref(blk->bs);
>>      blk_detach_bs(blk);
>
> I think the bdrv_unref() should really be part of blk_detach_bs().
>
> The same way it would be more logical to have bdrv_ref() as part of
> blk_attach_bs(). For blk_new_with_bs() this might mean bdrv_new,
> blk_attach_bs, bdrv_unref, which looks a bit odd, but if blk_attach_bs()
> is ever called from somewhere else, it probably makes more sense (if it
> isn't, it should be static).

My thinking was that you usually want to acquire a reference when you
detach, and you're usually ready to give yours up when you attach.

However, I now think I got a use-after-free hidden around there.  I'll
look into it tomorrow with a fresh mind.  Might lead to me accepting
your suggestion without further ado :)

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 07/23] block: Eliminate bdrv_iterate(), use bdrv_next()
  2014-09-11 10:46   ` Benoît Canet
@ 2014-09-11 18:44     ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 18:44 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> The Wednesday 10 Sep 2014 à 10:13:36 (+0200), Markus Armbruster wrote :
[...]
>> --- a/monitor.c
>> +++ b/monitor.c
>> @@ -4208,24 +4208,6 @@ static void file_completion(Monitor *mon, const char *input)
>>      closedir(ffs);
>>  }
>>  
>> -typedef struct MonitorBlockComplete {
>> -    Monitor *mon;
>> -    const char *input;
>> -} MonitorBlockComplete;
>> -
>> -static void block_completion_it(void *opaque, BlockDriverState *bs)
>> -{
>> -    const char *name = bdrv_get_device_name(bs);
>> -    MonitorBlockComplete *mbc = opaque;
>> -    Monitor *mon = mbc->mon;
>> -    const char *input = mbc->input;
>> -
>> -    if (input[0] == '\0' ||
>> -        !strncmp(name, (char *)input, strlen(input))) {
>> -        readline_add_completion(mon->rs, name);
>> -    }
>> -}
>> -
>>  static const char *next_arg_type(const char *typestr)
>>  {
>>      const char *p = strchr(typestr, ':');
>> @@ -4663,9 +4645,9 @@ static void monitor_find_completion_by_table(Monitor *mon,
>>  {
>>      const char *cmdname;
>>      int i;
>> -    const char *ptype, *str;
>> +    const char *ptype, *str, *name;
>>      const mon_cmd_t *cmd;
>> -    MonitorBlockComplete mbs;
>> +    BlockDriverState *bs;
>>  
>>      if (nb_args <= 1) {
>>          /* command completion */
>> @@ -4717,10 +4699,13 @@ static void monitor_find_completion_by_table(Monitor *mon,
>>              break;
>>          case 'B':
>>              /* block device name completion */
>> -            mbs.mon = mon;
>> -            mbs.input = str;
>
>> -            readline_set_completion_index(mon->rs, strlen(str));
>
> Why is this line removed ?

Accident!  Fixing...

> In monitor readline_set_completion_index seems to work in pair with
> readline_add_completion.
> Either this line should be removed and readline_add_completion too or
> the oposite.
>
>> -            bdrv_iterate(block_completion_it, &mbs);
>> +            for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>> +                name = bdrv_get_device_name(bs);
>> +                if (str[0] == '\0' ||
>> +                    !strncmp(name, str, strlen(str))) {
>> +                    readline_add_completion(mon->rs, name);
>> +                }
>> +            }
>>              break;
>>          case 's':
>>          case 'S':
>> -- 
>> 1.9.3
>> 
>> 

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[]
  2014-09-10 16:09   ` Eric Blake
@ 2014-09-11 18:45     ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 18:45 UTC (permalink / raw)
  To: Eric Blake; +Cc: kwolf, benoit.canet, famz, qemu-devel, stefanha

Eric Blake <eblake@redhat.com> writes:

> On 09/10/2014 02:13 AM, Markus Armbruster wrote:
>> device_name[] is can become non-empty only in bdrv_new_named() and
>
> s/is //

Fixing, thanks!

>> bdrv_move_feature_fields().  The latter is used only to undo damage
>> done by bdrv_swap().  The former is called only by blk_new_with_bs().
>> Therefore, when a BlockDriverState's device_name[] is non-empty, then
>> it's owned by a BlockBackend.
>> 
>> The converse is also true, because blk_attach_bs() is called only by
>> blk_new_with_bs() so far.
>> 
>> Furthermore, blk_new_with_bs() keeps the two names equal.
>> 
>> Therefore, device_name[] is redundant.  Eliminate it.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[]
  2014-09-11 11:34   ` Benoît Canet
  2014-09-11 11:43     ` Benoît Canet
  2014-09-11 13:00     ` Eric Blake
@ 2014-09-11 19:01     ` Markus Armbruster
  2 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 19:01 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> The Wednesday 10 Sep 2014 à 10:13:37 (+0200), Markus Armbruster wrote :
>> device_name[] is can become non-empty only in bdrv_new_named() and
>> bdrv_move_feature_fields().  The latter is used only to undo damage
>> done by bdrv_swap().  The former is called only by blk_new_with_bs().
>> Therefore, when a BlockDriverState's device_name[] is non-empty, then
>> it's owned by a BlockBackend.
>> 
>> The converse is also true, because blk_attach_bs() is called only by
>> blk_new_with_bs() so far.
>> 
>> Furthermore, blk_new_with_bs() keeps the two names equal.
>> 
>> Therefore, device_name[] is redundant.  Eliminate it.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> ---
>>  block-migration.c         | 12 +++++----
>>  block.c                   | 63 ++++++++++++++---------------------------------
>>  block/block-backend.c     | 12 ++++-----
>>  block/cow.c               |  2 +-
>>  block/mirror.c            |  3 ++-
>>  block/qapi.c              |  6 ++---
>>  block/qcow.c              |  4 +--
>>  block/qcow2.c             |  4 +--
>>  block/qed.c               |  2 +-
>>  block/quorum.c            |  4 +--
>>  block/vdi.c               |  2 +-
>>  block/vhdx.c              |  2 +-
>>  block/vmdk.c              |  4 +--
>>  block/vpc.c               |  2 +-
>>  block/vvfat.c             |  2 +-
>>  blockjob.c                |  3 ++-
>>  include/block/block.h     |  3 +--
>>  include/block/block_int.h |  2 --
>>  18 files changed, 53 insertions(+), 79 deletions(-)
>> 
>> diff --git a/block-migration.c b/block-migration.c
>> index cb3e16c..da30e93 100644
>> --- a/block-migration.c
>> +++ b/block-migration.c
>> @@ -14,7 +14,9 @@
>>   */
>>  
>>  #include "qemu-common.h"
>> -#include "block/block_int.h"
>> +#include "block/block.h"
>> +#include "qemu/error-report.h"
>> +#include "qemu/main-loop.h"
>>  #include "hw/hw.h"
>>  #include "qemu/queue.h"
>>  #include "qemu/timer.h"
>> @@ -130,9 +132,9 @@ static void blk_send(QEMUFile *f, BlkMigBlock * blk)
>>                       | flags);
>>  
>>      /* device name */
>> -    len = strlen(blk->bmds->bs->device_name);
>> +    len = strlen(bdrv_get_device_name(blk->bmds->bs));
>>      qemu_put_byte(f, len);
>> -    qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len);
>> +    qemu_put_buffer(f, (uint8_t *)bdrv_get_device_name(blk->bmds->bs), len);
>>  
>>      /* if a block is zero we need to flush here since the network
>>       * bandwidth is now a lot higher than the storage device bandwidth.
>> @@ -382,9 +384,9 @@ static void init_blk_migration(QEMUFile *f)
>>  
>>          if (bmds->shared_base) {
>>              DPRINTF("Start migration for %s with shared base image\n",
>> -                    bs->device_name);
>> +                    bdrv_get_device_name(bs));
>>          } else {
>> -            DPRINTF("Start full migration for %s\n", bs->device_name);
>> +            DPRINTF("Start full migration for %s\n", bdrv_get_device_name(bs));
>>          }
>>  
>>          QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
>> diff --git a/block.c b/block.c
>> index 593d89b..61ea15d 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -332,31 +332,6 @@ void bdrv_register(BlockDriver *bdrv)
>>      QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
>>  }
>>  
>> -/* create a new block device (by default it is empty) */
>> -BlockDriverState *bdrv_new_named(const char *device_name, Error **errp)
>> -{
>> -    BlockDriverState *bs;
>> -
>> -    assert(*device_name);
>> -
>> -    if (bdrv_find(device_name)) {
>> -        error_setg(errp, "Device with id '%s' already exists",
>> -                   device_name);
>> -        return NULL;
>> -    }
>> -    if (bdrv_find_node(device_name)) {
>> -        error_setg(errp, "Device with node-name '%s' already exists",
>> -                   device_name);
>> -        return NULL;
>> -    }
>> -
>> -    bs = bdrv_new();
>> -
>> -    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
>> -
>> -    return bs;
>> -}
>> -
>>  BlockDriverState *bdrv_new(void)
>>  {
>>      BlockDriverState *bs;
>> @@ -1159,7 +1134,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
>>      } else if (backing_hd) {
>>          error_setg(&bs->backing_blocker,
>>                     "device is used as backing hd of '%s'",
>> -                   bs->device_name);
>> +                   bdrv_get_device_name(bs));
>>      }
>>  
>>      bs->backing_hd = backing_hd;
>> @@ -1533,7 +1508,7 @@ int bdrv_open(BlockDriverState **pbs, const char *filename,
>>          } else {
>>              error_setg(errp, "Block format '%s' used by device '%s' doesn't "
>>                         "support the option '%s'", drv->format_name,
>> -                       bs->device_name, entry->key);
>> +                       bdrv_get_device_name(bs), entry->key);
>>          }
>>  
>>          ret = -EINVAL;
>> @@ -1740,7 +1715,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
>>      if (!(reopen_state->bs->open_flags & BDRV_O_ALLOW_RDWR) &&
>>          reopen_state->flags & BDRV_O_RDWR) {
>>          error_set(errp, QERR_DEVICE_IS_READ_ONLY,
>> -                  reopen_state->bs->device_name);
>> +                  bdrv_get_device_name(reopen_state->bs));
>>          goto error;
>>      }
>>  
>> @@ -1767,7 +1742,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
>>          /* It is currently mandatory to have a bdrv_reopen_prepare()
>>           * handler for each supported drv. */
>>          error_set(errp, QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
>> -                  drv->format_name, reopen_state->bs->device_name,
>> +                  drv->format_name, bdrv_get_device_name(reopen_state->bs),
>>                   "reopening of file");
>>          ret = -1;
>>          goto error;
>> @@ -1955,7 +1930,6 @@ void bdrv_drain_all(void)
>>     Also, NULL terminate the device_name to prevent double remove */
>>  void bdrv_make_anon(BlockDriverState *bs)
>>  {
>> -    bs->device_name[0] = '\0';
>>      if (bs->node_name[0] != '\0') {
>>          QTAILQ_REMOVE(&graph_bdrv_states, bs, node_list);
>>      }
>> @@ -2008,9 +1982,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
>>      /* job */
>>      bs_dest->job                = bs_src->job;
>>  
>> -    pstrcpy(bs_dest->device_name, sizeof(bs_dest->device_name),
>> -            bs_src->device_name);
>> -
>>      memcpy(bs_dest->op_blockers, bs_src->op_blockers,
>>             sizeof(bs_dest->op_blockers));
>>  }
>> @@ -2023,7 +1994,7 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
>>   * This will modify the BlockDriverState fields, and swap contents
>>   * between bs_new and bs_old. Both bs_new and bs_old are modified.
>>   *
>> - * bs_new must be nameless and not attached to a BlockBackend.
>> + * bs_new must not be attached to a BlockBackend.
>>   *
>>   * This function does not create any image files.
>>   */
>> @@ -2042,8 +2013,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
>>          QTAILQ_REMOVE(&graph_bdrv_states, bs_old, node_list);
>>      }
>>  
>> -    /* bs_new must be nameless and shouldn't have anything fancy enabled */
>> -    assert(bs_new->device_name[0] == '\0');
>> +    /* bs_new must be unattached and shouldn't have anything fancy enabled */
>>      assert(!bs_new->blk);
>>      assert(QLIST_EMPTY(&bs_new->dirty_bitmaps));
>>      assert(bs_new->job == NULL);
>> @@ -2060,8 +2030,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
>>      bdrv_move_feature_fields(bs_old, bs_new);
>>      bdrv_move_feature_fields(bs_new, &tmp);
>>  
>> -    /* bs_new must remain nameless and unattached */
>> -    assert(bs_new->device_name[0] == '\0');
>> +    /* bs_new must remain unattached */
>>      assert(!bs_new->blk);
>>  
>>      /* Check a few fields that should remain attached to the device */
>> @@ -2089,7 +2058,7 @@ void bdrv_swap(BlockDriverState *bs_new, BlockDriverState *bs_old)
>>   * This will modify the BlockDriverState fields, and swap contents
>>   * between bs_new and bs_top. Both bs_new and bs_top are modified.
>>   *
>> - * bs_new must be nameless and not attached to a BlockBackend.
>> + * bs_new must not be attached to a BlockBackend.
>>   *
>>   * This function does not create any image files.
>>   */
>> @@ -3799,7 +3768,7 @@ BlockDriverState *bdrv_find(const char *name)
>>      BlockDriverState *bs;
>>  
>>      for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
>> -        if (!strcmp(name, bs->device_name)) {
>> +        if (!strcmp(name, bdrv_get_device_name(bs))) {
>>              return bs;
>>          }
>>      }
>> @@ -3889,9 +3858,10 @@ BlockDriverState *bdrv_next(BlockDriverState *bs)
>>      return blk ? blk_bs(blk) : NULL;
>>  }
>>  
>> -const char *bdrv_get_device_name(BlockDriverState *bs)
>> +const char *bdrv_get_device_name(const BlockDriverState *bs)
>>  {
>> -    return bs->device_name;
>> +    const char *name = bs->blk ? blk_name(bs->blk) : NULL;
>> +    return name ?: "";
>>  }
>
> Why not ?
>
>     return bs->blk ? blk_name(bs->blk) : "";

Sold!

> or 
>
>     if (bs->blk) {
>         return blk_name(bs->blk);
>     }
>
>     return "";
>
> Would it fail to do the job ?
>
> Also we could have made sure that bdrv_get_device_name return either
> a non empty string or NULL.
>
> (We know blk_name will return a non empty string it's asserted)

In current master, bdrv_get_device_name(bs) returns an empty string if
and only if bs is in bdrv_states.

PATCH 06 switches from bdrv_states to blk_backends without changing the
value of bdrv_get_device_name().

Likewise, this patch switches from BDS member device_name to BB member
name without changing the value of bdrv_get_device_name().

That's good, because changing the value would involve checking all the
callers, and this series taxes certainly myself and probably my
reviewers enough already, so I'd rather not do that right now.

> This would need to change a few test all around the code but the final
> code logic would be less convoluted:
> -convert NULL to "" then test for not ""
> would turn into
> -return NULL test for not NULL
>
>>  
>>  int bdrv_get_flags(BlockDriverState *bs)
>> @@ -5253,13 +5223,15 @@ int bdrv_media_changed(BlockDriverState *bs)
>>  void bdrv_eject(BlockDriverState *bs, bool eject_flag)
>>  {
>>      BlockDriver *drv = bs->drv;
>> +    const char *device_name;
>>  
>>      if (drv && drv->bdrv_eject) {
>>          drv->bdrv_eject(bs, eject_flag);
>>      }
>>  
>> -    if (bs->device_name[0] != '\0') {
>> -        qapi_event_send_device_tray_moved(bdrv_get_device_name(bs),
>
>> +    device_name = bdrv_get_device_name(bs);
>> +        qapi_event_send_device_tray_moved(device_name,
>>                                            eject_flag, &error_abort);
>>      }
>>  }
>> @@ -5469,7 +5441,8 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
>>          blocker = QLIST_FIRST(&bs->op_blockers[op]);
>>          if (errp) {
>>              error_setg(errp, "Device '%s' is busy: %s",
>> -                       bs->device_name, error_get_pretty(blocker->reason));
>> +                       bdrv_get_device_name(bs),
>> +                       error_get_pretty(blocker->reason));
>>          }
>>          return true;
>>      }
>> diff --git a/block/block-backend.c b/block/block-backend.c
>> index c0876fa..2f10d6a 100644
>> --- a/block/block-backend.c
>> +++ b/block/block-backend.c
>> @@ -67,17 +67,17 @@ BlockBackend *blk_new_with_bs(const char *name, Error **errp)
>>      BlockBackend *blk;
>>      BlockDriverState *bs;
>>  
>> +    if (bdrv_find_node(name)) {
>> +        error_setg(errp, "Device with node-name '%s' already exists", name);
>
> Maybe the message written by the person who contributed the initial code (me) mislead you.
> I think the intent is good but the wording is wrong.
> node-name is associated with a regular BDS. A device cannot have a node name.
>
> Maybe something in the vein of:
>         error_setg(errp, "Device name '%s' would conflict with the node-name of an existing block driver state", name);

I moved the message from block.c.  Comes from Kevin's commit f2d953e.  I
like your wording better.  Kevin, would you mind me changing it in the
same patch, or do you want a separate one?

>> +        return NULL;
>> +    }
>> +
>>      blk = blk_new(name, errp);
>>      if (!blk) {
>>          return NULL;
>>      }
>>  
>> -    bs = bdrv_new_named(name, errp);
>> -    if (!bs) {
>> -        blk_unref(blk);
>> -        return NULL;
>> -    }
>> -
>> +    bs = bdrv_new();
>>      blk_attach_bs(blk, bs);
>>      return blk;
>>  }
[...]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[]
  2014-09-11 13:18       ` Benoît Canet
@ 2014-09-11 19:11         ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 19:11 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> The Thursday 11 Sep 2014 à 07:00:41 (-0600), Eric Blake wrote :
>> On 09/11/2014 05:34 AM, Benoît Canet wrote:
>> > The Wednesday 10 Sep 2014 à 10:13:37 (+0200), Markus Armbruster wrote :
>> >> device_name[] is can become non-empty only in bdrv_new_named() and
>> >> bdrv_move_feature_fields().  The latter is used only to undo damage
>> >> done by bdrv_swap().  The former is called only by blk_new_with_bs().
>> >> Therefore, when a BlockDriverState's device_name[] is non-empty, then
>> >> it's owned by a BlockBackend.
>> 
>> [lots of lines trimmed - it's not only okay, but desirable to trim out
>> portions of a patch that you are okay with, in order to call attention
>> to the problem spots that you are commenting on without making the
>> reader have to scroll through pages of quoted context]
>> 
>> >>  
>> >> -const char *bdrv_get_device_name(BlockDriverState *bs)
>> >> +const char *bdrv_get_device_name(const BlockDriverState *bs)
>> >>  {
>> >> -    return bs->device_name;
>> >> +    const char *name = bs->blk ? blk_name(bs->blk) : NULL;
>> >> +    return name ?: "";
>> >>  }
>> > 
>> > Why not ?
>> > 
>> >     return bs->blk ? blk_name(bs->blk) : "";
>> 
>> If I understand right, it was because blk_name(bs->blk) may return NULL,
>
> It think it can't: see patch 2 extract:
>
>> +BlockBackend *blk_new(const char *name, Error **errp)
>> +{
>> +    BlockBackend *blk = g_new0(BlockBackend, 1);
>> +     
>> +    assert(name && name[0]);
>
>> but this function is guaranteed to return non-NULL.

You're right, blk_new() always returns a non-null, non-empty string.

The condition to check here is "bs is not owned by a BB".  Benoît's

    bs->blk ? blk_name(bs->blk) : ""

does that nicely.

Of course, Eric is right in that returning NULL on "not owned by a BB"
would be cleaner than returning "".  However, doing that in the middle
of a series with a four-digit diffstat doesn't strike me as a good
idea.  Better do it on top.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
  2014-09-11 17:06   ` Benoît Canet
@ 2014-09-11 19:12     ` Markus Armbruster
  2014-09-11 19:34       ` Benoît Canet
  0 siblings, 1 reply; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 19:12 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

>> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
>
> This seems to be a fairly common pattern: "blk_bs(blk_by_legacy_dinfo())".
> How about a helper function ?

Yes, except the pattern is going to evaporate in patch 14 :)

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
  2014-09-11 12:07   ` Benoît Canet
@ 2014-09-11 19:20     ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 19:20 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> I have trouble to review this as I don't understand the qdevs parts.
> Maybe someone else could have a look at it.

The patch is big, but all it really does is replacing

    dinfo->bdrv

by

    blk_bs(blk_legacy_dinfo(dinfo))

Line wrapping muddies the waters a bit.  I also omit tests whether
dinfo->bdrv is null, because it never is.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] block: Rename BlockDriverAIOCB* to BlockAIOCB*
  2014-09-11 12:15   ` Benoît Canet
@ 2014-09-11 19:23     ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 19:23 UTC (permalink / raw)
  To: Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

Benoît Canet <benoit.canet@irqsave.net> writes:

> I think you should rebase this on top of Fam's null driver.

This patch is prone to conflicts, but I expect them to be trivial.  I'll
rebase onto whatever is current when we're ready to merge.

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe
  2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
                   ` (22 preceding siblings ...)
  2014-09-10  8:13 ` [Qemu-devel] [PATCH 23/23] block: Make device model's references to BlockBackend strong Markus Armbruster
@ 2014-09-11 19:24 ` Markus Armbruster
  23 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-11 19:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, benoit.canet, famz, stefanha

Review led to a couple of changes with ripple effects on later patches.
I suggest y'all await my v2 before you continue.

Thanks a lot for the review so far!

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
  2014-09-11 19:12     ` Markus Armbruster
@ 2014-09-11 19:34       ` Benoît Canet
  2014-09-11 19:40         ` Eric Blake
  0 siblings, 1 reply; 76+ messages in thread
From: Benoît Canet @ 2014-09-11 19:34 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: Benoît Canet, kwolf, famz, qemu-devel, stefanha

The Thursday 11 Sep 2014 à 21:12:44 (+0200), Markus Armbruster wrote :
> Benoît Canet <benoit.canet@irqsave.net> writes:
> 
> >> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
> >
> > This seems to be a fairly common pattern: "blk_bs(blk_by_legacy_dinfo())".
> > How about a helper function ?
> 
> Yes, except the pattern is going to evaporate in patch 14 :)

haha

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
  2014-09-11 19:34       ` Benoît Canet
@ 2014-09-11 19:40         ` Eric Blake
  2014-09-12  6:38           ` Markus Armbruster
  0 siblings, 1 reply; 76+ messages in thread
From: Eric Blake @ 2014-09-11 19:40 UTC (permalink / raw)
  To: Benoît Canet, Markus Armbruster; +Cc: kwolf, famz, qemu-devel, stefanha

[-- Attachment #1: Type: text/plain, Size: 838 bytes --]

On 09/11/2014 01:34 PM, Benoît Canet wrote:
> The Thursday 11 Sep 2014 à 21:12:44 (+0200), Markus Armbruster wrote :
>> Benoît Canet <benoit.canet@irqsave.net> writes:
>>
>>>> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
>>>
>>> This seems to be a fairly common pattern: "blk_bs(blk_by_legacy_dinfo())".
>>> How about a helper function ?
>>
>> Yes, except the pattern is going to evaporate in patch 14 :)
> 
> haha

Still, worth mentioning this fact in the commit message, rather than
making reviewers guess at it (that is, add a sentence something like:
This commit mechanically introduces long lines via repetitive pattern
replacement that will be shortened in a later patch


-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo
  2014-09-11 18:03     ` Markus Armbruster
@ 2014-09-11 20:43       ` Eric Blake
  0 siblings, 0 replies; 76+ messages in thread
From: Eric Blake @ 2014-09-11 20:43 UTC (permalink / raw)
  To: Markus Armbruster, Benoît Canet; +Cc: kwolf, famz, qemu-devel, stefanha

[-- Attachment #1: Type: text/plain, Size: 1712 bytes --]

On 09/11/2014 12:03 PM, Markus Armbruster wrote:
> Benoît Canet <benoit.canet@irqsave.net> writes:
> 
>> The Wednesday 10 Sep 2014 à 10:13:33 (+0200), Markus Armbruster wrote :
>>> Make the BlockBackend own the DriveInfo.  Change blockdev_init() to
>>> return the BlockBackend instead of the DriveInfo.
>>>
>>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>>> ---


>>> +static void drive_info_del(DriveInfo *dinfo);
>>
>> Is there any technical reason not to just put the
>> drive_info_del above the blk_delete function ?
>> I don't see any possible circular references between the two.
>>
>> Some people like Eric frown upon static function prototypes
>> in final code that's why I am asking.

I dislike it in code I write, and so I point it out in reviews, but I
also concede that it is a style, not technical issue, so I will never
reject a patch that uses forward declarations if the author thinks that
makes the presentation of the overall file easier to follow.

> 
> Placing functions before their callers makes the program easier to read
> when you need to see the functions definition before you can understand
> their use.
> 
> Placing the functions after callers makes the program easier to read
> when the gist of what they do is obvious from the call.  You're omitting
> unnecessary detail there, to be flesh it own further down.  Saving a
> function declaration is immaterial compared to that.
> 
> Before I put the function where I don't want it, I'd inline it :)

Then I won't try to convince you to paint the bikeshed any other color.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 539 bytes --]

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
  2014-09-11 19:40         ` Eric Blake
@ 2014-09-12  6:38           ` Markus Armbruster
  0 siblings, 0 replies; 76+ messages in thread
From: Markus Armbruster @ 2014-09-12  6:38 UTC (permalink / raw)
  To: Eric Blake; +Cc: Benoît Canet, kwolf, famz, qemu-devel, stefanha

Eric Blake <eblake@redhat.com> writes:

> On 09/11/2014 01:34 PM, Benoît Canet wrote:
>> The Thursday 11 Sep 2014 à 21:12:44 (+0200), Markus Armbruster wrote :
>>> Benoît Canet <benoit.canet@irqsave.net> writes:
>>>
>>>>> +                                   blk_bs(blk_by_legacy_dinfo(dinfo)));
>>>>
>>>> This seems to be a fairly common pattern: "blk_bs(blk_by_legacy_dinfo())".
>>>> How about a helper function ?
>>>
>>> Yes, except the pattern is going to evaporate in patch 14 :)
>> 
>> haha
>
> Still, worth mentioning this fact in the commit message, rather than
> making reviewers guess at it (that is, add a sentence something like:
> This commit mechanically introduces long lines via repetitive pattern
> replacement that will be shortened in a later patch

I can do that.

^ permalink raw reply	[flat|nested] 76+ messages in thread

end of thread, other threads:[~2014-09-12  6:38 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-10  8:13 [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 01/23] block: Split bdrv_new_named() off bdrv_new() Markus Armbruster
2014-09-10 11:03   ` Benoît Canet
2014-09-10 15:05     ` Eric Blake
2014-09-11  8:20       ` Markus Armbruster
2014-09-11  8:29     ` Markus Armbruster
2014-09-10 15:07   ` Eric Blake
2014-09-10 15:27   ` Benoît Canet
2014-09-10 21:22   ` Benoît Canet
2014-09-11  6:33   ` Fam Zheng
2014-09-10  8:13 ` [Qemu-devel] [PATCH 02/23] block: New BlockBackend Markus Armbruster
2014-09-10  9:56   ` Kevin Wolf
2014-09-11 10:03     ` Markus Armbruster
2014-09-11 11:45       ` Markus Armbruster
2014-09-11 14:38       ` Markus Armbruster
2014-09-10 11:34   ` Benoît Canet
2014-09-10 11:44     ` Kevin Wolf
2014-09-10 11:51       ` Benoît Canet
2014-09-11 10:11     ` Markus Armbruster
2014-09-10 12:40   ` Benoît Canet
2014-09-10 12:46     ` Benoît Canet
2014-09-11 10:22       ` Markus Armbruster
2014-09-11 10:21     ` Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 03/23] block: Connect BlockBackend to BlockDriverState Markus Armbruster
2014-09-10 11:55   ` Benoît Canet
2014-09-11 10:52     ` Markus Armbruster
2014-09-10 12:24   ` Kevin Wolf
2014-09-11 15:27     ` Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 04/23] block: Connect BlockBackend and DriveInfo Markus Armbruster
2014-09-10 13:08   ` Benoît Canet
2014-09-11 18:03     ` Markus Armbruster
2014-09-11 20:43       ` Eric Blake
2014-09-10 13:30   ` Kevin Wolf
2014-09-11 17:41     ` Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 05/23] block: Make BlockBackend own its BlockDriverState Markus Armbruster
2014-09-10 10:14   ` Kevin Wolf
2014-09-11 18:38     ` Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 06/23] block: Eliminate bdrv_states, use block_next() instead Markus Armbruster
2014-09-11 10:25   ` Benoît Canet
2014-09-10  8:13 ` [Qemu-devel] [PATCH 07/23] block: Eliminate bdrv_iterate(), use bdrv_next() Markus Armbruster
2014-09-11 10:46   ` Benoît Canet
2014-09-11 18:44     ` Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 08/23] block: Eliminate BlockDriverState member device_name[] Markus Armbruster
2014-09-10 16:09   ` Eric Blake
2014-09-11 18:45     ` Markus Armbruster
2014-09-11 11:34   ` Benoît Canet
2014-09-11 11:43     ` Benoît Canet
2014-09-11 13:00     ` Eric Blake
2014-09-11 13:18       ` Benoît Canet
2014-09-11 19:11         ` Markus Armbruster
2014-09-11 19:01     ` Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 09/23] block: Merge BlockBackend and BlockDriverState name spaces Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 10/23] block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo() Markus Armbruster
2014-09-11 12:07   ` Benoît Canet
2014-09-11 19:20     ` Markus Armbruster
2014-09-11 17:06   ` Benoît Canet
2014-09-11 19:12     ` Markus Armbruster
2014-09-11 19:34       ` Benoît Canet
2014-09-11 19:40         ` Eric Blake
2014-09-12  6:38           ` Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 11/23] block: Rename BlockDriverAIOCB* to BlockAIOCB* Markus Armbruster
2014-09-11 12:15   ` Benoît Canet
2014-09-11 19:23     ` Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 12/23] virtio-blk: Drop redundant VirtIOBlock member conf Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 13/23] virtio-blk: Rename VirtIOBlkConf variables to conf Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 14/23] hw: Convert from BlockDriverState to BlockBackend, mostly Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 15/23] ide: Complete conversion from BlockDriverState to BlockBackend Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 16/23] pc87312: Drop unused members of PC87312State Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 17/23] blockdev: Drop superfluous DriveInfo member id Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 18/23] blockdev: Fix blockdev-add not to create IDE drive (0, 0) Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 19/23] blockdev: Drop DriveInfo member enable_auto_del Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 20/23] block/qapi: Convert qmp_query_block() to BlockBackend Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 21/23] blockdev: Convert qmp_eject(), qmp_change_blockdev() " Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 22/23] block: Lift device model API into BlockBackend Markus Armbruster
2014-09-10  8:13 ` [Qemu-devel] [PATCH 23/23] block: Make device model's references to BlockBackend strong Markus Armbruster
2014-09-11 19:24 ` [Qemu-devel] [PATCH 00/23] Split BlockBackend off BDS with an axe Markus Armbruster

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.