All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH 0/5] block: Format/protocol split
@ 2010-04-14 15:50 Kevin Wolf
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 1/5] block: separate raw images from the file protocol Kevin Wolf
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Kevin Wolf @ 2010-04-14 15:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, hch

This is the next version of the format/protocol split RFC that Christoph posted
on Monday. I did fix image creation in his original patch and added some
additional patches for more cleanup and to fix the no_zero_init bug that is
mentioned in the commit log of this first patch.

One point that still needs to be done is converting all the random format
drivers that noone uses to use block.c functions instead of POSIX functions.
In some points they look like protocol drivers rather than format drivers
otherwise.

If there are no other important issues left, I'm going to merge this into the
block branch soon.

Christoph Hellwig (1):
  block: separate raw images from the file protocol

Kevin Wolf (4):
  block: Split bdrv_open
  block: Avoid forward declaration of bdrv_open_common
  block: Open the underlying image file in generic code
  block: bdrv_has_zero_init

 Makefile.objs          |    2 +-
 block.c                |  266 ++++++++++++++++++++++++++++++++----------------
 block.h                |    2 +
 block/blkdebug.c       |   17 +--
 block/bochs.c          |    2 +-
 block/cloop.c          |    2 +-
 block/cow.c            |    2 +-
 block/curl.c           |   10 +-
 block/dmg.c            |    2 +-
 block/nbd.c            |    2 +-
 block/parallels.c      |    2 +-
 block/qcow.c           |   69 ++++++-------
 block/qcow2-cluster.c  |   64 ++++++------
 block/qcow2-refcount.c |   80 +++++++-------
 block/qcow2-snapshot.c |   22 ++--
 block/qcow2.c          |   67 +++++-------
 block/qcow2.h          |    2 +-
 block/raw-posix.c      |   25 +++--
 block/raw-win32.c      |   16 ++--
 block/raw.c            |  144 ++++++++++++++++++++++++++
 block/vdi.c            |   30 ++----
 block/vmdk.c           |    2 +-
 block/vpc.c            |   34 +++----
 block/vvfat.c          |    2 +-
 block_int.h            |    5 +-
 qemu-img.c             |    6 +-
 26 files changed, 544 insertions(+), 333 deletions(-)
 create mode 100644 block/raw.c

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

* [Qemu-devel] [RFC PATCH 1/5] block: separate raw images from the file protocol
  2010-04-14 15:50 [Qemu-devel] [RFC PATCH 0/5] block: Format/protocol split Kevin Wolf
@ 2010-04-14 15:50 ` Kevin Wolf
  2010-04-14 18:36   ` Stefan Hajnoczi
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 2/5] block: Split bdrv_open Kevin Wolf
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Kevin Wolf @ 2010-04-14 15:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, hch

From: Christoph Hellwig <hch@lst.de>

We're running into various problems because the "raw" file access, which
is used internally by the various image formats is entangled with the
"raw" image format, which maps the VM view 1:1 to a file system.

This patch renames the raw file backends to the file protocol which
is treated like other protocols (e.g. nbd and http) and adds a new
"raw" image format which is just a wrapper around calls to the underlying
protocol.

The patch is surprisingly simple, besides changing the probing logical
in block.c to only look for image formats when using bdrv_open and
renaming of the old raw protocols to file there's almost nothing in there.

For creating images, a new bdrv_create_file is introduced which guesses the
protocol to use. This allows using qemu-img create -f raw (or just using the
default) for both files and host devices. Converting the other format drivers
to use this function to create their images is left for later patches.

The only issues still open are in the handling of the host devices.
Firstly in current qemu we can specifiy the host* format names
on various command line acceping images, but the new code can't
do that without adding some translation.  Second the layering breaks
the no_zero_init flag in the BlockDriver used by qemu-img.  I'm not
happy how this is done per-driver instead of per-state so I'll
prepare a separate patch to clean this up.

There's some more cleanup opportunity after this patch, e.g. using
separate lists and registration functions for image formats vs
protocols and maybe even host drivers, but this can be done at a
later stage.

Also there's a check for protocol in bdrv_open for the BDRV_O_SNAPSHOT
case that I don't quite understand, but which I fear won't work as
expected - possibly even before this patch.

Note that this patch requires various recent block patches from Kevin
and me, which should all be in his block queue.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 Makefile.objs     |    2 +-
 block.c           |   74 ++++++++++++++---------
 block.h           |    1 +
 block/raw-posix.c |   15 +++--
 block/raw-win32.c |   12 ++--
 block/raw.c       |  171 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 235 insertions(+), 40 deletions(-)
 create mode 100644 block/raw.c

diff --git a/Makefile.objs b/Makefile.objs
index 67a8a1e..10900c9 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -12,7 +12,7 @@ block-obj-y += nbd.o block.o aio.o aes.o osdep.o qemu-config.o
 block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 
-block-nested-y += cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
+block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
 block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o
 block-nested-y += parallels.o nbd.o blkdebug.o
 block-nested-$(CONFIG_WIN32) += raw-win32.o
diff --git a/block.c b/block.c
index 12cf434..715c30e 100644
--- a/block.c
+++ b/block.c
@@ -54,6 +54,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
                         uint8_t *buf, int nb_sectors);
 static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
                          const uint8_t *buf, int nb_sectors);
+static BlockDriver *find_protocol(const char *filename);
 
 static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
     QTAILQ_HEAD_INITIALIZER(bdrv_states);
@@ -203,6 +204,18 @@ int bdrv_create(BlockDriver *drv, const char* filename,
     return drv->bdrv_create(filename, options);
 }
 
+int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
+{
+    BlockDriver *drv;
+
+    drv = find_protocol(filename);
+    if (drv == NULL) {
+        drv = bdrv_find_format("file");
+    }
+
+    return bdrv_create(drv, filename, options);
+}
+
 #ifdef _WIN32
 void get_tmp_filename(char *filename, int size)
 {
@@ -246,6 +259,28 @@ int is_windows_drive(const char *filename)
 }
 #endif
 
+/*
+ * Detect host devices. By convention, /dev/cdrom[N] is always
+ * recognized as a host CDROM.
+ */
+static BlockDriver *find_hdev_driver(const char *filename)
+{
+    int score_max = 0, score;
+    BlockDriver *drv = NULL, *d;
+
+    QLIST_FOREACH(d, &bdrv_drivers, list) {
+        if (d->bdrv_probe_device) {
+            score = d->bdrv_probe_device(filename);
+            if (score > score_max) {
+                score_max = score;
+                drv = d;
+            }
+        }
+    }
+
+    return drv;
+}
+
 static BlockDriver *find_protocol(const char *filename)
 {
     BlockDriver *drv1;
@@ -256,11 +291,16 @@ static BlockDriver *find_protocol(const char *filename)
 #ifdef _WIN32
     if (is_windows_drive(filename) ||
         is_windows_drive_prefix(filename))
-        return bdrv_find_format("raw");
+        return bdrv_find_format("file");
 #endif
     p = strchr(filename, ':');
-    if (!p)
-        return bdrv_find_format("raw");
+    if (!p) {
+        drv1 = find_hdev_driver(filename);
+        if (!drv1) {
+            drv1 = bdrv_find_format("file");
+        }
+        return drv1;
+    }
     len = p - filename;
     if (len > sizeof(protocol) - 1)
         len = sizeof(protocol) - 1;
@@ -275,28 +315,6 @@ static BlockDriver *find_protocol(const char *filename)
     return NULL;
 }
 
-/*
- * Detect host devices. By convention, /dev/cdrom[N] is always
- * recognized as a host CDROM.
- */
-static BlockDriver *find_hdev_driver(const char *filename)
-{
-    int score_max = 0, score;
-    BlockDriver *drv = NULL, *d;
-
-    QLIST_FOREACH(d, &bdrv_drivers, list) {
-        if (d->bdrv_probe_device) {
-            score = d->bdrv_probe_device(filename);
-            if (score > score_max) {
-                score_max = score;
-                drv = d;
-            }
-        }
-    }
-
-    return drv;
-}
-
 static BlockDriver *find_image_format(const char *filename)
 {
     int ret, score, score_max;
@@ -319,6 +337,7 @@ static BlockDriver *find_image_format(const char *filename)
     }
 
     score_max = 0;
+    drv = NULL;
     QLIST_FOREACH(drv1, &bdrv_drivers, list) {
         if (drv1->bdrv_probe) {
             score = drv1->bdrv_probe(buf, ret, filename);
@@ -423,10 +442,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
     pstrcpy(bs->filename, sizeof(bs->filename), filename);
 
     if (!drv) {
-        drv = find_hdev_driver(filename);
-        if (!drv) {
-            drv = find_image_format(filename);
-        }
+        drv = find_image_format(filename);
     }
 
     if (!drv) {
diff --git a/block.h b/block.h
index 05ad572..f58edf1 100644
--- a/block.h
+++ b/block.h
@@ -57,6 +57,7 @@ BlockDriver *bdrv_find_format(const char *format_name);
 BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
 int bdrv_create(BlockDriver *drv, const char* filename,
     QEMUOptionParameter *options);
+int bdrv_create_file(const char* filename, QEMUOptionParameter *options);
 BlockDriverState *bdrv_new(const char *device_name);
 void bdrv_delete(BlockDriverState *bs);
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 4cda9c1..8f57ab0 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -768,8 +768,9 @@ static QEMUOptionParameter raw_create_options[] = {
     { NULL }
 };
 
-static BlockDriver bdrv_raw = {
-    .format_name = "raw",
+static BlockDriver bdrv_file = {
+    .format_name = "file",
+    .protocol_name = "file",
     .instance_size = sizeof(BDRVRawState),
     .bdrv_probe = NULL, /* no probe for protocols */
     .bdrv_open = raw_open,
@@ -1026,6 +1027,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
 
 static BlockDriver bdrv_host_device = {
     .format_name        = "host_device",
+    .protocol_name        = "host_device",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device  = hdev_probe_device,
     .bdrv_open          = hdev_open,
@@ -1140,6 +1142,7 @@ static int floppy_eject(BlockDriverState *bs, int eject_flag)
 
 static BlockDriver bdrv_host_floppy = {
     .format_name        = "host_floppy",
+    .protocol_name      = "host_floppy",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= floppy_probe_device,
     .bdrv_open          = floppy_open,
@@ -1239,6 +1242,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)
 
 static BlockDriver bdrv_host_cdrom = {
     .format_name        = "host_cdrom",
+    .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= cdrom_probe_device,
     .bdrv_open          = cdrom_open,
@@ -1361,6 +1365,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)
 
 static BlockDriver bdrv_host_cdrom = {
     .format_name        = "host_cdrom",
+    .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= cdrom_probe_device,
     .bdrv_open          = cdrom_open,
@@ -1385,13 +1390,13 @@ static BlockDriver bdrv_host_cdrom = {
 };
 #endif /* __FreeBSD__ */
 
-static void bdrv_raw_init(void)
+static void bdrv_file_init(void)
 {
     /*
      * Register all the drivers.  Note that order is important, the driver
      * registered last will get probed first.
      */
-    bdrv_register(&bdrv_raw);
+    bdrv_register(&bdrv_file);
     bdrv_register(&bdrv_host_device);
 #ifdef __linux__
     bdrv_register(&bdrv_host_floppy);
@@ -1402,4 +1407,4 @@ static void bdrv_raw_init(void)
 #endif
 }
 
-block_init(bdrv_raw_init);
+block_init(bdrv_file_init);
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 526764f..eadebeb 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -238,8 +238,9 @@ static QEMUOptionParameter raw_create_options[] = {
     { NULL }
 };
 
-static BlockDriver bdrv_raw = {
-    .format_name	= "raw",
+static BlockDriver bdrv_file = {
+    .format_name	= "file",
+    .protocol_name	= "file",
     .instance_size	= sizeof(BDRVRawState),
     .bdrv_open		= raw_open,
     .bdrv_close		= raw_close,
@@ -395,6 +396,7 @@ static int raw_set_locked(BlockDriverState *bs, int locked)
 
 static BlockDriver bdrv_host_device = {
     .format_name	= "host_device",
+    .protocol_name	= "host_device",
     .instance_size	= sizeof(BDRVRawState),
     .bdrv_probe_device	= hdev_probe_device,
     .bdrv_open		= hdev_open,
@@ -406,10 +408,10 @@ static BlockDriver bdrv_host_device = {
     .bdrv_getlength	= raw_getlength,
 };
 
-static void bdrv_raw_init(void)
+static void bdrv_file_init(void)
 {
-    bdrv_register(&bdrv_raw);
+    bdrv_register(&bdrv_file);
     bdrv_register(&bdrv_host_device);
 }
 
-block_init(bdrv_raw_init);
+block_init(bdrv_file_init);
diff --git a/block/raw.c b/block/raw.c
new file mode 100644
index 0000000..953e285
--- /dev/null
+++ b/block/raw.c
@@ -0,0 +1,171 @@
+
+#include "qemu-common.h"
+#include "block_int.h"
+#include "module.h"
+
+typedef struct RAWState {
+    BlockDriverState *hd;
+} RAWState;
+
+static int raw_open(BlockDriverState *bs, const char *filename, int flags)
+{
+    RAWState *s = bs->opaque;
+    int ret;
+
+    ret = bdrv_file_open(&s->hd, filename, flags);
+    if (!ret) {
+        bs->sg = s->hd->sg;
+    }
+
+    return ret;
+}
+
+static int raw_read(BlockDriverState *bs, int64_t sector_num,
+                    uint8_t *buf, int nb_sectors)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_read(s->hd, sector_num, buf, nb_sectors);
+}
+
+static int raw_write(BlockDriverState *bs, int64_t sector_num,
+                     const uint8_t *buf, int nb_sectors)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_write(s->hd, sector_num, buf, nb_sectors);
+}
+
+static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
+    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RAWState *s = bs->opaque;
+
+    return bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+}
+
+static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
+    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RAWState *s = bs->opaque;
+
+    return bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+}
+
+static void raw_close(BlockDriverState *bs)
+{
+    RAWState *s = bs->opaque;
+    bdrv_delete(s->hd);
+}
+
+static void raw_flush(BlockDriverState *bs)
+{
+    RAWState *s = bs->opaque;
+    bdrv_flush(s->hd);
+}
+
+static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_aio_flush(s->hd, cb, opaque);
+}
+
+static int64_t raw_getlength(BlockDriverState *bs)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_getlength(s->hd);
+}
+
+static int raw_truncate(BlockDriverState *bs, int64_t offset)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_truncate(s->hd, offset);
+}
+
+static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+   return 1; /* everything can be opened as raw image */
+}
+
+static int raw_is_inserted(BlockDriverState *bs)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_is_inserted(s->hd);
+}
+
+static int raw_eject(BlockDriverState *bs, int eject_flag)
+{
+    RAWState *s = bs->opaque;
+    return bdrv_eject(s->hd, eject_flag);
+}
+
+static int raw_set_locked(BlockDriverState *bs, int locked)
+{
+    RAWState *s = bs->opaque;
+    bdrv_set_locked(s->hd, locked);
+    return 0;
+}
+
+static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+{
+   RAWState *s = bs->opaque;
+   return bdrv_ioctl(s->hd, req, buf);
+}
+
+static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
+        unsigned long int req, void *buf,
+        BlockDriverCompletionFunc *cb, void *opaque)
+{
+   RAWState *s = bs->opaque;
+   return bdrv_aio_ioctl(s->hd, req, buf, cb, opaque);
+}
+
+static int raw_create(const char *filename, QEMUOptionParameter *options)
+{
+    return bdrv_create_file(filename, options);
+}
+
+static QEMUOptionParameter raw_create_options[] = {
+    {
+        .name = BLOCK_OPT_SIZE,
+        .type = OPT_SIZE,
+        .help = "Virtual disk size"
+    },
+    { NULL }
+};
+
+static BlockDriver bdrv_raw = {
+    .format_name        = "raw",
+
+    .instance_size      = sizeof(RAWState),
+
+    .bdrv_open          = raw_open,
+    .bdrv_close         = raw_close,
+    .bdrv_read          = raw_read,
+    .bdrv_write         = raw_write,
+    .bdrv_flush         = raw_flush,
+    .bdrv_probe         = raw_probe,
+    .bdrv_getlength     = raw_getlength,
+    .bdrv_truncate      = raw_truncate,
+
+    .bdrv_aio_readv     = raw_aio_readv,
+    .bdrv_aio_writev    = raw_aio_writev,
+    .bdrv_aio_flush     = raw_aio_flush,
+
+    .bdrv_is_inserted   = raw_is_inserted,
+    .bdrv_eject         = raw_eject,
+    .bdrv_set_locked    = raw_set_locked,
+    .bdrv_ioctl         = raw_ioctl,
+    .bdrv_aio_ioctl     = raw_aio_ioctl,
+
+    .bdrv_create        = raw_create,
+    .create_options     = raw_create_options,
+};
+
+static void bdrv_raw_init(void)
+{
+    bdrv_register(&bdrv_raw);
+}
+
+block_init(bdrv_raw_init);
-- 
1.6.6.1

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

* [Qemu-devel] [RFC PATCH 2/5] block: Split bdrv_open
  2010-04-14 15:50 [Qemu-devel] [RFC PATCH 0/5] block: Format/protocol split Kevin Wolf
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 1/5] block: separate raw images from the file protocol Kevin Wolf
@ 2010-04-14 15:50 ` Kevin Wolf
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 3/5] block: Avoid forward declaration of bdrv_open_common Kevin Wolf
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2010-04-14 15:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, hch

bdrv_open contains quite some code that is only useful for opening images (as
opposed to opening files by a protocol), for example snapshots.

This patch splits the code so that we have bdrv_open_file() for files (uses
protocols), bdrv_open() for images (uses format drivers) and bdrv_open_common()
for the code common for opening both images and files.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c |  135 ++++++++++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 86 insertions(+), 49 deletions(-)

diff --git a/block.c b/block.c
index 715c30e..e04f80d 100644
--- a/block.c
+++ b/block.c
@@ -42,6 +42,9 @@
 #include <windows.h>
 #endif
 
+static int bdrv_open_common(BlockDriverState *bs, const char *filename,
+    int flags, BlockDriver *drv);
+
 static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque);
@@ -350,6 +353,9 @@ static BlockDriver *find_image_format(const char *filename)
     return drv;
 }
 
+/*
+ * Opens a file using a protocol (file, host_device, nbd, ...)
+ */
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
 {
     BlockDriverState *bs;
@@ -362,7 +368,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     }
 
     bs = bdrv_new("");
-    ret = bdrv_open(bs, filename, flags, drv);
+    ret = bdrv_open_common(bs, filename, flags, drv);
     if (ret < 0) {
         bdrv_delete(bs);
         return ret;
@@ -372,19 +378,13 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
     return 0;
 }
 
+/*
+ * Opens a disk image (raw, qcow2, vmdk, ...)
+ */
 int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
               BlockDriver *drv)
 {
-    int ret, open_flags;
-    char tmp_filename[PATH_MAX];
-    char backing_filename[PATH_MAX];
-
-    bs->is_temporary = 0;
-    bs->encrypted = 0;
-    bs->valid_key = 0;
-    bs->open_flags = flags;
-    /* buffer_alignment defaulted to 512, drivers can change this value */
-    bs->buffer_alignment = 512;
+    int ret;
 
     if (flags & BDRV_O_SNAPSHOT) {
         BlockDriverState *bs1;
@@ -392,6 +392,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         int is_protocol = 0;
         BlockDriver *bdrv_qcow2;
         QEMUOptionParameter *options;
+        char tmp_filename[PATH_MAX];
+        char backing_filename[PATH_MAX];
 
         /* if snapshot, we create a temporary backing file and open it
            instead of opening 'filename' directly */
@@ -439,8 +441,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         bs->is_temporary = 1;
     }
 
-    pstrcpy(bs->filename, sizeof(bs->filename), filename);
-
+    /* Find the right image format driver */
     if (!drv) {
         drv = find_image_format(filename);
     }
@@ -449,11 +450,81 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         ret = -ENOENT;
         goto unlink_and_fail;
     }
-    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
-        ret = -ENOTSUP;
+
+    /* Open the image */
+    ret = bdrv_open_common(bs, filename, flags, drv);
+    if (ret < 0) {
         goto unlink_and_fail;
     }
 
+    /* If there is a backing file, use it */
+    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
+        char backing_filename[PATH_MAX];
+        int back_flags;
+        BlockDriver *back_drv = NULL;
+
+        bs->backing_hd = bdrv_new("");
+        path_combine(backing_filename, sizeof(backing_filename),
+                     filename, bs->backing_file);
+        if (bs->backing_format[0] != '\0')
+            back_drv = bdrv_find_format(bs->backing_format);
+
+        /* backing files always opened read-only */
+        back_flags =
+            flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
+
+        ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv);
+        if (ret < 0) {
+            bdrv_close(bs);
+            return ret;
+        }
+        if (bs->is_temporary) {
+            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);
+        } else {
+            /* base image inherits from "parent" */
+            bs->backing_hd->keep_read_only = bs->keep_read_only;
+        }
+    }
+
+    if (!bdrv_key_required(bs)) {
+        /* call the change callback */
+        bs->media_changed = 1;
+        if (bs->change_cb)
+            bs->change_cb(bs->change_opaque);
+    }
+
+    return 0;
+
+unlink_and_fail:
+    if (bs->is_temporary) {
+        unlink(filename);
+    }
+    return ret;
+}
+
+/*
+ * Common part for opening disk images and files
+ */
+static int bdrv_open_common(BlockDriverState *bs, const char *filename,
+    int flags, BlockDriver *drv)
+{
+    int ret, open_flags;
+
+    assert(drv != NULL);
+
+    bs->is_temporary = 0;
+    bs->encrypted = 0;
+    bs->valid_key = 0;
+    bs->open_flags = flags;
+    /* buffer_alignment defaulted to 512, drivers can change this value */
+    bs->buffer_alignment = 512;
+
+    pstrcpy(bs->filename, sizeof(bs->filename), filename);
+
+    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
+        return -ENOTSUP;
+    }
+
     bs->drv = drv;
     bs->opaque = qemu_mallocz(drv->instance_size);
 
@@ -493,46 +564,12 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
         unlink(filename);
     }
 #endif
-    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
-        /* if there is a backing file, use it */
-        BlockDriver *back_drv = NULL;
-        bs->backing_hd = bdrv_new("");
-        path_combine(backing_filename, sizeof(backing_filename),
-                     filename, bs->backing_file);
-        if (bs->backing_format[0] != '\0')
-            back_drv = bdrv_find_format(bs->backing_format);
-
-        /* backing files always opened read-only */
-        open_flags &= ~BDRV_O_RDWR;
-
-        ret = bdrv_open(bs->backing_hd, backing_filename, open_flags, back_drv);
-        if (ret < 0) {
-            bdrv_close(bs);
-            return ret;
-        }
-        if (bs->is_temporary) {
-            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);
-        } else {
-            /* base image inherits from "parent" */
-            bs->backing_hd->keep_read_only = bs->keep_read_only;
-        }
-    }
-
-    if (!bdrv_key_required(bs)) {
-        /* call the change callback */
-        bs->media_changed = 1;
-        if (bs->change_cb)
-            bs->change_cb(bs->change_opaque);
-    }
     return 0;
 
 free_and_fail:
     qemu_free(bs->opaque);
     bs->opaque = NULL;
     bs->drv = NULL;
-unlink_and_fail:
-    if (bs->is_temporary)
-        unlink(filename);
     return ret;
 }
 
-- 
1.6.6.1

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

* [Qemu-devel] [RFC PATCH 3/5] block: Avoid forward declaration of bdrv_open_common
  2010-04-14 15:50 [Qemu-devel] [RFC PATCH 0/5] block: Format/protocol split Kevin Wolf
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 1/5] block: separate raw images from the file protocol Kevin Wolf
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 2/5] block: Split bdrv_open Kevin Wolf
@ 2010-04-14 15:50 ` Kevin Wolf
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 4/5] block: Open the underlying image file in generic code Kevin Wolf
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 5/5] block: bdrv_has_zero_init Kevin Wolf
  4 siblings, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2010-04-14 15:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, hch

Move bdrv_open_common so it's defined before its callers and remove the forward
declaration.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c |  145 +++++++++++++++++++++++++++++++--------------------------------
 1 files changed, 71 insertions(+), 74 deletions(-)

diff --git a/block.c b/block.c
index e04f80d..fd70d64 100644
--- a/block.c
+++ b/block.c
@@ -42,9 +42,6 @@
 #include <windows.h>
 #endif
 
-static int bdrv_open_common(BlockDriverState *bs, const char *filename,
-    int flags, BlockDriver *drv);
-
 static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
         BlockDriverCompletionFunc *cb, void *opaque);
@@ -354,6 +351,77 @@ static BlockDriver *find_image_format(const char *filename)
 }
 
 /*
+ * Common part for opening disk images and files
+ */
+static int bdrv_open_common(BlockDriverState *bs, const char *filename,
+    int flags, BlockDriver *drv)
+{
+    int ret, open_flags;
+
+    assert(drv != NULL);
+
+    bs->is_temporary = 0;
+    bs->encrypted = 0;
+    bs->valid_key = 0;
+    bs->open_flags = flags;
+    /* buffer_alignment defaulted to 512, drivers can change this value */
+    bs->buffer_alignment = 512;
+
+    pstrcpy(bs->filename, sizeof(bs->filename), filename);
+
+    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
+        return -ENOTSUP;
+    }
+
+    bs->drv = drv;
+    bs->opaque = qemu_mallocz(drv->instance_size);
+
+    /*
+     * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
+     * write cache to the guest.  We do need the fdatasync to flush
+     * out transactions for block allocations, and we maybe have a
+     * volatile write cache in our backing device to deal with.
+     */
+    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
+        bs->enable_write_cache = 1;
+
+    /*
+     * Clear flags that are internal to the block layer before opening the
+     * image.
+     */
+    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
+
+    /*
+     * Snapshots should be writeable.
+     */
+    if (bs->is_temporary) {
+        open_flags |= BDRV_O_RDWR;
+    }
+
+    ret = drv->bdrv_open(bs, filename, open_flags);
+    if (ret < 0) {
+        goto free_and_fail;
+    }
+
+    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
+    if (drv->bdrv_getlength) {
+        bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
+    }
+#ifndef _WIN32
+    if (bs->is_temporary) {
+        unlink(filename);
+    }
+#endif
+    return 0;
+
+free_and_fail:
+    qemu_free(bs->opaque);
+    bs->opaque = NULL;
+    bs->drv = NULL;
+    return ret;
+}
+
+/*
  * Opens a file using a protocol (file, host_device, nbd, ...)
  */
 int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
