aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.objs2
-rw-r--r--block.c384
-rw-r--r--block.h2
-rw-r--r--block/blkdebug.c17
-rw-r--r--block/bochs.c2
-rw-r--r--block/cloop.c2
-rw-r--r--block/cow.c2
-rw-r--r--block/curl.c10
-rw-r--r--block/dmg.c2
-rw-r--r--block/nbd.c2
-rw-r--r--block/parallels.c2
-rw-r--r--block/qcow.c67
-rw-r--r--block/qcow2-cluster.c64
-rw-r--r--block/qcow2-refcount.c86
-rw-r--r--block/qcow2-snapshot.c22
-rw-r--r--block/qcow2.c110
-rw-r--r--block/qcow2.h8
-rw-r--r--block/raw-posix.c62
-rw-r--r--block/raw-win32.c16
-rw-r--r--block/raw.c144
-rw-r--r--block/vdi.c29
-rw-r--r--block/vmdk.c140
-rw-r--r--block/vpc.c32
-rw-r--r--block/vvfat.c2
-rw-r--r--block_int.h6
-rw-r--r--qemu-img-cmds.hx6
-rw-r--r--qemu-img.c104
-rw-r--r--qemu-img.texi12
28 files changed, 843 insertions, 494 deletions
diff --git a/Makefile.objs b/Makefile.objs
index 1c7c64b1d8..4f65bfbae5 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 7974215ea4..48305b7d7c 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;
@@ -253,14 +288,21 @@ 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))
- 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 +317,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 +339,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);
@@ -331,6 +352,118 @@ 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
+ */
+static int bdrv_open_common(BlockDriverState *bs, const char *filename,
+ int flags, BlockDriver *drv)
+{
+ int ret, open_flags;
+
+ assert(drv != NULL);
+
+ bs->file = NULL;
+ bs->total_sectors = 0;
+ 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;
+ }
+
+ /* 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;
+ }
+
+ bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
+
+ ret = refresh_total_sectors(bs, bs->total_sectors);
+ if (ret < 0) {
+ goto free_and_fail;
+ }
+
+#ifndef _WIN32
+ if (bs->is_temporary) {
+ unlink(filename);
+ }
+#endif
+ 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;
+ return ret;
+}
+
+/*
+ * Opens a file using a protocol (file, host_device, nbd, ...)
+ */
int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
{
BlockDriverState *bs;
@@ -343,7 +476,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;
@@ -353,19 +486,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;
@@ -373,6 +500,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 */
@@ -411,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;
}
@@ -420,66 +550,28 @@ 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_hdev_driver(filename);
- if (!drv) {
- drv = find_image_format(filename);
- }
+ drv = find_image_format(filename);
}
if (!drv) {
ret = -ENOENT;
goto unlink_and_fail;
}
- if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
- ret = -ENOTSUP;
- goto unlink_and_fail;
- }
- 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);
+ /* Open the image */
+ ret = bdrv_open_common(bs, filename, flags, drv);
if (ret < 0) {
- goto free_and_fail;
+ goto unlink_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
+ /* If there is a backing file, use it */
if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
- /* if there is a backing file, use it */
+ 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);
@@ -487,9 +579,10 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
back_drv = bdrv_find_format(bs->backing_format);
/* backing files always opened read-only */
- open_flags &= ~BDRV_O_RDWR;
+ back_flags =
+ flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
- ret = bdrv_open(bs->backing_hd, backing_filename, open_flags, back_drv);
+ ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv);
if (ret < 0) {
bdrv_close(bs);
return ret;
@@ -508,23 +601,23 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
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)
+ if (bs->is_temporary) {
unlink(filename);
+ }
return ret;
}
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
@@ -535,6 +628,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)
@@ -550,6 +647,10 @@ void bdrv_delete(BlockDriverState *bs)
}
bdrv_close(bs);
+ if (bs->file != NULL) {
+ bdrv_delete(bs->file);
+ }
+
qemu_free(bs);
}
@@ -780,6 +881,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);
}
@@ -883,13 +988,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;
}
/**
@@ -900,8 +1010,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);
@@ -1208,6 +1322,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,
@@ -1408,6 +1535,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
*
@@ -1422,19 +1578,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)
{
@@ -1445,15 +1616,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);
}
@@ -1712,9 +1875,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.h b/block.h
index 05ad572d8d..f87d24e5c8 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);
@@ -121,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/block/blkdebug.c b/block/blkdebug.c
index 643c3978f8..bb4a91abc7 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 fb83594dba..e952670cd1 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 06c687e690..e4f995b5d6 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 97e9745fc9..fde066ec32 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 2cf72cb4e8..b944740fb9 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 f4c01c76b6..d5c1a687e4 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 7bac38d086..a1ec123a63 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 41b3a7c9db..b2171016f1 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 c619984a03..2883c40f87 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 639e05e989..c11680d12a 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 47c9978845..744107cd1d 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;
@@ -554,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
@@ -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,14 +632,13 @@ 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));
- abort();
+ /* TODO Remember the clusters to free them later and avoid leaking */
}
}
@@ -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 8ddaea23b8..2a21c1723b 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 5436fec56d..21ed6f8753 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;
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);
@@ -192,8 +188,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, 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)
@@ -202,7 +197,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 +230,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 +249,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 +423,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 +443,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 +459,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 +609,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 +657,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 +726,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 +735,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 +782,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 +824,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 +839,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;
@@ -858,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,
@@ -872,9 +901,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 +946,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 +959,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 +994,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 +1014,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 +1029,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;
@@ -1060,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 de9397a3d3..01053b79d9 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);
@@ -184,7 +190,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 4cda9c1f85..7541ed2abe 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;
@@ -768,11 +739,12 @@ 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,
+ .bdrv_file_open = raw_open,
.bdrv_read = raw_read,
.bdrv_write = raw_write,
.bdrv_close = raw_close,
@@ -1026,9 +998,10 @@ 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,
+ .bdrv_file_open = hdev_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
.create_options = raw_create_options,
@@ -1140,9 +1113,10 @@ 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,
+ .bdrv_file_open = floppy_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
.create_options = raw_create_options,
@@ -1239,9 +1213,10 @@ 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,
+ .bdrv_file_open = cdrom_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
.create_options = raw_create_options,
@@ -1361,9 +1336,10 @@ 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,
+ .bdrv_file_open = cdrom_open,
.bdrv_close = raw_close,
.bdrv_create = hdev_create,
.create_options = raw_create_options,
@@ -1385,13 +1361,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 +1378,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 526764f62f..745bbde673 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -238,10 +238,11 @@ 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_file_open = raw_open,
.bdrv_close = raw_close,
.bdrv_create = raw_create,
.bdrv_flush = raw_flush,
@@ -395,9 +396,10 @@ 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,
+ .bdrv_file_open = hdev_open,
.bdrv_close = raw_close,
.bdrv_flush = raw_flush,
@@ -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 0000000000..4406b8c06b
--- /dev/null
+++ b/block/raw.c
@@ -0,0 +1,144 @@
+
+#include "qemu-common.h"
+#include "block_int.h"
+#include "module.h"
+
+static int raw_open(BlockDriverState *bs, int flags)
+{
+ bs->sg = bs->file->sg;
+ return 0;
+}
+
+static int raw_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int 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)
+{
+ 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)
+{
+ 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)
+{
+ return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
+}
+
+static void raw_close(BlockDriverState *bs)
+{
+}
+
+static void raw_flush(BlockDriverState *bs)
+{
+ bdrv_flush(bs->file);
+}
+
+static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ return bdrv_aio_flush(bs->file, cb, opaque);
+}
+
+static int64_t raw_getlength(BlockDriverState *bs)
+{
+ return bdrv_getlength(bs->file);
+}
+
+static int raw_truncate(BlockDriverState *bs, int64_t offset)
+{
+ return bdrv_truncate(bs->file, 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)
+{
+ return bdrv_is_inserted(bs->file);
+}
+
+static int raw_eject(BlockDriverState *bs, int eject_flag)
+{
+ return bdrv_eject(bs->file, eject_flag);
+}
+
+static int raw_set_locked(BlockDriverState *bs, int locked)
+{
+ bdrv_set_locked(bs->file, locked);
+ return 0;
+}
+
+static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+{
+ return bdrv_ioctl(bs->file, req, buf);
+}
+
+static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
+ unsigned long int req, void *buf,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ return bdrv_aio_ioctl(bs->file, 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",
+
+ /* It's really 0, but we need to make qemu_malloc() happy */
+ .instance_size = 1,
+
+ .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);
diff --git a/block/vdi.c b/block/vdi.c
index c91961acb4..1d257b4838 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 6fdea1d305..e659908028 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 {
@@ -87,14 +86,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;
@@ -117,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) {
@@ -145,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");
@@ -161,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;
}
@@ -346,27 +335,17 @@ 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)
+ if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE)
return -1;
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)
@@ -375,51 +354,25 @@ 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;
}
-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;
- 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;
- 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;
@@ -431,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);
@@ -444,13 +397,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);
@@ -461,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]);
@@ -469,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]);
@@ -482,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;
}
@@ -492,30 +439,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(bs->file, cluster_offset, whole_grain,
+ s->cluster_sectors);
+ if (ret < 0) {
+ return -1;
}
}
return 0;
@@ -526,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;
}
@@ -580,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;
@@ -593,18 +538,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 >>= 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;
- }
+ 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);
+ 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
@@ -666,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;
@@ -702,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 */
@@ -879,15 +821,11 @@ 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);
}
static void vmdk_flush(BlockDriverState *bs)
{
- BDRVVmdkState *s = bs->opaque;
- bdrv_flush(s->hd);
+ bdrv_flush(bs->file);
}
@@ -914,7 +852,7 @@ static BlockDriver bdrv_vmdk = {
.format_name = "vmdk",
.instance_size = sizeof(BDRVVmdkState),
.bdrv_probe = vmdk_probe,
- .bdrv_open = vmdk_open,
+ .bdrv_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 950ad58b3b..f94e4698b7 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 66259b48d5..ce16bbd8c4 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 d4067ff726..1a7240c582 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;
@@ -164,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;
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index f96876ae3b..c079019048 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 7203b8bc72..d3c30a74f3 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");
@@ -1134,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;
@@ -1153,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;
}
@@ -1223,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 ac978542c2..c1b1f2717e 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: