* [Qemu-devel] [PULL 00/18] Block patches
@ 2010-04-30 14:00 Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 01/18] block: separate raw images from the file protocol Kevin Wolf
` (18 more replies)
0 siblings, 19 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
Hi Anthony,
this is the second part of the block patches in my queue that I promised in the
pull request last week. I also included the high watermark patch even if it
didn't sit on the list for a very long time - but the people that I expected to
comment on it have already done so, either on the list or internally.
Kevin
The following changes since commit 9ed7b059ef776a3921cfd085e891f45076922542:
Amit Shah (1):
virtio-serial: Implement flow control for individual ports
are available in the git repository at:
git://repo.or.cz/qemu/kevin.git for-anthony
Christoph Hellwig (1):
block: separate raw images from the file protocol
Jan Kiszka (1):
block: Release allocated options after bdrv_open
Kevin Wolf (10):
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
vmdk: Fix COW
vmdk: Clean up backing file handling
vmdk: Convert to bdrv_open
qcow2: Remove abort on free_clusters failure
block: Add wr_highest_sector blockstat
qemu-img rebase: Fix output image corruption
Stefan Hajnoczi (6):
block: Set backing_hd to NULL after deleting it
qcow2: Avoid shadowing variable in alloc_clusters_noref()
raw-posix: Use pread/pwrite instead of lseek+read/write
block: Cache total_sectors to reduce bdrv_getlength calls
qemu-img: Add 'resize' command to grow/shrink disk images
qcow2: Implement bdrv_truncate() for growing images
Makefile.objs | 2 +-
block.c | 384 ++++++++++++++++++++++++++++++++++--------------
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 | 67 ++++-----
block/qcow2-cluster.c | 64 ++++----
block/qcow2-refcount.c | 86 ++++++------
block/qcow2-snapshot.c | 22 ++--
block/qcow2.c | 110 +++++++++-----
block/qcow2.h | 8 +-
block/raw-posix.c | 62 +++------
block/raw-win32.c | 16 +-
block/raw.c | 144 ++++++++++++++++++
block/vdi.c | 29 +---
block/vmdk.c | 140 +++++-------------
block/vpc.c | 32 ++---
block/vvfat.c | 2 +-
block_int.h | 6 +-
qemu-img-cmds.hx | 6 +
qemu-img.c | 104 +++++++++++++-
qemu-img.texi | 12 ++
28 files changed, 843 insertions(+), 494 deletions(-)
create mode 100644 block/raw.c
^ permalink raw reply [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 01/18] block: separate raw images from the file protocol
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 02/18] block: Split bdrv_open Kevin Wolf
` (17 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
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 1c7c64b..4f65bfb 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 7974215..ad681db 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] 20+ messages in thread
* [Qemu-devel] [PATCH 02/18] block: Split bdrv_open
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 01/18] block: separate raw images from the file protocol Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 03/18] block: Avoid forward declaration of bdrv_open_common Kevin Wolf
` (16 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
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 ad681db..6efc2b3 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] 20+ messages in thread
* [Qemu-devel] [PATCH 03/18] block: Avoid forward declaration of bdrv_open_common
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 01/18] block: separate raw images from the file protocol Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 02/18] block: Split bdrv_open Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 04/18] block: Open the underlying image file in generic code Kevin Wolf
` (15 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
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 6efc2b3..f9b5e53 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] 20+ messages in thread
* [Qemu-devel] [PATCH 04/18] block: Open the underlying image file in generic code
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (2 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 03/18] block: Avoid forward declaration of bdrv_open_common Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 05/18] block: bdrv_has_zero_init Kevin Wolf
` (14 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
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 | 26 +++++++++++++++-
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 | 67 ++++++++++++++++++----------------------
block/qcow2-cluster.c | 64 ++++++++++++++++++++------------------
block/qcow2-refcount.c | 80 ++++++++++++++++++++++++------------------------
block/qcow2-snapshot.c | 22 ++++++------
block/qcow2.c | 66 +++++++++++++++++-----------------------
block/qcow2.h | 2 +-
block/raw-posix.c | 10 +++---
block/raw-win32.c | 4 +-
block/raw.c | 63 +++++++++++---------------------------
block/vdi.c | 29 +++++------------
block/vmdk.c | 2 +-
block/vpc.c | 32 +++++++------------
block/vvfat.c | 2 +-
block_int.h | 5 ++-
23 files changed, 237 insertions(+), 276 deletions(-)
diff --git a/block.c b/block.c
index f9b5e53..eb1d562 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))
@@ -360,6 +362,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
assert(drv != NULL);
+ bs->file = NULL;
bs->is_temporary = 0;
bs->encrypted = 0;
bs->valid_key = 0;
@@ -398,7 +401,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 +427,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 +601,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 +620,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 fb83594..e952670 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -252,7 +252,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 06c687e..e4f995b 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -158,7 +158,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 f4c01c7..d5c1a68 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -288,7 +288,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 41b3a7c..b217101 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -167,7 +167,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..2883c40 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,6 @@ 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);
return -1;
}
@@ -271,13 +267,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 +302,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 +325,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 +354,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 +368,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 +418,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 +428,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 +465,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 +598,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 +611,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 +696,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 +736,6 @@ 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);
}
static int qcow_create(const char *filename, QEMUOptionParameter *options)
@@ -839,9 +835,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 +898,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 +910,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 5436fec..4fa3ff9 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,6 @@ 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);
return -1;
}
@@ -429,7 +424,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 +444,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 +460,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);
@@ -615,8 +610,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);
@@ -663,7 +658,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);
}
/*
@@ -733,7 +727,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;
}
@@ -742,13 +736,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;
@@ -789,7 +783,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;
@@ -832,7 +825,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;
@@ -847,9 +840,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;
@@ -872,9 +865,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;
}
@@ -917,8 +910,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;
}
@@ -930,16 +923,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)
@@ -968,7 +958,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;
@@ -988,7 +978,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;
@@ -1003,7 +993,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..1d257b4 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,6 @@ static int vdi_open(BlockDriverState *bs, const char *filename, int flags)
qemu_free(s->bmap);
fail:
- bdrv_delete(s->hd);
return -1;
}
@@ -607,7 +600,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 +663,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 +692,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 +741,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 +754,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 +884,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..f94e469 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,6 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
return 0;
fail:
- bdrv_delete(s->hd);
return -1;
}
@@ -266,7 +261,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 +311,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 +346,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 +357,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 +371,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 +380,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 +395,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 +407,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 +583,6 @@ static void vpc_close(BlockDriverState *bs)
#ifdef CACHE
qemu_free(s->pageentry_u8);
#endif
- bdrv_delete(s->hd);
}
static QEMUOptionParameter vpc_create_options[] = {
diff --git a/block/vvfat.c b/block/vvfat.c
index 66259b4..ce16bbd 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] 20+ messages in thread
* [Qemu-devel] [PATCH 05/18] block: bdrv_has_zero_init
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (3 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 04/18] block: Open the underlying image file in generic code Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 06/18] vmdk: Fix COW Kevin Wolf
` (13 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
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 eb1d562..56835af 100644
--- a/block.c
+++ b/block.c
@@ -1282,6 +1282,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] 20+ messages in thread
* [Qemu-devel] [PATCH 06/18] vmdk: Fix COW
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (4 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 05/18] block: bdrv_has_zero_init Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 07/18] vmdk: Clean up backing file handling Kevin Wolf
` (12 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
When trying to do COW, VMDK wrote the data back to the backing file. This
problem was revealed by the patch that made backing files read-only. This patch
does not only fix the problem, but also simplifies the VMDK code a bit.
This fixes the backing file qemu-iotests cases for VMDK.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/vmdk.c | 35 +++++++++++------------------------
1 files changed, 11 insertions(+), 24 deletions(-)
diff --git a/block/vmdk.c b/block/vmdk.c
index 5ef4375..ae34121 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -87,14 +87,6 @@ typedef struct VmdkMetaData {
int valid;
} VmdkMetaData;
-typedef struct ActiveBDRVState{
- BlockDriverState *hd; // active image handler
- uint64_t cluster_offset; // current write offset
-}ActiveBDRVState;
-
-static ActiveBDRVState activeBDRV;
-
-
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
{
uint32_t magic;
@@ -492,30 +484,28 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
uint64_t offset, int allocate)
{
- uint64_t parent_cluster_offset;
BDRVVmdkState *s = bs->opaque;
uint8_t whole_grain[s->cluster_sectors*512]; // 128 sectors * 512 bytes each = grain size 64KB
// we will be here if it's first write on non-exist grain(cluster).
// try to read from parent image, if exist
if (bs->backing_hd) {
- BDRVVmdkState *ps = bs->backing_hd->opaque;
+ int ret;
if (!vmdk_is_cid_valid(bs))
return -1;
- parent_cluster_offset = get_cluster_offset(bs->backing_hd, NULL,
- offset, allocate);
-
- if (parent_cluster_offset) {
- BDRVVmdkState *act_s = activeBDRV.hd->opaque;
-
- if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) != ps->cluster_sectors*512)
- return -1;
+ ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
+ s->cluster_sectors);
+ if (ret < 0) {
+ return -1;
+ }
- //Write grain only into the active image
- if (bdrv_pwrite(act_s->hd, activeBDRV.cluster_offset << 9, whole_grain, sizeof(whole_grain)) != sizeof(whole_grain))
- return -1;
+ //Write grain only into the active image
+ ret = bdrv_write(s->hd, cluster_offset, whole_grain,
+ s->cluster_sectors);
+ if (ret < 0) {
+ return -1;
}
}
return 0;
@@ -601,9 +591,6 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
cluster_offset >>= 9;
tmp = cpu_to_le32(cluster_offset);
l2_table[l2_index] = tmp;
- // Save the active image state
- activeBDRV.cluster_offset = cluster_offset;
- activeBDRV.hd = bs;
}
/* First of all we write grain itself, to avoid race condition
* that may to corrupt the image.
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 07/18] vmdk: Clean up backing file handling
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (5 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 06/18] vmdk: Fix COW Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 08/18] vmdk: Convert to bdrv_open Kevin Wolf
` (11 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
VMDK is doing interesting things when it needs to open a backing file. This
patch changes that part to look more like in other drivers. The nice side
effect is that the file name isn't needed any more in the open function.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/vmdk.c | 58 +++++++++-------------------------------------------------
1 files changed, 9 insertions(+), 49 deletions(-)
diff --git a/block/vmdk.c b/block/vmdk.c
index ae34121..e44769b 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -76,7 +76,6 @@ typedef struct BDRVVmdkState {
unsigned int cluster_sectors;
uint32_t parent_cid;
- int is_parent;
} BDRVVmdkState;
typedef struct VmdkMetaData {
@@ -338,19 +337,11 @@ fail:
return ret;
}
-static void vmdk_parent_close(BlockDriverState *bs)
-{
- if (bs->backing_hd)
- bdrv_close(bs->backing_hd);
-}
-
-static int parent_open = 0;
-static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
+static int vmdk_parent_open(BlockDriverState *bs)
{
BDRVVmdkState *s = bs->opaque;
char *p_name;
char desc[DESC_SIZE];
- char parent_img_name[1024];
/* the descriptor offset = 0x200 */
if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
@@ -358,7 +349,6 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) {
char *end_name;
- struct stat file_buf;
p_name += sizeof("parentFileNameHint") + 1;
if ((end_name = strchr(p_name,'\"')) == NULL)
@@ -367,24 +357,6 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
return -1;
pstrcpy(bs->backing_file, end_name - p_name + 1, p_name);
- if (stat(bs->backing_file, &file_buf) != 0) {
- path_combine(parent_img_name, sizeof(parent_img_name),
- filename, bs->backing_file);
- } else {
- pstrcpy(parent_img_name, sizeof(parent_img_name),
- bs->backing_file);
- }
-
- bs->backing_hd = bdrv_new("");
- if (!bs->backing_hd) {
- failure:
- bdrv_close(s->hd);
- return -1;
- }
- parent_open = 1;
- if (bdrv_open(bs->backing_hd, parent_img_name, 0, NULL) < 0)
- goto failure;
- parent_open = 0;
}
return 0;
@@ -396,11 +368,6 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
uint32_t magic;
int l1_size, i, ret;
- if (parent_open) {
- /* Parent must be opened as RO, no RDWR. */
- flags = 0;
- }
-
ret = bdrv_file_open(&s->hd, filename, flags);
if (ret < 0)
return ret;
@@ -436,13 +403,8 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
- if (parent_open)
- s->is_parent = 1;
- else
- s->is_parent = 0;
-
// try to open parent images, if exist
- if (vmdk_parent_open(bs, filename) != 0)
+ if (vmdk_parent_open(bs) != 0)
goto fail;
// write the CID once after the image creation
s->parent_cid = vmdk_read_cid(bs,1);
@@ -583,15 +545,15 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
if (!cluster_offset) {
if (!allocate)
return 0;
+
// Avoid the L2 tables update for the images that have snapshots.
- if (!s->is_parent) {
- cluster_offset = bdrv_getlength(s->hd);
- bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+ cluster_offset = bdrv_getlength(s->hd);
+ bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+
+ cluster_offset >>= 9;
+ tmp = cpu_to_le32(cluster_offset);
+ l2_table[l2_index] = tmp;
- cluster_offset >>= 9;
- tmp = cpu_to_le32(cluster_offset);
- l2_table[l2_index] = tmp;
- }
/* First of all we write grain itself, to avoid race condition
* that may to corrupt the image.
* This problem may occur because of insufficient space on host disk
@@ -866,8 +828,6 @@ static void vmdk_close(BlockDriverState *bs)
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
- // try to close parent image, if exist
- vmdk_parent_close(s->hd);
bdrv_delete(s->hd);
}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 08/18] vmdk: Convert to bdrv_open
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (6 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 07/18] vmdk: Clean up backing file handling Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 09/18] block: Set backing_hd to NULL after deleting it Kevin Wolf
` (10 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
It's a format driver, so implement bdrv_open instead of bdrv_file_open.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/vmdk.c | 51 +++++++++++++++++++++------------------------------
1 files changed, 21 insertions(+), 30 deletions(-)
diff --git a/block/vmdk.c b/block/vmdk.c
index e44769b..e659908 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -108,14 +108,13 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
{
- BDRVVmdkState *s = bs->opaque;
char desc[DESC_SIZE];
uint32_t cid;
const char *p_name, *cid_str;
size_t cid_str_size;
/* the descriptor offset = 0x200 */
- if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+ if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return 0;
if (parent) {
@@ -136,12 +135,11 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
{
- BDRVVmdkState *s = bs->opaque;
char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
char *p_name, *tmp_str;
/* the descriptor offset = 0x200 */
- if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+ if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return -1;
tmp_str = strstr(desc,"parentCID");
@@ -152,7 +150,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
pstrcat(desc, sizeof(desc), tmp_desc);
}
- if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+ if (bdrv_pwrite(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return -1;
return 0;
}
@@ -339,12 +337,11 @@ fail:
static int vmdk_parent_open(BlockDriverState *bs)
{
- BDRVVmdkState *s = bs->opaque;
char *p_name;
char desc[DESC_SIZE];
/* the descriptor offset = 0x200 */
- if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+ if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return -1;
if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) {
@@ -362,23 +359,20 @@ static int vmdk_parent_open(BlockDriverState *bs)
return 0;
}
-static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
+static int vmdk_open(BlockDriverState *bs, int flags)
{
BDRVVmdkState *s = bs->opaque;
uint32_t magic;
- int l1_size, i, ret;
+ int l1_size, i;
- ret = bdrv_file_open(&s->hd, filename, flags);
- if (ret < 0)
- return ret;
- if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
+ if (bdrv_pread(bs->file, 0, &magic, sizeof(magic)) != sizeof(magic))
goto fail;
magic = be32_to_cpu(magic);
if (magic == VMDK3_MAGIC) {
VMDK3Header header;
- if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
+ if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) != sizeof(header))
goto fail;
s->cluster_sectors = le32_to_cpu(header.granularity);
s->l2_size = 1 << 9;
@@ -390,7 +384,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
} else if (magic == VMDK4_MAGIC) {
VMDK4Header header;
- if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
+ if (bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)) != sizeof(header))
goto fail;
bs->total_sectors = le64_to_cpu(header.capacity);
s->cluster_sectors = le64_to_cpu(header.granularity);
@@ -415,7 +409,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
/* read the L1 table */
l1_size = s->l1_size * sizeof(uint32_t);
s->l1_table = qemu_malloc(l1_size);
- if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
+ if (bdrv_pread(bs->file, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
goto fail;
for(i = 0; i < s->l1_size; i++) {
le32_to_cpus(&s->l1_table[i]);
@@ -423,7 +417,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
if (s->l1_backup_table_offset) {
s->l1_backup_table = qemu_malloc(l1_size);
- if (bdrv_pread(s->hd, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
+ if (bdrv_pread(bs->file, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
goto fail;
for(i = 0; i < s->l1_size; i++) {
le32_to_cpus(&s->l1_backup_table[i]);
@@ -436,7 +430,6 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
qemu_free(s->l1_backup_table);
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
- bdrv_delete(s->hd);
return -1;
}
@@ -464,7 +457,7 @@ static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
}
//Write grain only into the active image
- ret = bdrv_write(s->hd, cluster_offset, whole_grain,
+ ret = bdrv_write(bs->file, cluster_offset, whole_grain,
s->cluster_sectors);
if (ret < 0) {
return -1;
@@ -478,13 +471,13 @@ static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data)
BDRVVmdkState *s = bs->opaque;
/* update L2 table */
- if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
+ if (bdrv_pwrite(bs->file, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
&(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
return -1;
/* update backup L2 table */
if (s->l1_backup_table_offset != 0) {
m_data->l2_offset = s->l1_backup_table[m_data->l1_index];
- if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
+ if (bdrv_pwrite(bs->file, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
&(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
return -1;
}
@@ -532,7 +525,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
}
}
l2_table = s->l2_cache + (min_index * s->l2_size);
- if (bdrv_pread(s->hd, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) !=
+ if (bdrv_pread(bs->file, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) !=
s->l2_size * sizeof(uint32_t))
return 0;
@@ -547,8 +540,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
return 0;
// Avoid the L2 tables update for the images that have snapshots.
- cluster_offset = bdrv_getlength(s->hd);
- bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+ cluster_offset = bdrv_getlength(bs->file);
+ bdrv_truncate(bs->file, cluster_offset + (s->cluster_sectors << 9));
cluster_offset >>= 9;
tmp = cpu_to_le32(cluster_offset);
@@ -615,7 +608,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
memset(buf, 0, 512 * n);
}
} else {
- if(bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
+ if(bdrv_pread(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
return -1;
}
nb_sectors -= n;
@@ -651,7 +644,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
if (!cluster_offset)
return -1;
- if (bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
+ if (bdrv_pwrite(bs->file, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
return -1;
if (m_data.valid) {
/* update L2 tables */
@@ -828,13 +821,11 @@ static void vmdk_close(BlockDriverState *bs)
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
- bdrv_delete(s->hd);
}
static void vmdk_flush(BlockDriverState *bs)
{
- BDRVVmdkState *s = bs->opaque;
- bdrv_flush(s->hd);
+ bdrv_flush(bs->file);
}
@@ -861,7 +852,7 @@ static BlockDriver bdrv_vmdk = {
.format_name = "vmdk",
.instance_size = sizeof(BDRVVmdkState),
.bdrv_probe = vmdk_probe,
- .bdrv_file_open = vmdk_open,
+ .bdrv_open = vmdk_open,
.bdrv_read = vmdk_read,
.bdrv_write = vmdk_write,
.bdrv_close = vmdk_close,
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 09/18] block: Set backing_hd to NULL after deleting it
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (7 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 08/18] vmdk: Convert to bdrv_open Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 10/18] qcow2: Avoid shadowing variable in alloc_clusters_noref() Kevin Wolf
` (9 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
It is safer to set backing_hd to NULL after deleting it so that any use
after deletion is obvious during development. Happy segfaulting!
This patch should be applied after Kevin Wolf's "vmdk: Convert to
bdrv_open" so that vmdk does not segfault on close.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/block.c b/block.c
index 56835af..b318355 100644
--- a/block.c
+++ b/block.c
@@ -589,8 +589,10 @@ unlink_and_fail:
void bdrv_close(BlockDriverState *bs)
{
if (bs->drv) {
- if (bs->backing_hd)
+ if (bs->backing_hd) {
bdrv_delete(bs->backing_hd);
+ bs->backing_hd = NULL;
+ }
bs->drv->bdrv_close(bs);
qemu_free(bs->opaque);
#ifdef _WIN32
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 10/18] qcow2: Avoid shadowing variable in alloc_clusters_noref()
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (8 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 09/18] block: Set backing_hd to NULL after deleting it Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 11/18] raw-posix: Use pread/pwrite instead of lseek+read/write Kevin Wolf
` (8 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
The i loop iterator is shadowed by the next free cluster index. Both
using the variable name 'i' makes the code harder to read.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2-refcount.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 2661493..95491d3 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -556,8 +556,8 @@ static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
nb_clusters = size_to_clusters(s, size);
retry:
for(i = 0; i < nb_clusters; i++) {
- int64_t i = s->free_cluster_index++;
- if (get_refcount(bs, i) != 0)
+ int64_t next_cluster_index = s->free_cluster_index++;
+ if (get_refcount(bs, next_cluster_index) != 0)
goto retry;
}
#ifdef DEBUG_ALLOC2
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 11/18] raw-posix: Use pread/pwrite instead of lseek+read/write
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (9 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 10/18] qcow2: Avoid shadowing variable in alloc_clusters_noref() Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 12/18] block: Cache total_sectors to reduce bdrv_getlength calls Kevin Wolf
` (7 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
This patch combines the lseek+read/write calls to use pread/pwrite
instead. This will result in fewer system calls and is already used by
AIO.
Thanks to Jan Kiszka <jan.kiszka@siemens.com> for identifying excessive
lseek and Christoph Hellwig <hch@lst.de> for confirming that this
approach should work.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/raw-posix.c | 37 ++++---------------------------------
1 files changed, 4 insertions(+), 33 deletions(-)
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 598ea19..7541ed2 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -105,7 +105,6 @@
typedef struct BDRVRawState {
int fd;
int type;
- unsigned int lseek_err_cnt;
int open_flags;
#if defined(__linux__)
/* linux floppy specific */
@@ -134,8 +133,6 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
BDRVRawState *s = bs->opaque;
int fd, ret;
- s->lseek_err_cnt = 0;
-
s->open_flags = open_flags | O_BINARY;
s->open_flags &= ~O_ACCMODE;
if (bdrv_flags & BDRV_O_RDWR) {
@@ -243,19 +240,7 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
if (ret < 0)
return ret;
- if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
- ++(s->lseek_err_cnt);
- if(s->lseek_err_cnt <= 10) {
- DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
- "] lseek failed : %d = %s\n",
- s->fd, bs->filename, offset, buf, count,
- bs->total_sectors, errno, strerror(errno));
- }
- return -1;
- }
- s->lseek_err_cnt=0;
-
- ret = read(s->fd, buf, count);
+ ret = pread(s->fd, buf, count, offset);
if (ret == count)
goto label__raw_read__success;
@@ -276,12 +261,10 @@ static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
/* Try harder for CDrom. */
if (bs->type == BDRV_TYPE_CDROM) {
- lseek(s->fd, offset, SEEK_SET);
- ret = read(s->fd, buf, count);
+ ret = pread(s->fd, buf, count, offset);
if (ret == count)
goto label__raw_read__success;
- lseek(s->fd, offset, SEEK_SET);
- ret = read(s->fd, buf, count);
+ ret = pread(s->fd, buf, count, offset);
if (ret == count)
goto label__raw_read__success;
@@ -313,19 +296,7 @@ static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
if (ret < 0)
return -errno;
- if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
- ++(s->lseek_err_cnt);
- if(s->lseek_err_cnt) {
- DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
- PRId64 "] lseek failed : %d = %s\n",
- s->fd, bs->filename, offset, buf, count,
- bs->total_sectors, errno, strerror(errno));
- }
- return -EIO;
- }
- s->lseek_err_cnt = 0;
-
- ret = write(s->fd, buf, count);
+ ret = pwrite(s->fd, buf, count, offset);
if (ret == count)
goto label__raw_write__success;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 12/18] block: Cache total_sectors to reduce bdrv_getlength calls
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (10 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 11/18] raw-posix: Use pread/pwrite instead of lseek+read/write Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 13/18] qemu-img: Add 'resize' command to grow/shrink disk images Kevin Wolf
` (6 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
The BlockDriver bdrv_getlength function is called from the I/O code path
when checking that the request falls within the device. Unfortunately
this involves an lseek system call in the raw protocol; every read or
write request will incur this lseek cost.
Jan Kiszka <jan.kiszka@siemens.com> identified this issue and its
latency overhead. This patch caches device length in the existing
total_sectors variable so lseek calls can be avoided for fixed size
devices.
Growable devices fall back to the full bdrv_getlength code path because
I have not added logic to detect extending the size of the device in a
write.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block.c | 43 ++++++++++++++++++++++++++++++++++++++-----
1 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/block.c b/block.c
index b318355..91fecab 100644
--- a/block.c
+++ b/block.c
@@ -352,6 +352,26 @@ static BlockDriver *find_image_format(const char *filename)
return drv;
}
+/**
+ * Set the current 'total_sectors' value
+ */
+static int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
+{
+ BlockDriver *drv = bs->drv;
+
+ /* query actual device if possible, otherwise just trust the hint */
+ if (drv->bdrv_getlength) {
+ int64_t length = drv->bdrv_getlength(bs);
+ if (length < 0) {
+ return length;
+ }
+ hint = length >> BDRV_SECTOR_BITS;
+ }
+
+ bs->total_sectors = hint;
+ return 0;
+}
+
/*
* Common part for opening disk images and files
*/
@@ -363,6 +383,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
assert(drv != NULL);
bs->file = NULL;
+ bs->total_sectors = 0;
bs->is_temporary = 0;
bs->encrypted = 0;
bs->valid_key = 0;
@@ -416,9 +437,12 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
}
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;
+
+ ret = refresh_total_sectors(bs, bs->total_sectors);
+ if (ret < 0) {
+ goto free_and_fail;
}
+
#ifndef _WIN32
if (bs->is_temporary) {
unlink(filename);
@@ -959,13 +983,18 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
int bdrv_truncate(BlockDriverState *bs, int64_t offset)
{
BlockDriver *drv = bs->drv;
+ int ret;
if (!drv)
return -ENOMEDIUM;
if (!drv->bdrv_truncate)
return -ENOTSUP;
if (bs->read_only)
return -EACCES;
- return drv->bdrv_truncate(bs, offset);
+ ret = drv->bdrv_truncate(bs, offset);
+ if (ret == 0) {
+ ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
+ }
+ return ret;
}
/**
@@ -976,8 +1005,12 @@ int64_t bdrv_getlength(BlockDriverState *bs)
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_getlength) {
- /* legacy mode */
+
+ /* Fixed size devices use the total_sectors value for speed instead of
+ issuing a length query (like lseek) on each call. Also, legacy block
+ drivers don't provide a bdrv_getlength function and must use
+ total_sectors. */
+ if (!bs->growable || !drv->bdrv_getlength) {
return bs->total_sectors * BDRV_SECTOR_SIZE;
}
return drv->bdrv_getlength(bs);
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 13/18] qemu-img: Add 'resize' command to grow/shrink disk images
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (11 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 12/18] block: Cache total_sectors to reduce bdrv_getlength calls Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 14/18] qcow2: Remove abort on free_clusters failure Kevin Wolf
` (5 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
This patch adds a 'resize' command to grow/shrink disk images. This
allows changing the size of disk images without copying to a new image
file. Currently only raw files support resize.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
qemu-img-cmds.hx | 6 +++
qemu-img.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
qemu-img.texi | 12 +++++++
3 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index f96876a..c079019 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -49,5 +49,11 @@ DEF("rebase", img_rebase,
"rebase [-f fmt] [-u] -b backing_file [-F backing_fmt] filename")
STEXI
@item rebase [-f @var{fmt}] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
+ETEXI
+
+DEF("resize", img_resize,
+ "resize filename [+ | -]size")
+STEXI
+@item rebase @var{filename} [+ | -]@var{size}
@end table
ETEXI
diff --git a/qemu-img.c b/qemu-img.c
index 74311a5..c21d999 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1225,6 +1225,98 @@ static int img_rebase(int argc, char **argv)
return 0;
}
+static int img_resize(int argc, char **argv)
+{
+ int c, ret, relative;
+ const char *filename, *fmt, *size;
+ int64_t n, total_size;
+ BlockDriverState *bs;
+ QEMUOptionParameter *param;
+ QEMUOptionParameter resize_options[] = {
+ {
+ .name = BLOCK_OPT_SIZE,
+ .type = OPT_SIZE,
+ .help = "Virtual disk size"
+ },
+ { NULL }
+ };
+
+ fmt = NULL;
+ for(;;) {
+ c = getopt(argc, argv, "f:h");
+ if (c == -1) {
+ break;
+ }
+ switch(c) {
+ case 'h':
+ help();
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ }
+ }
+ if (optind + 1 >= argc) {
+ help();
+ }
+ filename = argv[optind++];
+ size = argv[optind++];
+
+ /* Choose grow, shrink, or absolute resize mode */
+ switch (size[0]) {
+ case '+':
+ relative = 1;
+ size++;
+ break;
+ case '-':
+ relative = -1;
+ size++;
+ break;
+ default:
+ relative = 0;
+ break;
+ }
+
+ /* Parse size */
+ param = parse_option_parameters("", resize_options, NULL);
+ if (set_option_parameter(param, BLOCK_OPT_SIZE, size)) {
+ /* Error message already printed when size parsing fails */
+ exit(1);
+ }
+ n = get_option_parameter(param, BLOCK_OPT_SIZE)->value.n;
+ free_option_parameters(param);
+
+ bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
+
+ if (relative) {
+ total_size = bdrv_getlength(bs) + n * relative;
+ } else {
+ total_size = n;
+ }
+ if (total_size <= 0) {
+ error("New image size must be positive");
+ }
+
+ ret = bdrv_truncate(bs, total_size);
+ switch (ret) {
+ case 0:
+ printf("Image resized.\n");
+ break;
+ case -ENOTSUP:
+ error("This image format does not support resize");
+ break;
+ case -EACCES:
+ error("Image is read-only");
+ break;
+ default:
+ error("Error resizing image (%d)", -ret);
+ break;
+ }
+
+ bdrv_delete(bs);
+ return 0;
+}
+
static const img_cmd_t img_cmds[] = {
#define DEF(option, callback, arg_string) \
{ option, callback },
diff --git a/qemu-img.texi b/qemu-img.texi
index ac97854..c1b1f27 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -106,6 +106,18 @@ they are displayed too.
@item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot} ] @var{filename}
List, apply, create or delete snapshots in image @var{filename}.
+
+@item resize @var{filename} [+ | -]@var{size}
+
+Change the disk image as if it had been created with @var{size}.
+
+Before using this command to shrink a disk image, you MUST use file system and
+partitioning tools inside the VM to reduce allocated file systems and partition
+sizes accordingly. Failure to do so will result in data loss!
+
+After using this command to grow a disk image, you must use file system and
+partitioning tools inside the VM to actually begin using the new space on the
+device.
@end table
Supported image file formats:
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 14/18] qcow2: Remove abort on free_clusters failure
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (12 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 13/18] qemu-img: Add 'resize' command to grow/shrink disk images Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 15/18] qcow2: Implement bdrv_truncate() for growing images Kevin Wolf
` (4 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
While it's true that during regular operation free_clusters failure would be a
bug, an I/O error can always happen. There's no need to kill the VM, the worst
thing that can happen (and it will) is that we leak some clusters.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2-refcount.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 95491d3..744107c 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -638,7 +638,7 @@ void qcow2_free_clusters(BlockDriverState *bs,
ret = update_refcount(bs, offset, size, -1);
if (ret < 0) {
fprintf(stderr, "qcow2_free_clusters failed: %s\n", strerror(-ret));
- abort();
+ /* TODO Remember the clusters to free them later and avoid leaking */
}
}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 15/18] qcow2: Implement bdrv_truncate() for growing images
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (13 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 14/18] qcow2: Remove abort on free_clusters failure Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 16/18] block: Add wr_highest_sector blockstat Kevin Wolf
` (3 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
This patch adds the ability to grow qcow2 images in-place using
bdrv_truncate(). This enables qemu-img resize command support for
qcow2.
Snapshots are not supported and bdrv_truncate() will return -ENOTSUP.
The notion of resizing an image with snapshots could lead to confusion:
users may expect snapshots to remain unchanged, but this is not possible
with the current qcow2 on-disk format where the header.size field is
global instead of per-snapshot. Others may expect snapshots to change
size along with the current image data. I think it is safest to not
support snapshots and perhaps add behavior later if there is a
consensus.
Backing images continue to work. If the image is now larger than its
backing image, zeroes are read when accessing beyond the end of the
backing image.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/qcow2.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
block/qcow2.h | 6 ++++++
2 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 4fa3ff9..21ed6f8 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -140,7 +140,7 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
static int qcow_open(BlockDriverState *bs, int flags)
{
BDRVQcowState *s = bs->opaque;
- int len, i, shift;
+ int len, i;
QCowHeader header;
uint64_t ext_end;
@@ -188,8 +188,7 @@ static int qcow_open(BlockDriverState *bs, int flags)
/* read the level 1 table */
s->l1_size = header.l1_size;
- shift = s->cluster_bits + s->l2_bits;
- s->l1_vm_state_index = (header.size + (1LL << shift) - 1) >> shift;
+ s->l1_vm_state_index = size_to_l1(s, header.size);
/* the L1 table must contain at least enough entries to put
header.size bytes */
if (s->l1_size < s->l1_vm_state_index)
@@ -851,6 +850,43 @@ static int qcow_make_empty(BlockDriverState *bs)
return 0;
}
+static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
+{
+ BDRVQcowState *s = bs->opaque;
+ int ret, new_l1_size;
+
+ if (offset & 511) {
+ return -EINVAL;
+ }
+
+ /* cannot proceed if image has snapshots */
+ if (s->nb_snapshots) {
+ return -ENOTSUP;
+ }
+
+ /* shrinking is currently not supported */
+ if (offset < bs->total_sectors * 512) {
+ return -ENOTSUP;
+ }
+
+ new_l1_size = size_to_l1(s, offset);
+ ret = qcow2_grow_l1_table(bs, new_l1_size);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* write updated header.size */
+ offset = cpu_to_be64(offset);
+ ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, size),
+ &offset, sizeof(uint64_t));
+ if (ret < 0) {
+ return ret;
+ }
+
+ s->l1_vm_state_index = new_l1_size;
+ return 0;
+}
+
/* XXX: put compressed sectors first, then all the cluster aligned
tables to avoid losing bytes in alignment */
static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
@@ -1050,7 +1086,9 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_aio_readv = qcow_aio_readv,
.bdrv_aio_writev = qcow_aio_writev,
.bdrv_aio_flush = qcow_aio_flush,
- .bdrv_write_compressed = qcow_write_compressed,
+
+ .bdrv_truncate = qcow2_truncate,
+ .bdrv_write_compressed = qcow_write_compressed,
.bdrv_snapshot_create = qcow2_snapshot_create,
.bdrv_snapshot_goto = qcow2_snapshot_goto,
diff --git a/block/qcow2.h b/block/qcow2.h
index 5bd08db..01053b7 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -150,6 +150,12 @@ static inline int size_to_clusters(BDRVQcowState *s, int64_t size)
return (size + (s->cluster_size - 1)) >> s->cluster_bits;
}
+static inline int size_to_l1(BDRVQcowState *s, int64_t size)
+{
+ int shift = s->cluster_bits + s->l2_bits;
+ return (size + (1ULL << shift) - 1) >> shift;
+}
+
static inline int64_t align_offset(int64_t offset, int n)
{
offset = (offset + n - 1) & ~(n - 1);
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 16/18] block: Add wr_highest_sector blockstat
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (14 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 15/18] qcow2: Implement bdrv_truncate() for growing images Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 17/18] qemu-img rebase: Fix output image corruption Kevin Wolf
` (2 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
This adds the wr_highest_sector blockstat which implements what is generally
known as the high watermark. It is the highest offset of a sector written to
the respective BlockDriverState since it has been opened.
The query-blockstat QMP command is extended to add this value to the result,
and also to add the statistics of the underlying protocol in a new "parent"
field. Note that to get the "high watermark" of a qcow2 image, you need to look
into the wr_highest_sector field of the parent (which can be a file, a
host_device, ...). The wr_highest_sector of the qcow2 BlockDriverState itself
is the highest offset on the _virtual_ disk that the guest has written to.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++------------
block_int.h | 1 +
2 files changed, 59 insertions(+), 15 deletions(-)
diff --git a/block.c b/block.c
index 91fecab..f463ec4 100644
--- a/block.c
+++ b/block.c
@@ -880,6 +880,10 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
set_dirty_bitmap(bs, sector_num, nb_sectors, 1);
}
+ if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
+ bs->wr_highest_sector = sector_num + nb_sectors - 1;
+ }
+
return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
}
@@ -1530,6 +1534,35 @@ void bdrv_stats_print(Monitor *mon, const QObject *data)
qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon);
}
+static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
+{
+ QObject *res;
+ QDict *dict;
+
+ res = qobject_from_jsonf("{ 'stats': {"
+ "'rd_bytes': %" PRId64 ","
+ "'wr_bytes': %" PRId64 ","
+ "'rd_operations': %" PRId64 ","
+ "'wr_operations': %" PRId64 ","
+ "'wr_highest_offset': %" PRId64
+ "} }",
+ bs->rd_bytes, bs->wr_bytes,
+ bs->rd_ops, bs->wr_ops,
+ bs->wr_highest_sector * 512);
+ dict = qobject_to_qdict(res);
+
+ if (*bs->device_name) {
+ qdict_put(dict, "device", qstring_from_str(bs->device_name));
+ }
+
+ if (bs->file) {
+ QObject *parent = bdrv_info_stats_bs(bs->file);
+ qdict_put_obj(dict, "parent", parent);
+ }
+
+ return res;
+}
+
/**
* bdrv_info_stats(): show block device statistics
*
@@ -1544,19 +1577,34 @@ void bdrv_stats_print(Monitor *mon, const QObject *data)
* - "wr_bytes": bytes written
* - "rd_operations": read operations
* - "wr_operations": write operations
- *
+ * - "wr_highest_offset": Highest offset of a sector written since the
+ * BlockDriverState has been opened
+ * - "parent": Contains recursively the statistics of the underlying
+ * protocol (e.g. the host file for a qcow2 image). If there is no
+ * underlying protocol, this field is omitted.
+ *
* Example:
*
* [ { "device": "ide0-hd0",
* "stats": { "rd_bytes": 512,
* "wr_bytes": 0,
* "rd_operations": 1,
- * "wr_operations": 0 } },
+ * "wr_operations": 0,
+ * "wr_highest_offset": 0,
+ * "parent": {
+ * "stats": { "rd_bytes": 1024,
+ * "wr_bytes": 0,
+ * "rd_operations": 2,
+ * "wr_operations": 0,
+ * "wr_highest_offset": 0,
+ * }
+ * } } },
* { "device": "ide1-cd0",
* "stats": { "rd_bytes": 0,
* "wr_bytes": 0,
* "rd_operations": 0,
- * "wr_operations": 0 } } ]
+ * "wr_operations": 0,
+ * "wr_highest_offset": 0 } },
*/
void bdrv_info_stats(Monitor *mon, QObject **ret_data)
{
@@ -1567,15 +1615,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data)
devices = qlist_new();
QTAILQ_FOREACH(bs, &bdrv_states, list) {
- obj = qobject_from_jsonf("{ 'device': %s, 'stats': {"
- "'rd_bytes': %" PRId64 ","
- "'wr_bytes': %" PRId64 ","
- "'rd_operations': %" PRId64 ","
- "'wr_operations': %" PRId64
- "} }",
- bs->device_name,
- bs->rd_bytes, bs->wr_bytes,
- bs->rd_ops, bs->wr_ops);
+ obj = bdrv_info_stats_bs(bs);
qlist_append_obj(devices, obj);
}
@@ -1834,9 +1874,12 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
cb, opaque);
if (ret) {
- /* Update stats even though technically transfer has not happened. */
- bs->wr_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
- bs->wr_ops ++;
+ /* Update stats even though technically transfer has not happened. */
+ bs->wr_bytes += (unsigned) nb_sectors * BDRV_SECTOR_SIZE;
+ bs->wr_ops ++;
+ if (bs->wr_highest_sector < sector_num + nb_sectors - 1) {
+ bs->wr_highest_sector = sector_num + nb_sectors - 1;
+ }
}
return ret;
diff --git a/block_int.h b/block_int.h
index a3afe63..1a7240c 100644
--- a/block_int.h
+++ b/block_int.h
@@ -167,6 +167,7 @@ struct BlockDriverState {
uint64_t wr_bytes;
uint64_t rd_ops;
uint64_t wr_ops;
+ uint64_t wr_highest_sector;
/* Whether the disk can expand beyond total_sectors */
int growable;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 17/18] qemu-img rebase: Fix output image corruption
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (15 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 16/18] block: Add wr_highest_sector blockstat Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 18/18] block: Release allocated options after bdrv_open Kevin Wolf
2010-05-03 13:01 ` [Qemu-devel] Re: [PULL 00/18] Block patches Anthony Liguori
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
qemu-img rebase must always give clusters in the COW file priority over those
in the backing file. As it failed to use number of non-allocated clusters but
assumed the maximum, it was possible that allocated clusters were taken from
the backing file instead, leading to a corrupted output image.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
qemu-img.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index c21d999..d3c30a7 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1136,7 +1136,7 @@ static int img_rebase(int argc, char **argv)
if (!unsafe) {
uint64_t num_sectors;
uint64_t sector;
- int n, n1;
+ int n;
uint8_t * buf_old;
uint8_t * buf_new;
@@ -1155,8 +1155,8 @@ static int img_rebase(int argc, char **argv)
}
/* If the cluster is allocated, we don't need to take action */
- if (bdrv_is_allocated(bs, sector, n, &n1)) {
- n = n1;
+ ret = bdrv_is_allocated(bs, sector, n, &n);
+ if (ret) {
continue;
}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] [PATCH 18/18] block: Release allocated options after bdrv_open
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (16 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 17/18] qemu-img rebase: Fix output image corruption Kevin Wolf
@ 2010-04-30 14:00 ` Kevin Wolf
2010-05-03 13:01 ` [Qemu-devel] Re: [PULL 00/18] Block patches Anthony Liguori
18 siblings, 0 replies; 20+ messages in thread
From: Kevin Wolf @ 2010-04-30 14:00 UTC (permalink / raw)
To: aliguori; +Cc: kwolf, qemu-devel
From: Jan Kiszka <jan.kiszka@siemens.com>
They aren't used afterwards nor supposed to be stored by a bdrv_create
handler.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/block.c b/block.c
index f463ec4..48305b7 100644
--- a/block.c
+++ b/block.c
@@ -540,6 +540,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
}
ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
+ free_option_parameters(options);
if (ret < 0) {
return ret;
}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [Qemu-devel] Re: [PULL 00/18] Block patches
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
` (17 preceding siblings ...)
2010-04-30 14:00 ` [Qemu-devel] [PATCH 18/18] block: Release allocated options after bdrv_open Kevin Wolf
@ 2010-05-03 13:01 ` Anthony Liguori
18 siblings, 0 replies; 20+ messages in thread
From: Anthony Liguori @ 2010-05-03 13:01 UTC (permalink / raw)
To: Kevin Wolf; +Cc: qemu-devel
On 04/30/2010 09:00 AM, Kevin Wolf wrote:
> Hi Anthony,
>
> this is the second part of the block patches in my queue that I promised in the
> pull request last week. I also included the high watermark patch even if it
> didn't sit on the list for a very long time - but the people that I expected to
> comment on it have already done so, either on the list or internally.
>
> Kevin
>
> The following changes since commit 9ed7b059ef776a3921cfd085e891f45076922542:
> Amit Shah (1):
> virtio-serial: Implement flow control for individual ports
>
> are available in the git repository at:
>
> git://repo.or.cz/qemu/kevin.git for-anthony
>
Pulled. Thanks.
Regards,
Anthony Liguori
> Christoph Hellwig (1):
> block: separate raw images from the file protocol
>
> Jan Kiszka (1):
> block: Release allocated options after bdrv_open
>
> Kevin Wolf (10):
> 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
> vmdk: Fix COW
> vmdk: Clean up backing file handling
> vmdk: Convert to bdrv_open
> qcow2: Remove abort on free_clusters failure
> block: Add wr_highest_sector blockstat
> qemu-img rebase: Fix output image corruption
>
> Stefan Hajnoczi (6):
> block: Set backing_hd to NULL after deleting it
> qcow2: Avoid shadowing variable in alloc_clusters_noref()
> raw-posix: Use pread/pwrite instead of lseek+read/write
> block: Cache total_sectors to reduce bdrv_getlength calls
> qemu-img: Add 'resize' command to grow/shrink disk images
> qcow2: Implement bdrv_truncate() for growing images
>
> Makefile.objs | 2 +-
> block.c | 384 ++++++++++++++++++++++++++++++++++--------------
> 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 | 67 ++++-----
> block/qcow2-cluster.c | 64 ++++----
> block/qcow2-refcount.c | 86 ++++++------
> block/qcow2-snapshot.c | 22 ++--
> block/qcow2.c | 110 +++++++++-----
> block/qcow2.h | 8 +-
> block/raw-posix.c | 62 +++------
> block/raw-win32.c | 16 +-
> block/raw.c | 144 ++++++++++++++++++
> block/vdi.c | 29 +---
> block/vmdk.c | 140 +++++-------------
> block/vpc.c | 32 ++---
> block/vvfat.c | 2 +-
> block_int.h | 6 +-
> qemu-img-cmds.hx | 6 +
> qemu-img.c | 104 +++++++++++++-
> qemu-img.texi | 12 ++
> 28 files changed, 843 insertions(+), 494 deletions(-)
> create mode 100644 block/raw.c
>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2010-05-03 13:01 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-30 14:00 [Qemu-devel] [PULL 00/18] Block patches Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 01/18] block: separate raw images from the file protocol Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 02/18] block: Split bdrv_open Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 03/18] block: Avoid forward declaration of bdrv_open_common Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 04/18] block: Open the underlying image file in generic code Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 05/18] block: bdrv_has_zero_init Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 06/18] vmdk: Fix COW Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 07/18] vmdk: Clean up backing file handling Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 08/18] vmdk: Convert to bdrv_open Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 09/18] block: Set backing_hd to NULL after deleting it Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 10/18] qcow2: Avoid shadowing variable in alloc_clusters_noref() Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 11/18] raw-posix: Use pread/pwrite instead of lseek+read/write Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 12/18] block: Cache total_sectors to reduce bdrv_getlength calls Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 13/18] qemu-img: Add 'resize' command to grow/shrink disk images Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 14/18] qcow2: Remove abort on free_clusters failure Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 15/18] qcow2: Implement bdrv_truncate() for growing images Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 16/18] block: Add wr_highest_sector blockstat Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 17/18] qemu-img rebase: Fix output image corruption Kevin Wolf
2010-04-30 14:00 ` [Qemu-devel] [PATCH 18/18] block: Release allocated options after bdrv_open Kevin Wolf
2010-05-03 13:01 ` [Qemu-devel] Re: [PULL 00/18] Block patches Anthony Liguori
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).