@@ -502,77 +570,6 @@ unlink_and_fail:
     return ret;
 }
 
-/*
- * Common part for opening disk images and files
- */
-static int bdrv_open_common(BlockDriverState *bs, const char *filename,
-    int flags, BlockDriver *drv)
-{
-    int ret, open_flags;
-
-    assert(drv != NULL);
-
-    bs->is_temporary = 0;
-    bs->encrypted = 0;
-    bs->valid_key = 0;
-    bs->open_flags = flags;
-    /* buffer_alignment defaulted to 512, drivers can change this value */
-    bs->buffer_alignment = 512;
-
-    pstrcpy(bs->filename, sizeof(bs->filename), filename);
-
-    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
-        return -ENOTSUP;
-    }
-
-    bs->drv = drv;
-    bs->opaque = qemu_mallocz(drv->instance_size);
-
-    /*
-     * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
-     * write cache to the guest.  We do need the fdatasync to flush
-     * out transactions for block allocations, and we maybe have a
-     * volatile write cache in our backing device to deal with.
-     */
-    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
-        bs->enable_write_cache = 1;
-
-    /*
-     * Clear flags that are internal to the block layer before opening the
-     * image.
-     */
-    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
-
-    /*
-     * Snapshots should be writeable.
-     */
-    if (bs->is_temporary) {
-        open_flags |= BDRV_O_RDWR;
-    }
-
-    ret = drv->bdrv_open(bs, filename, open_flags);
-    if (ret < 0) {
-        goto free_and_fail;
-    }
-
-    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
-    if (drv->bdrv_getlength) {
-        bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
-    }
-#ifndef _WIN32
-    if (bs->is_temporary) {
-        unlink(filename);
-    }
-#endif
-    return 0;
-
-free_and_fail:
-    qemu_free(bs->opaque);
-    bs->opaque = NULL;
-    bs->drv = NULL;
-    return ret;
-}
-
 void bdrv_close(BlockDriverState *bs)
 {
     if (bs->drv) {
-- 
1.6.6.1

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

* [Qemu-devel] [RFC PATCH 4/5] block: Open the underlying image file in generic code
  2010-04-14 15:50 [Qemu-devel] [RFC PATCH 0/5] block: Format/protocol split Kevin Wolf
                   ` (2 preceding siblings ...)
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 3/5] block: Avoid forward declaration of bdrv_open_common Kevin Wolf
@ 2010-04-14 15:50 ` Kevin Wolf
  2010-04-15  8:48   ` Stefan Hajnoczi
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 5/5] block: bdrv_has_zero_init Kevin Wolf
  4 siblings, 1 reply; 8+ messages in thread
From: Kevin Wolf @ 2010-04-14 15:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, hch

Format drivers shouldn't need to bother with things like file names, but rather
just get an open BlockDriverState for the underlying protocol. This patch
introduces this behaviour for bdrv_open implementation. For protocols which
need to access the filename to open their file/device/connection/... a new
callback bdrv_file_open is introduced which doesn't get an underlying file
opened.

For now, also some of the more obscure formats use bdrv_file_open because they
open() the file themselves instead of using the block.c functions. They need to
be fixed in later patches.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c                |   25 ++++++++++++++-
 block/blkdebug.c       |   17 +++------
 block/bochs.c          |    2 +-
 block/cloop.c          |    2 +-
 block/cow.c            |    2 +-
 block/curl.c           |   10 +++---
 block/dmg.c            |    2 +-
 block/nbd.c            |    2 +-
 block/parallels.c      |    2 +-
 block/qcow.c           |   69 +++++++++++++++++++----------------------
 block/qcow2-cluster.c  |   64 ++++++++++++++++++++------------------
 block/qcow2-refcount.c |   80 ++++++++++++++++++++++++------------------------
 block/qcow2-snapshot.c |   22 ++++++------
 block/qcow2.c          |   67 +++++++++++++++++-----------------------
 block/qcow2.h          |    2 +-
 block/raw-posix.c      |   10 +++---
 block/raw-win32.c      |    4 +-
 block/raw.c            |   63 +++++++++++---------------------------
 block/vdi.c            |   30 ++++++------------
 block/vmdk.c           |    2 +-
 block/vpc.c            |   34 ++++++++------------
 block/vvfat.c          |    2 +-
 block_int.h            |    5 ++-
 23 files changed, 242 insertions(+), 276 deletions(-)

diff --git a/block.c b/block.c
index fd70d64..6c66974 100644
--- a/block.c
+++ b/block.c
@@ -288,6 +288,8 @@ static BlockDriver *find_protocol(const char *filename)
     int len;
     const char *p;
 
+    /* TODO Drivers without bdrv_file_open must be specified explicitly */
+
 #ifdef _WIN32
     if (is_windows_drive(filename) ||
         is_windows_drive_prefix(filename))
@@ -398,7 +400,16 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
         open_flags |= BDRV_O_RDWR;
     }
 
-    ret = drv->bdrv_open(bs, filename, open_flags);
+    /* Open the image, either directly or using a protocol */
+    if (drv->bdrv_file_open) {
+        ret = drv->bdrv_file_open(bs, filename, open_flags);
+    } else {
+        ret = bdrv_file_open(&bs->file, filename, open_flags);
+        if (ret >= 0) {
+            ret = drv->bdrv_open(bs, open_flags);
+        }
+    }
+
     if (ret < 0) {
         goto free_and_fail;
     }
@@ -415,6 +426,10 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
     return 0;
 
 free_and_fail:
+    if (bs->file) {
+        bdrv_delete(bs->file);
+        bs->file = NULL;
+    }
     qemu_free(bs->opaque);
     bs->opaque = NULL;
     bs->drv = NULL;
@@ -585,6 +600,10 @@ void bdrv_close(BlockDriverState *bs)
         bs->opaque = NULL;
         bs->drv = NULL;
 
+        if (bs->file != NULL) {
+            bdrv_close(bs->file);
+        }
+
         /* call the change callback */
         bs->media_changed = 1;
         if (bs->change_cb)
@@ -600,6 +619,10 @@ void bdrv_delete(BlockDriverState *bs)
     }
 
     bdrv_close(bs);
+    if (bs->file != NULL) {
+        bdrv_delete(bs->file);
+    }
+
     qemu_free(bs);
 }
 
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 643c397..bb4a91a 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -44,7 +44,6 @@ typedef struct BlkdebugVars {
 } BlkdebugVars;
 
 typedef struct BDRVBlkdebugState {
-    BlockDriverState *hd;
     BlkdebugVars vars;
     QLIST_HEAD(list, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
 } BDRVBlkdebugState;
@@ -303,7 +302,7 @@ static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
     filename = c + 1;
 
     /* Open the backing file */
-    ret = bdrv_file_open(&s->hd, filename, flags);
+    ret = bdrv_file_open(&bs->file, filename, flags);
     if (ret < 0) {
         return ret;
     }
@@ -362,7 +361,7 @@ static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
     }
 
     BlockDriverAIOCB *acb =
-        bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+        bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
     return acb;
 }
 
@@ -377,7 +376,7 @@ static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
     }
 
     BlockDriverAIOCB *acb =
-        bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+        bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
     return acb;
 }
 
@@ -393,21 +392,17 @@ static void blkdebug_close(BlockDriverState *bs)
             qemu_free(rule);
         }
     }
-
-    bdrv_delete(s->hd);
 }
 
 static void blkdebug_flush(BlockDriverState *bs)
 {
-    BDRVBlkdebugState *s = bs->opaque;
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 static BlockDriverAIOCB *blkdebug_aio_flush(BlockDriverState *bs,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BDRVBlkdebugState *s = bs->opaque;
-    return bdrv_aio_flush(s->hd, cb, opaque);
+    return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
 static void process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
@@ -456,7 +451,7 @@ static BlockDriver bdrv_blkdebug = {
 
     .instance_size      = sizeof(BDRVBlkdebugState),
 
-    .bdrv_open          = blkdebug_open,
+    .bdrv_file_open     = blkdebug_open,
     .bdrv_close         = blkdebug_close,
     .bdrv_flush         = blkdebug_flush,
 
diff --git a/block/bochs.c b/block/bochs.c
index 843008f..c8f921f 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -254,7 +254,7 @@ static BlockDriver bdrv_bochs = {
     .format_name	= "bochs",
     .instance_size	= sizeof(BDRVBochsState),
     .bdrv_probe		= bochs_probe,
-    .bdrv_open		= bochs_open,
+    .bdrv_file_open	= bochs_open,
     .bdrv_read		= bochs_read,
     .bdrv_close		= bochs_close,
 };
diff --git a/block/cloop.c b/block/cloop.c
index bf1b9b4..96cbb89 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -161,7 +161,7 @@ static BlockDriver bdrv_cloop = {
     .format_name	= "cloop",
     .instance_size	= sizeof(BDRVCloopState),
     .bdrv_probe		= cloop_probe,
-    .bdrv_open		= cloop_open,
+    .bdrv_file_open	= cloop_open,
     .bdrv_read		= cloop_read,
     .bdrv_close		= cloop_close,
 };
diff --git a/block/cow.c b/block/cow.c
index 97e9745..fde066e 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -291,7 +291,7 @@ static BlockDriver bdrv_cow = {
     .format_name	= "cow",
     .instance_size	= sizeof(BDRVCowState),
     .bdrv_probe		= cow_probe,
-    .bdrv_open		= cow_open,
+    .bdrv_file_open	= cow_open,
     .bdrv_read		= cow_read,
     .bdrv_write		= cow_write,
     .bdrv_close		= cow_close,
diff --git a/block/curl.c b/block/curl.c
index 2cf72cb..b944740 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -495,7 +495,7 @@ static BlockDriver bdrv_http = {
     .protocol_name   = "http",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
@@ -507,7 +507,7 @@ static BlockDriver bdrv_https = {
     .protocol_name   = "https",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
@@ -519,7 +519,7 @@ static BlockDriver bdrv_ftp = {
     .protocol_name   = "ftp",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
@@ -531,7 +531,7 @@ static BlockDriver bdrv_ftps = {
     .protocol_name   = "ftps",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
@@ -543,7 +543,7 @@ static BlockDriver bdrv_tftp = {
     .protocol_name   = "tftp",
 
     .instance_size   = sizeof(BDRVCURLState),
-    .bdrv_open       = curl_open,
+    .bdrv_file_open  = curl_open,
     .bdrv_close      = curl_close,
     .bdrv_getlength  = curl_getlength,
 
diff --git a/block/dmg.c b/block/dmg.c
index dbb4eda..f65b5f5 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -291,7 +291,7 @@ static BlockDriver bdrv_dmg = {
     .format_name	= "dmg",
     .instance_size	= sizeof(BDRVDMGState),
     .bdrv_probe		= dmg_probe,
-    .bdrv_open		= dmg_open,
+    .bdrv_file_open	= dmg_open,
     .bdrv_read		= dmg_read,
     .bdrv_close		= dmg_close,
 };
diff --git a/block/nbd.c b/block/nbd.c
index 7bac38d..a1ec123 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -177,7 +177,7 @@ static int64_t nbd_getlength(BlockDriverState *bs)
 static BlockDriver bdrv_nbd = {
     .format_name	= "nbd",
     .instance_size	= sizeof(BDRVNBDState),
-    .bdrv_open		= nbd_open,
+    .bdrv_file_open	= nbd_open,
     .bdrv_read		= nbd_read,
     .bdrv_write		= nbd_write,
     .bdrv_close		= nbd_close,
diff --git a/block/parallels.c b/block/parallels.c
index b6312a6..3d04965 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -169,7 +169,7 @@ static BlockDriver bdrv_parallels = {
     .format_name	= "parallels",
     .instance_size	= sizeof(BDRVParallelsState),
     .bdrv_probe		= parallels_probe,
-    .bdrv_open		= parallels_open,
+    .bdrv_file_open	= parallels_open,
     .bdrv_read		= parallels_read,
     .bdrv_close		= parallels_close,
 };
diff --git a/block/qcow.c b/block/qcow.c
index c619984..01b1692 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -76,7 +76,7 @@ typedef struct BDRVQcowState {
     AES_KEY aes_decrypt_key;
 } BDRVQcowState;
 
-static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
+static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
 
 static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
@@ -90,16 +90,13 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
         return 0;
 }
 
-static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
+static int qcow_open(BlockDriverState *bs, int flags)
 {
     BDRVQcowState *s = bs->opaque;
-    int len, i, shift, ret;
+    int len, i, shift;
     QCowHeader header;
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (ret < 0)
-        return ret;
-    if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
+    if (bdrv_pread(bs->file, 0, &header, sizeof(header)) != sizeof(header))
         goto fail;
     be32_to_cpus(&header.magic);
     be32_to_cpus(&header.version);
@@ -135,7 +132,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
     if (!s->l1_table)
         goto fail;
-    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
+    if (bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
         s->l1_size * sizeof(uint64_t))
         goto fail;
     for(i = 0;i < s->l1_size; i++) {
@@ -158,7 +155,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
         len = header.backing_file_size;
         if (len > 1023)
             len = 1023;
-        if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
+        if (bdrv_pread(bs->file, header.backing_file_offset, bs->backing_file, len) != len)
             goto fail;
         bs->backing_file[len] = '\0';
     }
@@ -169,7 +166,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     qemu_free(s->l2_cache);
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
-    bdrv_delete(s->hd);
+    bdrv_delete(bs->file);
     return -1;
 }
 
@@ -271,13 +268,13 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
         if (!allocate)
             return 0;
         /* allocate a new l2 entry */
-        l2_offset = bdrv_getlength(s->hd);
+        l2_offset = bdrv_getlength(bs->file);
         /* round to cluster size */
         l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
         /* update the L1 entry */
         s->l1_table[l1_index] = l2_offset;
         tmp = cpu_to_be64(l2_offset);
-        if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
+        if (bdrv_pwrite(bs->file, s->l1_table_offset + l1_index * sizeof(tmp),
                         &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;
         new_l2_table = 1;
@@ -306,11 +303,11 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
     l2_table = s->l2_cache + (min_index << s->l2_bits);
     if (new_l2_table) {
         memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
-        if (bdrv_pwrite(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
+        if (bdrv_pwrite(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
             s->l2_size * sizeof(uint64_t))
             return 0;
     } else {
-        if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
+        if (bdrv_pread(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
             s->l2_size * sizeof(uint64_t))
             return 0;
     }
@@ -329,22 +326,22 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
             /* if the cluster is already compressed, we must
                decompress it in the case it is not completely
                overwritten */
-            if (decompress_cluster(s, cluster_offset) < 0)
+            if (decompress_cluster(bs, cluster_offset) < 0)
                 return 0;
-            cluster_offset = bdrv_getlength(s->hd);
+            cluster_offset = bdrv_getlength(bs->file);
             cluster_offset = (cluster_offset + s->cluster_size - 1) &
                 ~(s->cluster_size - 1);
             /* write the cluster content */
-            if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) !=
+            if (bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache, s->cluster_size) !=
                 s->cluster_size)
                 return -1;
         } else {
-            cluster_offset = bdrv_getlength(s->hd);
+            cluster_offset = bdrv_getlength(bs->file);
             if (allocate == 1) {
                 /* round to cluster size */
                 cluster_offset = (cluster_offset + s->cluster_size - 1) &
                     ~(s->cluster_size - 1);
-                bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
+                bdrv_truncate(bs->file, cluster_offset + s->cluster_size);
                 /* if encrypted, we must initialize the cluster
                    content which won't be written */
                 if (s->crypt_method &&
@@ -358,7 +355,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
                                             s->cluster_data,
                                             s->cluster_data + 512, 1, 1,
                                             &s->aes_encrypt_key);
-                            if (bdrv_pwrite(s->hd, cluster_offset + i * 512,
+                            if (bdrv_pwrite(bs->file, cluster_offset + i * 512,
                                             s->cluster_data, 512) != 512)
                                 return -1;
                         }
@@ -372,7 +369,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
         /* update L2 table */
         tmp = cpu_to_be64(cluster_offset);
         l2_table[l2_index] = tmp;
-        if (bdrv_pwrite(s->hd,
+        if (bdrv_pwrite(bs->file,
                         l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
             return 0;
     }
@@ -422,8 +419,9 @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
     return 0;
 }
 
-static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
+static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
 {
+    BDRVQcowState *s = bs->opaque;
     int ret, csize;
     uint64_t coffset;
 
@@ -431,7 +429,7 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
     if (s->cluster_cache_offset != coffset) {
         csize = cluster_offset >> (63 - s->cluster_bits);
         csize &= (s->cluster_size - 1);
-        ret = bdrv_pread(s->hd, coffset, s->cluster_data, csize);
+        ret = bdrv_pread(bs->file, coffset, s->cluster_data, csize);
         if (ret != csize)
             return -1;
         if (decompress_buffer(s->cluster_cache, s->cluster_size,
@@ -468,11 +466,11 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
                 memset(buf, 0, 512 * n);
             }
         } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
-            if (decompress_cluster(s, cluster_offset) < 0)
+            if (decompress_cluster(bs, cluster_offset) < 0)
                 return -1;
             memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
         } else {
-            ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
+            ret = bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512);
             if (ret != n * 512)
                 return -1;
             if (s->crypt_method) {
@@ -601,7 +599,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         }
     } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
-        if (decompress_cluster(s, acb->cluster_offset) < 0)
+        if (decompress_cluster(bs, acb->cluster_offset) < 0)
             goto done;
         memcpy(acb->buf,
                s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
@@ -614,7 +612,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = acb->n * 512;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_readv(s->hd,
+        acb->hd_aiocb = bdrv_aio_readv(bs->file,
                             (acb->cluster_offset >> 9) + index_in_cluster,
                             &acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
         if (acb->hd_aiocb == NULL)
@@ -699,7 +697,7 @@ static void qcow_aio_write_cb(void *opaque, int ret)
     acb->hd_iov.iov_base = (void *)src_buf;
     acb->hd_iov.iov_len = acb->n * 512;
     qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-    acb->hd_aiocb = bdrv_aio_writev(s->hd,
+    acb->hd_aiocb = bdrv_aio_writev(bs->file,
                                     (cluster_offset >> 9) + index_in_cluster,
                                     &acb->hd_qiov, acb->n,
                                     qcow_aio_write_cb, acb);
@@ -739,7 +737,7 @@ static void qcow_close(BlockDriverState *bs)
     qemu_free(s->l2_cache);
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
-    bdrv_delete(s->hd);
+    bdrv_delete(bs->file);
 }
 
 static int qcow_create(const char *filename, QEMUOptionParameter *options)
@@ -839,9 +837,9 @@ static int qcow_make_empty(BlockDriverState *bs)
     int ret;
 
     memset(s->l1_table, 0, l1_length);
-    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
+    if (bdrv_pwrite(bs->file, s->l1_table_offset, s->l1_table, l1_length) < 0)
 	return -1;
-    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
+    ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length);
     if (ret < 0)
         return ret;
 
@@ -902,7 +900,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
         cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
                                             out_len, 0, 0);
         cluster_offset &= s->cluster_offset_mask;
-        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
+        if (bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len) != out_len) {
             qemu_free(out_buf);
             return -1;
         }
@@ -914,16 +912,13 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
 
 static void qcow_flush(BlockDriverState *bs)
 {
-    BDRVQcowState *s = bs->opaque;
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
         BlockDriverCompletionFunc *cb, void *opaque)
 {
-    BDRVQcowState *s = bs->opaque;
-
-    return bdrv_aio_flush(s->hd, cb, opaque);
+    return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
 static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 639e05e..c11680d 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -54,27 +54,27 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
     memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
 
     /* write new table (align to cluster) */
-    BLKDBG_EVENT(s->hd, BLKDBG_L1_GROW_ALLOC_TABLE);
+    BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ALLOC_TABLE);
     new_l1_table_offset = qcow2_alloc_clusters(bs, new_l1_size2);
     if (new_l1_table_offset < 0) {
         qemu_free(new_l1_table);
         return new_l1_table_offset;
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L1_GROW_WRITE_TABLE);
+    BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);
     for(i = 0; i < s->l1_size; i++)
         new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
-    ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
+    ret = bdrv_pwrite(bs->file, new_l1_table_offset, new_l1_table, new_l1_size2);
     if (ret != new_l1_size2)
         goto fail;
     for(i = 0; i < s->l1_size; i++)
         new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
 
     /* set new table */
-    BLKDBG_EVENT(s->hd, BLKDBG_L1_GROW_ACTIVATE_TABLE);
+    BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE);
     cpu_to_be32w((uint32_t*)data, new_l1_size);
     cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
-    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, l1_size), data,sizeof(data));
     if (ret != sizeof(data)) {
         goto fail;
     }
@@ -174,8 +174,8 @@ static uint64_t *l2_load(BlockDriverState *bs, uint64_t l2_offset)
     min_index = l2_cache_new_entry(bs);
     l2_table = s->l2_cache + (min_index << s->l2_bits);
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L2_LOAD);
-    if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
+    BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
+    if (bdrv_pread(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
         s->l2_size * sizeof(uint64_t))
         return NULL;
     s->l2_cache_offsets[min_index] = l2_offset;
@@ -189,8 +189,9 @@ static uint64_t *l2_load(BlockDriverState *bs, uint64_t l2_offset)
  * and we really don't want bdrv_pread to perform a read-modify-write)
  */
 #define L1_ENTRIES_PER_SECTOR (512 / 8)
-static int write_l1_entry(BDRVQcowState *s, int l1_index)
+static int write_l1_entry(BlockDriverState *bs, int l1_index)
 {
+    BDRVQcowState *s = bs->opaque;
     uint64_t buf[L1_ENTRIES_PER_SECTOR];
     int l1_start_index;
     int i, ret;
@@ -200,8 +201,8 @@ static int write_l1_entry(BDRVQcowState *s, int l1_index)
         buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L1_UPDATE);
-    ret = bdrv_pwrite(s->hd, s->l1_table_offset + 8 * l1_start_index,
+    BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
+    ret = bdrv_pwrite(bs->file, s->l1_table_offset + 8 * l1_start_index,
         buf, sizeof(buf));
     if (ret < 0) {
         return ret;
@@ -241,7 +242,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
     /* update the L1 entry */
 
     s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
-    ret = write_l1_entry(s, l1_index);
+    ret = write_l1_entry(bs, l1_index);
     if (ret < 0) {
         return ret;
     }
@@ -256,16 +257,16 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
         memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
     } else {
         /* if there was an old l2 table, read it from the disk */
-        BLKDBG_EVENT(s->hd, BLKDBG_L2_ALLOC_COW_READ);
-        ret = bdrv_pread(s->hd, old_l2_offset, l2_table,
+        BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_COW_READ);
+        ret = bdrv_pread(bs->file, old_l2_offset, l2_table,
             s->l2_size * sizeof(uint64_t));
         if (ret < 0) {
             return ret;
         }
     }
     /* write the l2 table to the file */
-    BLKDBG_EVENT(s->hd, BLKDBG_L2_ALLOC_WRITE);
-    ret = bdrv_pwrite(s->hd, l2_offset, l2_table,
+    BLKDBG_EVENT(bs->file, BLKDBG_L2_ALLOC_WRITE);
+    ret = bdrv_pwrite(bs->file, l2_offset, l2_table,
         s->l2_size * sizeof(uint64_t));
     if (ret < 0) {
         return ret;
@@ -348,7 +349,7 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
                 /* read from the base image */
                 n1 = qcow2_backing_read1(bs->backing_hd, sector_num, buf, n);
                 if (n1 > 0) {
-                    BLKDBG_EVENT(s->hd, BLKDBG_READ_BACKING);
+                    BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING);
                     ret = bdrv_read(bs->backing_hd, sector_num, buf, n1);
                     if (ret < 0)
                         return -1;
@@ -357,12 +358,12 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
                 memset(buf, 0, 512 * n);
             }
         } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
-            if (qcow2_decompress_cluster(s, cluster_offset) < 0)
+            if (qcow2_decompress_cluster(bs, cluster_offset) < 0)
                 return -1;
             memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
         } else {
-            BLKDBG_EVENT(s->hd, BLKDBG_READ);
-            ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
+            BLKDBG_EVENT(bs->file, BLKDBG_READ);
+            ret = bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512);
             if (ret != n * 512)
                 return -1;
             if (s->crypt_method) {
@@ -386,7 +387,7 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
     n = n_end - n_start;
     if (n <= 0)
         return 0;
-    BLKDBG_EVENT(s->hd, BLKDBG_COW_READ);
+    BLKDBG_EVENT(bs->file, BLKDBG_COW_READ);
     ret = qcow_read(bs, start_sect + n_start, s->cluster_data, n);
     if (ret < 0)
         return ret;
@@ -396,8 +397,8 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
                         s->cluster_data, n, 1,
                         &s->aes_encrypt_key);
     }
-    BLKDBG_EVENT(s->hd, BLKDBG_COW_WRITE);
-    ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start,
+    BLKDBG_EVENT(bs->file, BLKDBG_COW_WRITE);
+    ret = bdrv_write(bs->file, (cluster_offset >> 9) + n_start,
                      s->cluster_data, n);
     if (ret < 0)
         return ret;
@@ -610,9 +611,9 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
 
     /* compressed clusters never have the copied flag */
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L2_UPDATE_COMPRESSED);
+    BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
     l2_table[l2_index] = cpu_to_be64(cluster_offset);
-    if (bdrv_pwrite(s->hd,
+    if (bdrv_pwrite(bs->file,
                     l2_offset + l2_index * sizeof(uint64_t),
                     l2_table + l2_index,
                     sizeof(uint64_t)) != sizeof(uint64_t))
@@ -626,7 +627,7 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
  * read-modify-write in bdrv_pwrite
  */
 #define L2_ENTRIES_PER_SECTOR (512 / 8)
-static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
+static int write_l2_entries(BlockDriverState *bs, uint64_t *l2_table,
     uint64_t l2_offset, int l2_index, int num)
 {
     int l2_start_index = l2_index & ~(L1_ENTRIES_PER_SECTOR - 1);
@@ -635,8 +636,8 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
     size_t len = end_offset - start_offset;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_L2_UPDATE);
-    ret = bdrv_pwrite(s->hd, l2_offset + start_offset,
+    BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
+    ret = bdrv_pwrite(bs->file, l2_offset + start_offset,
         &l2_table[l2_start_index], len);
     if (ret < 0) {
         return ret;
@@ -693,7 +694,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
                     (i << s->cluster_bits)) | QCOW_OFLAG_COPIED);
      }
 
-    ret = write_l2_entries(s, l2_table, l2_offset, l2_index, m->nb_clusters);
+    ret = write_l2_entries(bs, l2_table, l2_offset, l2_index, m->nb_clusters);
     if (ret < 0) {
         goto err;
     }
@@ -877,8 +878,9 @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
     return 0;
 }
 
-int qcow2_decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
+int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
 {
+    BDRVQcowState *s = bs->opaque;
     int ret, csize, nb_csectors, sector_offset;
     uint64_t coffset;
 
@@ -887,8 +889,8 @@ int qcow2_decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
         nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
         sector_offset = coffset & 511;
         csize = nb_csectors * 512 - sector_offset;
-        BLKDBG_EVENT(s->hd, BLKDBG_READ_COMPRESSED);
-        ret = bdrv_read(s->hd, coffset >> 9, s->cluster_data, nb_csectors);
+        BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
+        ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data, nb_csectors);
         if (ret < 0) {
             return -1;
         }
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 47c9978..2661493 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -34,16 +34,17 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
 
 static int cache_refcount_updates = 0;
 
-static int write_refcount_block(BDRVQcowState *s)
+static int write_refcount_block(BlockDriverState *bs)
 {
+    BDRVQcowState *s = bs->opaque;
     size_t size = s->cluster_size;
 
     if (s->refcount_block_cache_offset == 0) {
         return 0;
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_UPDATE);
-    if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE);
+    if (bdrv_pwrite(bs->file, s->refcount_block_cache_offset,
             s->refcount_block_cache, size) != size)
     {
         return -EIO;
@@ -64,8 +65,8 @@ int qcow2_refcount_init(BlockDriverState *bs)
     refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
     s->refcount_table = qemu_malloc(refcount_table_size2);
     if (s->refcount_table_size > 0) {
-        BLKDBG_EVENT(s->hd, BLKDBG_REFTABLE_LOAD);
-        ret = bdrv_pread(s->hd, s->refcount_table_offset,
+        BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
+        ret = bdrv_pread(bs->file, s->refcount_table_offset,
                          s->refcount_table, refcount_table_size2);
         if (ret != refcount_table_size2)
             goto fail;
@@ -92,11 +93,11 @@ static int load_refcount_block(BlockDriverState *bs,
     int ret;
 
     if (cache_refcount_updates) {
-        write_refcount_block(s);
+        write_refcount_block(bs);
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_LOAD);
-    ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_LOAD);
+    ret = bdrv_pread(bs->file, refcount_block_offset, s->refcount_block_cache,
                      s->cluster_size);
     if (ret != s->cluster_size)
         return -EIO;
@@ -167,7 +168,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     unsigned int refcount_table_index;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC);
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC);
 
     /* Find the refcount block for the given cluster */
     refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
@@ -212,7 +213,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
      */
 
     if (cache_refcount_updates) {
-        ret = write_refcount_block(s);
+        ret = write_refcount_block(bs);
         if (ret < 0) {
             return ret;
         }
@@ -244,8 +245,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     }
 
     /* Now the new refcount block needs to be written to disk */
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_WRITE);
-    ret = bdrv_pwrite(s->hd, new_block, s->refcount_block_cache,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE);
+    ret = bdrv_pwrite(bs->file, new_block, s->refcount_block_cache,
         s->cluster_size);
     if (ret < 0) {
         goto fail_block;
@@ -254,8 +255,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     /* If the refcount table is big enough, just hook the block up there */
     if (refcount_table_index < s->refcount_table_size) {
         uint64_t data64 = cpu_to_be64(new_block);
-        BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_HOOKUP);
-        ret = bdrv_pwrite(s->hd,
+        BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP);
+        ret = bdrv_pwrite(bs->file,
             s->refcount_table_offset + refcount_table_index * sizeof(uint64_t),
             &data64, sizeof(data64));
         if (ret < 0) {
@@ -277,7 +278,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
      * refcount table at once without producing an inconsistent state in
      * between.
      */
-    BLKDBG_EVENT(s->hd, BLKDBG_REFTABLE_GROW);
+    BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_GROW);
 
     /* Calculate the number of refcount blocks needed so far */
     uint64_t refcount_block_clusters = 1 << (s->cluster_bits - REFCOUNT_SHIFT);
@@ -334,8 +335,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     }
 
     /* Write refcount blocks to disk */
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS);
-    ret = bdrv_pwrite(s->hd, meta_offset, new_blocks,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS);
+    ret = bdrv_pwrite(bs->file, meta_offset, new_blocks,
         blocks_clusters * s->cluster_size);
     qemu_free(new_blocks);
     if (ret < 0) {
@@ -347,8 +348,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
         cpu_to_be64s(&new_table[i]);
     }
 
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE);
-    ret = bdrv_pwrite(s->hd, table_offset, new_table,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE);
+    ret = bdrv_pwrite(bs->file, table_offset, new_table,
         table_size * sizeof(uint64_t));
     if (ret < 0) {
         goto fail_table;
@@ -362,8 +363,8 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
     uint8_t data[12];
     cpu_to_be64w((uint64_t*)data, table_offset);
     cpu_to_be32w((uint32_t*)(data + 8), table_clusters);
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE);
-    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE);
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, refcount_table_offset),
         data, sizeof(data));
     if (ret < 0) {
         goto fail_table;
@@ -398,9 +399,10 @@ fail_block:
 }
 
 #define REFCOUNTS_PER_SECTOR (512 >> REFCOUNT_SHIFT)
-static int write_refcount_block_entries(BDRVQcowState *s,
+static int write_refcount_block_entries(BlockDriverState *bs,
     int64_t refcount_block_offset, int first_index, int last_index)
 {
+    BDRVQcowState *s = bs->opaque;
     size_t size;
 
     if (cache_refcount_updates) {
@@ -412,8 +414,8 @@ static int write_refcount_block_entries(BDRVQcowState *s,
         & ~(REFCOUNTS_PER_SECTOR - 1);
 
     size = (last_index - first_index) << REFCOUNT_SHIFT;
-    BLKDBG_EVENT(s->hd, BLKDBG_REFBLOCK_UPDATE_PART);
-    if (bdrv_pwrite(s->hd,
+    BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
+    if (bdrv_pwrite(bs->file,
         refcount_block_offset + (first_index << REFCOUNT_SHIFT),
         &s->refcount_block_cache[first_index], size) != size)
     {
@@ -458,7 +460,7 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
         table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
         if ((old_table_index >= 0) && (table_index != old_table_index)) {
 
-            if (write_refcount_block_entries(s, refcount_block_offset,
+            if (write_refcount_block_entries(bs, refcount_block_offset,
                 first_index, last_index) < 0)
             {
                 return -EIO;
@@ -503,7 +505,7 @@ fail:
 
     /* Write last changed block to disk */
     if (refcount_block_offset != 0) {
-        if (write_refcount_block_entries(s, refcount_block_offset,
+        if (write_refcount_block_entries(bs, refcount_block_offset,
             first_index, last_index) < 0)
         {
             return ret < 0 ? ret : -EIO;
@@ -568,11 +570,10 @@ retry:
 
 int64_t qcow2_alloc_clusters(BlockDriverState *bs, int64_t size)
 {
-    BDRVQcowState *s = bs->opaque;
     int64_t offset;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_CLUSTER_ALLOC);
+    BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
     offset = alloc_clusters_noref(bs, size);
     ret = update_refcount(bs, offset, size, 1);
     if (ret < 0) {
@@ -589,7 +590,7 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
     int64_t offset, cluster_offset;
     int free_in_cluster;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_CLUSTER_ALLOC_BYTES);
+    BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_BYTES);
     assert(size > 0 && size <= s->cluster_size);
     if (s->free_byte_offset == 0) {
         s->free_byte_offset = qcow2_alloc_clusters(bs, s->cluster_size);
@@ -631,10 +632,9 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
 void qcow2_free_clusters(BlockDriverState *bs,
                           int64_t offset, int64_t size)
 {
-    BDRVQcowState *s = bs->opaque;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_CLUSTER_FREE);
+    BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_FREE);
     ret = update_refcount(bs, offset, size, -1);
     if (ret < 0) {
         fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret));
@@ -718,7 +718,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
             l1_table = NULL;
         }
         l1_allocated = 1;
-        if (bdrv_pread(s->hd, l1_table_offset,
+        if (bdrv_pread(bs->file, l1_table_offset,
                        l1_table, l1_size2) != l1_size2)
             goto fail;
         for(i = 0;i < l1_size; i++)
@@ -738,7 +738,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
             old_l2_offset = l2_offset;
             l2_offset &= ~QCOW_OFLAG_COPIED;
             l2_modified = 0;
-            if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
+            if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size)
                 goto fail;
             for(j = 0; j < s->l2_size; j++) {
                 offset = be64_to_cpu(l2_table[j]);
@@ -777,7 +777,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
                 }
             }
             if (l2_modified) {
-                if (bdrv_pwrite(s->hd,
+                if (bdrv_pwrite(bs->file,
                                 l2_offset, l2_table, l2_size) != l2_size)
                     goto fail;
             }
@@ -799,7 +799,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
     if (l1_modified) {
         for(i = 0; i < l1_size; i++)
             cpu_to_be64s(&l1_table[i]);
-        if (bdrv_pwrite(s->hd, l1_table_offset, l1_table,
+        if (bdrv_pwrite(bs->file, l1_table_offset, l1_table,
                         l1_size2) != l1_size2)
             goto fail;
         for(i = 0; i < l1_size; i++)
@@ -809,14 +809,14 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
         qemu_free(l1_table);
     qemu_free(l2_table);
     cache_refcount_updates = 0;
-    write_refcount_block(s);
+    write_refcount_block(bs);
     return 0;
  fail:
     if (l1_allocated)
         qemu_free(l1_table);
     qemu_free(l2_table);
     cache_refcount_updates = 0;
-    write_refcount_block(s);
+    write_refcount_block(bs);
     return -EIO;
 }
 
@@ -890,7 +890,7 @@ static int check_refcounts_l2(BlockDriverState *bs,
     l2_size = s->l2_size * sizeof(uint64_t);
     l2_table = qemu_malloc(l2_size);
 
-    if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
+    if (bdrv_pread(bs->file, l2_offset, l2_table, l2_size) != l2_size)
         goto fail;
 
     /* Do the actual checks */
@@ -982,7 +982,7 @@ static int check_refcounts_l1(BlockDriverState *bs,
         l1_table = NULL;
     } else {
         l1_table = qemu_malloc(l1_size2);
-        if (bdrv_pread(s->hd, l1_table_offset,
+        if (bdrv_pread(bs->file, l1_table_offset,
                        l1_table, l1_size2) != l1_size2)
             goto fail;
         for(i = 0;i < l1_size; i++)
@@ -1051,7 +1051,7 @@ int qcow2_check_refcounts(BlockDriverState *bs)
     uint16_t *refcount_table;
     int ret, errors = 0;
 
-    size = bdrv_getlength(s->hd);
+    size = bdrv_getlength(bs->file);
     nb_clusters = size_to_clusters(s, size);
     refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t));
 
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 8ddaea2..2a21c17 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -79,7 +79,7 @@ int qcow2_read_snapshots(BlockDriverState *bs)
     s->snapshots = qemu_mallocz(s->nb_snapshots * sizeof(QCowSnapshot));
     for(i = 0; i < s->nb_snapshots; i++) {
         offset = align_offset(offset, 8);
-        if (bdrv_pread(s->hd, offset, &h, sizeof(h)) != sizeof(h))
+        if (bdrv_pread(bs->file, offset, &h, sizeof(h)) != sizeof(h))
             goto fail;
         offset += sizeof(h);
         sn = s->snapshots + i;
@@ -97,13 +97,13 @@ int qcow2_read_snapshots(BlockDriverState *bs)
         offset += extra_data_size;
 
         sn->id_str = qemu_malloc(id_str_size + 1);
-        if (bdrv_pread(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
+        if (bdrv_pread(bs->file, offset, sn->id_str, id_str_size) != id_str_size)
             goto fail;
         offset += id_str_size;
         sn->id_str[id_str_size] = '\0';
 
         sn->name = qemu_malloc(name_size + 1);
-        if (bdrv_pread(s->hd, offset, sn->name, name_size) != name_size)
+        if (bdrv_pread(bs->file, offset, sn->name, name_size) != name_size)
             goto fail;
         offset += name_size;
         sn->name[name_size] = '\0';
@@ -158,24 +158,24 @@ static int qcow_write_snapshots(BlockDriverState *bs)
         h.id_str_size = cpu_to_be16(id_str_size);
         h.name_size = cpu_to_be16(name_size);
         offset = align_offset(offset, 8);
-        if (bdrv_pwrite(s->hd, offset, &h, sizeof(h)) != sizeof(h))
+        if (bdrv_pwrite(bs->file, offset, &h, sizeof(h)) != sizeof(h))
             goto fail;
         offset += sizeof(h);
-        if (bdrv_pwrite(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
+        if (bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size) != id_str_size)
             goto fail;
         offset += id_str_size;
-        if (bdrv_pwrite(s->hd, offset, sn->name, name_size) != name_size)
+        if (bdrv_pwrite(bs->file, offset, sn->name, name_size) != name_size)
             goto fail;
         offset += name_size;
     }
 
     /* update the various header fields */
     data64 = cpu_to_be64(snapshots_offset);
-    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, snapshots_offset),
+    if (bdrv_pwrite(bs->file, offsetof(QCowHeader, snapshots_offset),
                     &data64, sizeof(data64)) != sizeof(data64))
         goto fail;
     data32 = cpu_to_be32(s->nb_snapshots);
-    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, nb_snapshots),
+    if (bdrv_pwrite(bs->file, offsetof(QCowHeader, nb_snapshots),
                     &data32, sizeof(data32)) != sizeof(data32))
         goto fail;
 
@@ -284,7 +284,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     for(i = 0; i < s->l1_size; i++) {
         l1_table[i] = cpu_to_be64(s->l1_table[i]);
     }
-    if (bdrv_pwrite(s->hd, sn->l1_table_offset,
+    if (bdrv_pwrite(bs->file, sn->l1_table_offset,
                     l1_table, s->l1_size * sizeof(uint64_t)) !=
         (s->l1_size * sizeof(uint64_t)))
         goto fail;
@@ -332,10 +332,10 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     s->l1_size = sn->l1_size;
     l1_size2 = s->l1_size * sizeof(uint64_t);
     /* copy the snapshot l1 table to the current l1 table */
-    if (bdrv_pread(s->hd, sn->l1_table_offset,
+    if (bdrv_pread(bs->file, sn->l1_table_offset,
                    s->l1_table, l1_size2) != l1_size2)
         goto fail;
-    if (bdrv_pwrite(s->hd, s->l1_table_offset,
+    if (bdrv_pwrite(bs->file, s->l1_table_offset,
                     s->l1_table, l1_size2) != l1_size2)
         goto fail;
     for(i = 0;i < s->l1_size; i++) {
diff --git a/block/qcow2.c b/block/qcow2.c
index 11ce8d1..4949d77 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -77,7 +77,6 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
 static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
                                 uint64_t end_offset)
 {
-    BDRVQcowState *s = bs->opaque;
     QCowExtension ext;
     uint64_t offset;
 
@@ -95,7 +94,7 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
         printf("attemting to read extended header in offset %lu\n", offset);
 #endif
 
-        if (bdrv_pread(s->hd, offset, &ext, sizeof(ext)) != sizeof(ext)) {
+        if (bdrv_pread(bs->file, offset, &ext, sizeof(ext)) != sizeof(ext)) {
             fprintf(stderr, "qcow_handle_extension: ERROR: pread fail from offset %llu\n",
                     (unsigned long long)offset);
             return 1;
@@ -117,7 +116,7 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
                         ext.len, sizeof(bs->backing_format));
                 return 2;
             }
-            if (bdrv_pread(s->hd, offset , bs->backing_format,
+            if (bdrv_pread(bs->file, offset , bs->backing_format,
                            ext.len) != ext.len)
                 return 3;
             bs->backing_format[ext.len] = '\0';
@@ -138,17 +137,14 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
 }
 
 
-static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
+static int qcow_open(BlockDriverState *bs, int flags)
 {
     BDRVQcowState *s = bs->opaque;
-    int len, i, shift, ret;
+    int len, i, shift;
     QCowHeader header;
     uint64_t ext_end;
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (ret < 0)
-        return ret;
-    if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
+    if (bdrv_pread(bs->file, 0, &header, sizeof(header)) != sizeof(header))
         goto fail;
     be32_to_cpus(&header.magic);
     be32_to_cpus(&header.version);
@@ -202,7 +198,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     if (s->l1_size > 0) {
         s->l1_table = qemu_mallocz(
             align_offset(s->l1_size * sizeof(uint64_t), 512));
-        if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
+        if (bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
             s->l1_size * sizeof(uint64_t))
             goto fail;
         for(i = 0;i < s->l1_size; i++) {
@@ -235,7 +231,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
         len = header.backing_file_size;
         if (len > 1023)
             len = 1023;
-        if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
+        if (bdrv_pread(bs->file, header.backing_file_offset, bs->backing_file, len) != len)
             goto fail;
         bs->backing_file[len] = '\0';
     }
@@ -254,7 +250,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
     qemu_free(s->l2_cache);
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
-    bdrv_delete(s->hd);
+    bdrv_delete(bs->file);
     return -1;
 }
 
@@ -429,7 +425,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
                 acb->hd_iov.iov_base = (void *)acb->buf;
                 acb->hd_iov.iov_len = acb->cur_nr_sectors * 512;
                 qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-                BLKDBG_EVENT(s->hd, BLKDBG_READ_BACKING_AIO);
+                BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
                 acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
                                     &acb->hd_qiov, acb->cur_nr_sectors,
 				    qcow_aio_read_cb, acb);
@@ -449,7 +445,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         }
     } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
         /* add AIO support for compressed blocks ? */
-        if (qcow2_decompress_cluster(s, acb->cluster_offset) < 0)
+        if (qcow2_decompress_cluster(bs, acb->cluster_offset) < 0)
             goto done;
         memcpy(acb->buf, s->cluster_cache + index_in_cluster * 512,
                512 * acb->cur_nr_sectors);
@@ -465,8 +461,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = acb->cur_nr_sectors * 512;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        BLKDBG_EVENT(s->hd, BLKDBG_READ_AIO);
-        acb->hd_aiocb = bdrv_aio_readv(s->hd,
+        BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
+        acb->hd_aiocb = bdrv_aio_readv(bs->file,
                             (acb->cluster_offset >> 9) + index_in_cluster,
                             &acb->hd_qiov, acb->cur_nr_sectors,
                             qcow_aio_read_cb, acb);
@@ -621,8 +617,8 @@ static void qcow_aio_write_cb(void *opaque, int ret)
     acb->hd_iov.iov_base = (void *)src_buf;
     acb->hd_iov.iov_len = acb->cur_nr_sectors * 512;
     qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-    BLKDBG_EVENT(s->hd, BLKDBG_WRITE_AIO);
-    acb->hd_aiocb = bdrv_aio_writev(s->hd,
+    BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
+    acb->hd_aiocb = bdrv_aio_writev(bs->file,
                                     (acb->cluster_offset >> 9) + index_in_cluster,
                                     &acb->hd_qiov, acb->cur_nr_sectors,
                                     qcow_aio_write_cb, acb);
@@ -669,7 +665,6 @@ static void qcow_close(BlockDriverState *bs)
     qemu_free(s->cluster_cache);
     qemu_free(s->cluster_data);
     qcow2_refcount_close(bs);
-    bdrv_delete(s->hd);
 }
 
 /*
@@ -739,7 +734,7 @@ static int qcow2_update_ext_header(BlockDriverState *bs,
         backing_file_offset = sizeof(QCowHeader) + offset;
     }
 
-    ret = bdrv_pwrite(s->hd, sizeof(QCowHeader), buf, ext_size);
+    ret = bdrv_pwrite(bs->file, sizeof(QCowHeader), buf, ext_size);
     if (ret < 0) {
         goto fail;
     }
@@ -748,13 +743,13 @@ static int qcow2_update_ext_header(BlockDriverState *bs,
     uint64_t be_backing_file_offset = cpu_to_be64(backing_file_offset);
     uint32_t be_backing_file_size = cpu_to_be32(backing_file_len);
 
-    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, backing_file_offset),
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, backing_file_offset),
         &be_backing_file_offset, sizeof(uint64_t));
     if (ret < 0) {
         goto fail;
     }
 
-    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, backing_file_size),
+    ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, backing_file_size),
         &be_backing_file_size, sizeof(uint32_t));
     if (ret < 0) {
         goto fail;
@@ -795,7 +790,6 @@ static int get_bits_from_size(size_t size)
 
 static int preallocate(BlockDriverState *bs)
 {
-    BDRVQcowState *s = bs->opaque;
     uint64_t nb_sectors;
     uint64_t offset;
     int num;
@@ -838,7 +832,7 @@ static int preallocate(BlockDriverState *bs)
     if (meta.cluster_offset != 0) {
         uint8_t buf[512];
         memset(buf, 0, 512);
-        bdrv_write(s->hd, (meta.cluster_offset >> 9) + num - 1, buf, 1);
+        bdrv_write(bs->file, (meta.cluster_offset >> 9) + num - 1, buf, 1);
     }
 
     return 0;
@@ -1095,9 +1089,9 @@ static int qcow_make_empty(BlockDriverState *bs)
     int ret;
 
     memset(s->l1_table, 0, l1_length);
-    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
+    if (bdrv_pwrite(bs->file, s->l1_table_offset, s->l1_table, l1_length) < 0)
         return -1;
-    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
+    ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length);
     if (ret < 0)
         return ret;
 
@@ -1120,9 +1114,9 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
     if (nb_sectors == 0) {
         /* align end of file to a sector boundary to ease reading with
            sector based I/Os */
-        cluster_offset = bdrv_getlength(s->hd);
+        cluster_offset = bdrv_getlength(bs->file);
         cluster_offset = (cluster_offset + 511) & ~511;
-        bdrv_truncate(s->hd, cluster_offset);
+        bdrv_truncate(bs->file, cluster_offset);
         return 0;
     }
 
@@ -1165,8 +1159,8 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
         if (!cluster_offset)
             return -1;
         cluster_offset &= s->cluster_offset_mask;
-        BLKDBG_EVENT(s->hd, BLKDBG_WRITE_COMPRESSED);
-        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
+        BLKDBG_EVENT(bs->file, BLKDBG_WRITE_COMPRESSED);
+        if (bdrv_pwrite(bs->file, cluster_offset, out_buf, out_len) != out_len) {
             qemu_free(out_buf);
             return -1;
         }
@@ -1178,16 +1172,13 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
 
 static void qcow_flush(BlockDriverState *bs)
 {
-    BDRVQcowState *s = bs->opaque;
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 static BlockDriverAIOCB *qcow_aio_flush(BlockDriverState *bs,
          BlockDriverCompletionFunc *cb, void *opaque)
 {
-     BDRVQcowState *s = bs->opaque;
-
-     return bdrv_aio_flush(s->hd, cb, opaque);
+    return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
 static int64_t qcow_vm_state_offset(BDRVQcowState *s)
@@ -1216,7 +1207,7 @@ static void dump_refcounts(BlockDriverState *bs)
     int64_t nb_clusters, k, k1, size;
     int refcount;
 
-    size = bdrv_getlength(s->hd);
+    size = bdrv_getlength(bs->file);
     nb_clusters = size_to_clusters(s, size);
     for(k = 0; k < nb_clusters;) {
         k1 = k;
@@ -1236,7 +1227,7 @@ static int qcow_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
     int growable = bs->growable;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_SAVE);
+    BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_SAVE);
     bs->growable = 1;
     ret = bdrv_pwrite(bs, qcow_vm_state_offset(s) + pos, buf, size);
     bs->growable = growable;
@@ -1251,7 +1242,7 @@ static int qcow_load_vmstate(BlockDriverState *bs, uint8_t *buf,
     int growable = bs->growable;
     int ret;
 
-    BLKDBG_EVENT(s->hd, BLKDBG_VMSTATE_LOAD);
+    BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_LOAD);
     bs->growable = 1;
     ret = bdrv_pread(bs, qcow_vm_state_offset(s) + pos, buf, size);
     bs->growable = growable;
diff --git a/block/qcow2.h b/block/qcow2.h
index de9397a..5bd08db 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -184,7 +184,7 @@ int qcow2_check_refcounts(BlockDriverState *bs);
 /* qcow2-cluster.c functions */
 int qcow2_grow_l1_table(BlockDriverState *bs, int min_size);
 void qcow2_l2_cache_reset(BlockDriverState *bs);
-int qcow2_decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
+int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
 void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
                      uint8_t *out_buf, const uint8_t *in_buf,
                      int nb_sectors, int enc,
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 8f57ab0..598ea19 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -773,7 +773,7 @@ static BlockDriver bdrv_file = {
     .protocol_name = "file",
     .instance_size = sizeof(BDRVRawState),
     .bdrv_probe = NULL, /* no probe for protocols */
-    .bdrv_open = raw_open,
+    .bdrv_file_open = raw_open,
     .bdrv_read = raw_read,
     .bdrv_write = raw_write,
     .bdrv_close = raw_close,
@@ -1030,7 +1030,7 @@ static BlockDriver bdrv_host_device = {
     .protocol_name        = "host_device",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device  = hdev_probe_device,
-    .bdrv_open          = hdev_open,
+    .bdrv_file_open     = hdev_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
@@ -1145,7 +1145,7 @@ static BlockDriver bdrv_host_floppy = {
     .protocol_name      = "host_floppy",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= floppy_probe_device,
-    .bdrv_open          = floppy_open,
+    .bdrv_file_open     = floppy_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
@@ -1245,7 +1245,7 @@ static BlockDriver bdrv_host_cdrom = {
     .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= cdrom_probe_device,
-    .bdrv_open          = cdrom_open,
+    .bdrv_file_open     = cdrom_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
@@ -1368,7 +1368,7 @@ static BlockDriver bdrv_host_cdrom = {
     .protocol_name      = "host_cdrom",
     .instance_size      = sizeof(BDRVRawState),
     .bdrv_probe_device	= cdrom_probe_device,
-    .bdrv_open          = cdrom_open,
+    .bdrv_file_open     = cdrom_open,
     .bdrv_close         = raw_close,
     .bdrv_create        = hdev_create,
     .create_options     = raw_create_options,
diff --git a/block/raw-win32.c b/block/raw-win32.c
index eadebeb..745bbde 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -242,7 +242,7 @@ static BlockDriver bdrv_file = {
     .format_name	= "file",
     .protocol_name	= "file",
     .instance_size	= sizeof(BDRVRawState),
-    .bdrv_open		= raw_open,
+    .bdrv_file_open	= raw_open,
     .bdrv_close		= raw_close,
     .bdrv_create	= raw_create,
     .bdrv_flush		= raw_flush,
@@ -399,7 +399,7 @@ static BlockDriver bdrv_host_device = {
     .protocol_name	= "host_device",
     .instance_size	= sizeof(BDRVRawState),
     .bdrv_probe_device	= hdev_probe_device,
-    .bdrv_open		= hdev_open,
+    .bdrv_file_open	= hdev_open,
     .bdrv_close		= raw_close,
     .bdrv_flush		= raw_flush,
 
diff --git a/block/raw.c b/block/raw.c
index 953e285..4406b8c 100644
--- a/block/raw.c
+++ b/block/raw.c
@@ -3,84 +3,61 @@
 #include "block_int.h"
 #include "module.h"
 
-typedef struct RAWState {
-    BlockDriverState *hd;
-} RAWState;
-
-static int raw_open(BlockDriverState *bs, const char *filename, int flags)
+static int raw_open(BlockDriverState *bs, int flags)
 {
-    RAWState *s = bs->opaque;
-    int ret;
-
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (!ret) {
-        bs->sg = s->hd->sg;
-    }
-
-    return ret;
+    bs->sg = bs->file->sg;
+    return 0;
 }
 
 static int raw_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_read(s->hd, sector_num, buf, nb_sectors);
+    return bdrv_read(bs->file, sector_num, buf, nb_sectors);
 }
 
 static int raw_write(BlockDriverState *bs, int64_t sector_num,
                      const uint8_t *buf, int nb_sectors)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_write(s->hd, sector_num, buf, nb_sectors);
+    return bdrv_write(bs->file, sector_num, buf, nb_sectors);
 }
 
 static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
     int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
-    RAWState *s = bs->opaque;
-
-    return bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+    return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
 }
 
 static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
     int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
-    RAWState *s = bs->opaque;
-
-    return bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
+    return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
 }
 
 static void raw_close(BlockDriverState *bs)
 {
-    RAWState *s = bs->opaque;
-    bdrv_delete(s->hd);
 }
 
 static void raw_flush(BlockDriverState *bs)
 {
-    RAWState *s = bs->opaque;
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_aio_flush(s->hd, cb, opaque);
+    return bdrv_aio_flush(bs->file, cb, opaque);
 }
 
 static int64_t raw_getlength(BlockDriverState *bs)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_getlength(s->hd);
+    return bdrv_getlength(bs->file);
 }
 
 static int raw_truncate(BlockDriverState *bs, int64_t offset)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_truncate(s->hd, offset);
+    return bdrv_truncate(bs->file, offset);
 }
 
 static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
@@ -90,35 +67,30 @@ static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
 
 static int raw_is_inserted(BlockDriverState *bs)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_is_inserted(s->hd);
+    return bdrv_is_inserted(bs->file);
 }
 
 static int raw_eject(BlockDriverState *bs, int eject_flag)
 {
-    RAWState *s = bs->opaque;
-    return bdrv_eject(s->hd, eject_flag);
+    return bdrv_eject(bs->file, eject_flag);
 }
 
 static int raw_set_locked(BlockDriverState *bs, int locked)
 {
-    RAWState *s = bs->opaque;
-    bdrv_set_locked(s->hd, locked);
+    bdrv_set_locked(bs->file, locked);
     return 0;
 }
 
 static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
 {
-   RAWState *s = bs->opaque;
-   return bdrv_ioctl(s->hd, req, 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)
 {
-   RAWState *s = bs->opaque;
-   return bdrv_aio_ioctl(s->hd, req, buf, cb, opaque);
+   return bdrv_aio_ioctl(bs->file, req, buf, cb, opaque);
 }
 
 static int raw_create(const char *filename, QEMUOptionParameter *options)
@@ -138,7 +110,8 @@ static QEMUOptionParameter raw_create_options[] = {
 static BlockDriver bdrv_raw = {
     .format_name        = "raw",
 
-    .instance_size      = sizeof(RAWState),
+    /* It's really 0, but we need to make qemu_malloc() happy */
+    .instance_size      = 1,
 
     .bdrv_open          = raw_open,
     .bdrv_close         = raw_close,
diff --git a/block/vdi.c b/block/vdi.c
index c91961a..8b85339 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -376,21 +376,15 @@ static int vdi_probe(const uint8_t *buf, int buf_size, const char *filename)
     return result;
 }
 
-static int vdi_open(BlockDriverState *bs, const char *filename, int flags)
+static int vdi_open(BlockDriverState *bs, int flags)
 {
     BDRVVdiState *s = bs->opaque;
     VdiHeader header;
     size_t bmap_size;
-    int ret;
 
     logout("\n");
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (ret < 0) {
-        return ret;
-    }
-
-    if (bdrv_read(s->hd, 0, (uint8_t *)&header, 1) < 0) {
+    if (bdrv_read(bs->file, 0, (uint8_t *)&header, 1) < 0) {
         goto fail;
     }
 
@@ -442,7 +436,7 @@ static int vdi_open(BlockDriverState *bs, const char *filename, int flags)
     bmap_size = header.blocks_in_image * sizeof(uint32_t);
     bmap_size = (bmap_size + SECTOR_SIZE - 1) / SECTOR_SIZE;
     s->bmap = qemu_malloc(bmap_size * SECTOR_SIZE);
-    if (bdrv_read(s->hd, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
+    if (bdrv_read(bs->file, s->bmap_sector, (uint8_t *)s->bmap, bmap_size) < 0) {
         goto fail_free_bmap;
     }
 
@@ -452,7 +446,7 @@ static int vdi_open(BlockDriverState *bs, const char *filename, int flags)
     qemu_free(s->bmap);
 
  fail:
-    bdrv_delete(s->hd);
+    bdrv_delete(bs->file);
     return -1;
 }
 
@@ -607,7 +601,7 @@ static void vdi_aio_read_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_readv(s->hd, offset, &acb->hd_qiov,
+        acb->hd_aiocb = bdrv_aio_readv(bs->file, offset, &acb->hd_qiov,
                                        n_sectors, vdi_aio_read_cb, acb);
         if (acb->hd_aiocb == NULL) {
             goto done;
@@ -670,7 +664,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
             acb->hd_iov.iov_base = acb->block_buffer;
             acb->hd_iov.iov_len = SECTOR_SIZE;
             qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-            acb->hd_aiocb = bdrv_aio_writev(s->hd, 0, &acb->hd_qiov, 1,
+            acb->hd_aiocb = bdrv_aio_writev(bs->file, 0, &acb->hd_qiov, 1,
                                             vdi_aio_write_cb, acb);
             if (acb->hd_aiocb == NULL) {
                 goto done;
@@ -699,7 +693,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
             qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
             logout("will write %u block map sectors starting from entry %u\n",
                    n_sectors, bmap_first);
-            acb->hd_aiocb = bdrv_aio_writev(s->hd, offset, &acb->hd_qiov,
+            acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
                                             n_sectors, vdi_aio_write_cb, acb);
             if (acb->hd_aiocb == NULL) {
                 goto done;
@@ -748,7 +742,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)block;
         acb->hd_iov.iov_len = s->block_size;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_writev(s->hd, offset,
+        acb->hd_aiocb = bdrv_aio_writev(bs->file, offset,
                                         &acb->hd_qiov, s->block_sectors,
                                         vdi_aio_write_cb, acb);
         if (acb->hd_aiocb == NULL) {
@@ -761,7 +755,7 @@ static void vdi_aio_write_cb(void *opaque, int ret)
         acb->hd_iov.iov_base = (void *)acb->buf;
         acb->hd_iov.iov_len = n_sectors * SECTOR_SIZE;
         qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
-        acb->hd_aiocb = bdrv_aio_writev(s->hd, offset, &acb->hd_qiov,
+        acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
                                         n_sectors, vdi_aio_write_cb, acb);
         if (acb->hd_aiocb == NULL) {
             goto done;
@@ -891,16 +885,12 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
 
 static void vdi_close(BlockDriverState *bs)
 {
-    BDRVVdiState *s = bs->opaque;
-    logout("\n");
-    bdrv_delete(s->hd);
 }
 
 static void vdi_flush(BlockDriverState *bs)
 {
-    BDRVVdiState *s = bs->opaque;
     logout("\n");
-    bdrv_flush(s->hd);
+    bdrv_flush(bs->file);
 }
 
 
diff --git a/block/vmdk.c b/block/vmdk.c
index 6fdea1d..5ef4375 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -914,7 +914,7 @@ static BlockDriver bdrv_vmdk = {
     .format_name	= "vmdk",
     .instance_size	= sizeof(BDRVVmdkState),
     .bdrv_probe		= vmdk_probe,
-    .bdrv_open		= vmdk_open,
+    .bdrv_file_open	= vmdk_open,
     .bdrv_read		= vmdk_read,
     .bdrv_write		= vmdk_write,
     .bdrv_close		= vmdk_close,
diff --git a/block/vpc.c b/block/vpc.c
index 950ad58..1d1ae09 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -150,20 +150,16 @@ static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
     return 0;
 }
 
-static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
+static int vpc_open(BlockDriverState *bs, int flags)
 {
     BDRVVPCState *s = bs->opaque;
-    int ret, i;
+    int i;
     struct vhd_footer* footer;
     struct vhd_dyndisk_header* dyndisk_header;
     uint8_t buf[HEADER_SIZE];
     uint32_t checksum;
 
-    ret = bdrv_file_open(&s->hd, filename, flags);
-    if (ret < 0)
-        return ret;
-
-    if (bdrv_pread(s->hd, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE)
+    if (bdrv_pread(bs->file, 0, s->footer_buf, HEADER_SIZE) != HEADER_SIZE)
         goto fail;
 
     footer = (struct vhd_footer*) s->footer_buf;
@@ -174,7 +170,7 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
     footer->checksum = 0;
     if (vpc_checksum(s->footer_buf, HEADER_SIZE) != checksum)
         fprintf(stderr, "block-vpc: The header checksum of '%s' is "
-            "incorrect.\n", filename);
+            "incorrect.\n", bs->filename);
 
     // The visible size of a image in Virtual PC depends on the geometry
     // rather than on the size stored in the footer (the size in the footer
@@ -182,7 +178,7 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
     bs->total_sectors = (int64_t)
         be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl;
 
-    if (bdrv_pread(s->hd, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE)
+    if (bdrv_pread(bs->file, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE)
             != HEADER_SIZE)
         goto fail;
 
@@ -199,7 +195,7 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
     s->pagetable = qemu_malloc(s->max_table_entries * 4);
 
     s->bat_offset = be64_to_cpu(dyndisk_header->table_offset);
-    if (bdrv_pread(s->hd, s->bat_offset, s->pagetable,
+    if (bdrv_pread(bs->file, s->bat_offset, s->pagetable,
             s->max_table_entries * 4) != s->max_table_entries * 4)
 	    goto fail;
 
@@ -228,7 +224,7 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
 
     return 0;
  fail:
-    bdrv_delete(s->hd);
+    bdrv_delete(bs->file);
     return -1;
 }
 
@@ -266,7 +262,7 @@ static inline int64_t get_sector_offset(BlockDriverState *bs,
 
         s->last_bitmap_offset = bitmap_offset;
         memset(bitmap, 0xff, s->bitmap_size);
-        bdrv_pwrite(s->hd, bitmap_offset, bitmap, s->bitmap_size);
+        bdrv_pwrite(bs->file, bitmap_offset, bitmap, s->bitmap_size);
     }
 
 //    printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
@@ -316,7 +312,7 @@ static int rewrite_footer(BlockDriverState* bs)
     BDRVVPCState *s = bs->opaque;
     int64_t offset = s->free_data_block_offset;
 
-    ret = bdrv_pwrite(s->hd, offset, s->footer_buf, HEADER_SIZE);
+    ret = bdrv_pwrite(bs->file, offset, s->footer_buf, HEADER_SIZE);
     if (ret < 0)
         return ret;
 
@@ -351,7 +347,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
 
     // Initialize the block's bitmap
     memset(bitmap, 0xff, s->bitmap_size);
-    bdrv_pwrite(s->hd, s->free_data_block_offset, bitmap, s->bitmap_size);
+    bdrv_pwrite(bs->file, s->free_data_block_offset, bitmap, s->bitmap_size);
 
     // Write new footer (the old one will be overwritten)
     s->free_data_block_offset += s->block_size + s->bitmap_size;
@@ -362,7 +358,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
     // Write BAT entry to disk
     bat_offset = s->bat_offset + (4 * index);
     bat_value = be32_to_cpu(s->pagetable[index]);
-    ret = bdrv_pwrite(s->hd, bat_offset, &bat_value, 4);
+    ret = bdrv_pwrite(bs->file, bat_offset, &bat_value, 4);
     if (ret < 0)
         goto fail;
 
@@ -376,7 +372,6 @@ fail:
 static int vpc_read(BlockDriverState *bs, int64_t sector_num,
                     uint8_t *buf, int nb_sectors)
 {
-    BDRVVPCState *s = bs->opaque;
     int ret;
     int64_t offset;
 
@@ -386,7 +381,7 @@ static int vpc_read(BlockDriverState *bs, int64_t sector_num,
         if (offset == -1) {
             memset(buf, 0, 512);
         } else {
-            ret = bdrv_pread(s->hd, offset, buf, 512);
+            ret = bdrv_pread(bs->file, offset, buf, 512);
             if (ret != 512)
                 return -1;
         }
@@ -401,7 +396,6 @@ static int vpc_read(BlockDriverState *bs, int64_t sector_num,
 static int vpc_write(BlockDriverState *bs, int64_t sector_num,
     const uint8_t *buf, int nb_sectors)
 {
-    BDRVVPCState *s = bs->opaque;
     int64_t offset;
     int ret;
 
@@ -414,7 +408,7 @@ static int vpc_write(BlockDriverState *bs, int64_t sector_num,
                 return -1;
         }
 
-        ret = bdrv_pwrite(s->hd, offset, buf, 512);
+        ret = bdrv_pwrite(bs->file, offset, buf, 512);
         if (ret != 512)
             return -1;
 
@@ -590,7 +584,7 @@ static void vpc_close(BlockDriverState *bs)
 #ifdef CACHE
     qemu_free(s->pageentry_u8);
 #endif
-    bdrv_delete(s->hd);
+    bdrv_delete(bs->file);
 }
 
 static QEMUOptionParameter vpc_create_options[] = {
diff --git a/block/vvfat.c b/block/vvfat.c
index 0701df4..5adbe84 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2827,7 +2827,7 @@ static void vvfat_close(BlockDriverState *bs)
 static BlockDriver bdrv_vvfat = {
     .format_name	= "vvfat",
     .instance_size	= sizeof(BDRVVVFATState),
-    .bdrv_open		= vvfat_open,
+    .bdrv_file_open	= vvfat_open,
     .bdrv_read		= vvfat_read,
     .bdrv_write		= vvfat_write,
     .bdrv_close		= vvfat_close,
diff --git a/block_int.h b/block_int.h
index d4067ff..a3afe63 100644
--- a/block_int.h
+++ b/block_int.h
@@ -51,7 +51,8 @@ struct BlockDriver {
     int instance_size;
     int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
     int (*bdrv_probe_device)(const char *filename);
-    int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
+    int (*bdrv_open)(BlockDriverState *bs, int flags);
+    int (*bdrv_file_open)(BlockDriverState *bs, const char *filename, int flags);
     int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
                      uint8_t *buf, int nb_sectors);
     int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
@@ -155,6 +156,8 @@ struct BlockDriverState {
     int media_changed;
 
     BlockDriverState *backing_hd;
+    BlockDriverState *file;
+
     /* async read/write emulation */
 
     void *sync_aiocb;
-- 
1.6.6.1

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

* [Qemu-devel] [RFC PATCH 5/5] block: bdrv_has_zero_init
  2010-04-14 15:50 [Qemu-devel] [RFC PATCH 0/5] block: Format/protocol split Kevin Wolf
                   ` (3 preceding siblings ...)
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 4/5] block: Open the underlying image file in generic code Kevin Wolf
@ 2010-04-14 15:50 ` Kevin Wolf
  4 siblings, 0 replies; 8+ messages in thread
From: Kevin Wolf @ 2010-04-14 15:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: kwolf, hch

This fixes the problem that qemu-img's use of no_zero_init only considered the
no_zero_init flag of the format driver, but not of the underlying protocols.

Between the raw/file split and this fix, converting to host devices is broken.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c    |   13 +++++++++++++
 block.h    |    1 +
 qemu-img.c |    6 ++++--
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/block.c b/block.c
index 6c66974..cf75f97 100644
--- a/block.c
+++ b/block.c
@@ -1281,6 +1281,19 @@ void bdrv_flush_all(void)
     }
 }
 
+int bdrv_has_zero_init(BlockDriverState *bs)
+{
+    assert(bs->drv);
+
+    if (bs->drv->no_zero_init) {
+        return 0;
+    } else if (bs->file) {
+        return bdrv_has_zero_init(bs->file);
+    }
+
+    return 1;
+}
+
 /*
  * Returns true iff the specified sector is present in the disk image. Drivers
  * not implementing the functionality are assumed to not support backing files,
diff --git a/block.h b/block.h
index f58edf1..f87d24e 100644
--- a/block.h
+++ b/block.h
@@ -122,6 +122,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
 void bdrv_flush(BlockDriverState *bs);
 void bdrv_flush_all(void);
 
+int bdrv_has_zero_init(BlockDriverState *bs);
 int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 	int *pnum);
 
diff --git a/qemu-img.c b/qemu-img.c
index 7203b8b..74311a5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -732,6 +732,8 @@ static int img_convert(int argc, char **argv)
         /* signal EOF to align */
         bdrv_write_compressed(out_bs, 0, NULL, 0);
     } else {
+        int has_zero_init = bdrv_has_zero_init(out_bs);
+
         sector_num = 0; // total number of sectors converted so far
         for(;;) {
             nb_sectors = total_sectors - sector_num;
@@ -755,7 +757,7 @@ static int img_convert(int argc, char **argv)
             if (n > bs_offset + bs_sectors - sector_num)
                 n = bs_offset + bs_sectors - sector_num;
 
-            if (!drv->no_zero_init) {
+            if (has_zero_init) {
                 /* If the output image is being created as a copy on write image,
                    assume that sectors which are unallocated in the input image
                    are present in both the output's and input's base images (no
@@ -788,7 +790,7 @@ static int img_convert(int argc, char **argv)
                    If the output is to a host device, we also write out
                    sectors that are entirely 0, since whatever data was
                    already there is garbage, not 0s. */
-                if (drv->no_zero_init || out_baseimg ||
+                if (!has_zero_init || out_baseimg ||
                     is_allocated_sectors(buf1, n, &n1)) {
                     if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
                         error("error while writing");
-- 
1.6.6.1

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

* Re: [Qemu-devel] [RFC PATCH 1/5] block: separate raw images from the file protocol
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 1/5] block: separate raw images from the file protocol Kevin Wolf
@ 2010-04-14 18:36   ` Stefan Hajnoczi
  0 siblings, 0 replies; 8+ messages in thread
From: Stefan Hajnoczi @ 2010-04-14 18:36 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel, hch

On Wed, Apr 14, 2010 at 4:50 PM, Kevin Wolf <kwolf@redhat.com> wrote:
> +static int raw_set_locked(BlockDriverState *bs, int locked)
> +{
> +    RAWState *s = bs->opaque;
> +    bdrv_set_locked(s->hd, locked);
> +    return 0;
> +}

Not something for this patch, but it's odd that
BlockDriver->bdrv_set_locked() has a return value but global
bdrv_set_locked() doesn't.

Stefan

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

* Re: [Qemu-devel] [RFC PATCH 4/5] block: Open the underlying image file in generic code
  2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 4/5] block: Open the underlying image file in generic code Kevin Wolf
@ 2010-04-15  8:48   ` Stefan Hajnoczi
  0 siblings, 0 replies; 8+ messages in thread
From: Stefan Hajnoczi @ 2010-04-15  8:48 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-devel, hch

On Wed, Apr 14, 2010 at 4:50 PM, Kevin Wolf <kwolf@redhat.com> wrote:
> diff --git a/block/qcow.c b/block/qcow.c
> index c619984..01b1692 100644
> --- a/block/qcow.c
> +++ b/block/qcow.c
[..]
> @@ -169,7 +166,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
>     qemu_free(s->l2_cache);
>     qemu_free(s->cluster_cache);
>     qemu_free(s->cluster_data);
> -    bdrv_delete(s->hd);
> +    bdrv_delete(bs->file);
>     return -1;
>  }

qcow.c does not need to delete bs->file anymore because block.c does
that when BlockDriver->bdrv_open() fails.  Also since we're not
setting bs->file to NULL after bdrv_delete() here, block.c will double
delete it.

> @@ -739,7 +737,7 @@ static void qcow_close(BlockDriverState *bs)
>     qemu_free(s->l2_cache);
>     qemu_free(s->cluster_cache);
>     qemu_free(s->cluster_data);
> -    bdrv_delete(s->hd);
> +    bdrv_delete(bs->file);
>  }
>
>  static int qcow_create(const char *filename, QEMUOptionParameter *options)

block.c will bdrv_close(bs->file) for us, so I think this is not
needed.  Double delete.

> diff --git a/block/qcow2.c b/block/qcow2.c
> index 11ce8d1..4949d77 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
[...]
> @@ -254,7 +250,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
>     qemu_free(s->l2_cache);
>     qemu_free(s->cluster_cache);
>     qemu_free(s->cluster_data);
> -    bdrv_delete(s->hd);
> +    bdrv_delete(bs->file);
>     return -1;
>  }

Same as above.

> diff --git a/block/vdi.c b/block/vdi.c
> index c91961a..8b85339 100644
> --- a/block/vdi.c
> +++ b/block/vdi.c
[...]
> @@ -452,7 +446,7 @@ static int vdi_open(BlockDriverState *bs, const char *filename, int flags)
>     qemu_free(s->bmap);
>
>  fail:
> -    bdrv_delete(s->hd);
> +    bdrv_delete(bs->file);
>     return -1;
>  }

Same as above.

> diff --git a/block/vpc.c b/block/vpc.c
> index 950ad58..1d1ae09 100644
> --- a/block/vpc.c
> +++ b/block/vpc.c
[...]
> @@ -228,7 +224,7 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
>
>     return 0;
>  fail:
> -    bdrv_delete(s->hd);
> +    bdrv_delete(bs->file);
>     return -1;
>  }

Same as above.

> @@ -590,7 +584,7 @@ static void vpc_close(BlockDriverState *bs)
>  #ifdef CACHE
>     qemu_free(s->pageentry_u8);
>  #endif
> -    bdrv_delete(s->hd);
> +    bdrv_delete(bs->file);
>  }
>
>  static QEMUOptionParameter vpc_create_options[] = {

Same as above.

Stefan

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

end of thread, other threads:[~2010-04-15  8:48 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-14 15:50 [Qemu-devel] [RFC PATCH 0/5] block: Format/protocol split Kevin Wolf
2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 1/5] block: separate raw images from the file protocol Kevin Wolf
2010-04-14 18:36   ` Stefan Hajnoczi
2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 2/5] block: Split bdrv_open Kevin Wolf
2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 3/5] block: Avoid forward declaration of bdrv_open_common Kevin Wolf
2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 4/5] block: Open the underlying image file in generic code Kevin Wolf
2010-04-15  8:48   ` Stefan Hajnoczi
2010-04-14 15:50 ` [Qemu-devel] [RFC PATCH 5/5] block: bdrv_has_zero_init Kevin Wolf

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.