Block patches
Subsystems (2)
Hi Anthony,
this is the second part of the block patches in my queue that I promised in the pull request last week. I also included the high watermark patch even if it didn't sit on the list for a very long time - but the people that I expected to comment on it have already done so, either on the list or internally.
Kevin
The following changes since commit 9ed7b059ef776a3921cfd085e891f45076922542:
Amit Shah (1):
virtio-serial: Implement flow control for individual ports
are available in the git repository at:
git://repo.or.cz/qemu/kevin.git for-anthony
Christoph Hellwig (1):
block: separate raw images from the file protocol
Jan Kiszka (1):
block: Release allocated options after bdrv_open
Kevin Wolf (10):
block: Split bdrv_open
block: Avoid forward declaration of bdrv_open_common
block: Open the underlying image file in generic code
block: bdrv_has_zero_init
vmdk: Fix COW
vmdk: Clean up backing file handling
vmdk: Convert to bdrv_open
qcow2: Remove abort on free_clusters failure
block: Add wr_highest_sector blockstat qemu-img rebase: Fix output image corruption
Stefan Hajnoczi (6):
block: Set backing_hd to NULL after deleting it
qcow2: Avoid shadowing variable in alloc_clusters_noref()
raw-posix: Use pread/pwrite instead of lseek+read/write
block: Cache total_sectors to reduce bdrv_getlength calls
qemu-img: Add 'resize' command to grow/shrink disk images
qcow2: Implement bdrv_truncate() for growing images
Makefile.objs | 2 +- block.c | 384 ++++++++++++++++++++++++++++++++++-------------- block.h | 2 + block/blkdebug.c | 17 +-- block/bochs.c | 2 +- block/cloop.c | 2 +- block/cow.c | 2 +- block/curl.c | 10 +- block/dmg.c | 2 +- block/nbd.c | 2 +- block/parallels.c | 2 +- block/qcow.c | 67 ++++----- block/qcow2-cluster.c | 64 ++++---- block/qcow2-refcount.c | 86 ++++++------ block/qcow2-snapshot.c | 22 ++-- block/qcow2.c | 110 +++++++++----- block/qcow2.h | 8 +- block/raw-posix.c | 62 +++------ block/raw-win32.c | 16 +- block/raw.c | 144 ++++++++++++++++++ block/vdi.c | 29 +--- block/vmdk.c | 140 +++++------------- block/vpc.c | 32 ++--- block/vvfat.c | 2 +- block_int.h | 6 +- qemu-img-cmds.hx | 6 + qemu-img.c | 104 +++++++++++++- qemu-img.texi | 12 ++ 28 files changed, 843 insertions(+), 494 deletions(-) create mode 100644 block/raw.c
PATCH 1/18 block: separate raw images from the file protocol
From: Christoph Hellwig <[email protected]>
We're running into various problems because the "raw" file access, which is used internally by the various image formats is entangled with the "raw" image format, which maps the VM view 1:1 to a file system.
This patch renames the raw file backends to the file protocol which is treated like other protocols (e.g. nbd and http) and adds a new "raw" image format which is just a wrapper around calls to the underlying protocol.
The patch is surprisingly simple, besides changing the probing logical in block.c to only look for image formats when using bdrv_open and renaming of the old raw protocols to file there's almost nothing in there.
For creating images, a new bdrv_create_file is introduced which guesses the protocol to use. This allows using qemu-img create -f raw (or just using the default) for both files and host devices. Converting the other format drivers to use this function to create their images is left for later patches.
The only issues still open are in the handling of the host devices. Firstly in current qemu we can specifiy the host* format names on various command line acceping images, but the new code can't do that without adding some translation. Second the layering breaks the no_zero_init flag in the BlockDriver used by qemu-img. I'm not happy how this is done per-driver instead of per-state so I'll prepare a separate patch to clean this up.
There's some more cleanup opportunity after this patch, e.g. using separate lists and registration functions for image formats vs protocols and maybe even host drivers, but this can be done at a later stage.
Also there's a check for protocol in bdrv_open for the BDRV_O_SNAPSHOT case that I don't quite understand, but which I fear won't work as expected - possibly even before this patch.
Note that this patch requires various recent block patches from Kevin and me, which should all be in his block queue.
--- Makefile.objs | 2 +- block.c | 74 ++++++++++++++--------- block.h | 1 + block/raw-posix.c | 15 +++-- block/raw-win32.c | 12 ++-- block/raw.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 235 insertions(+), 40 deletions(-) create mode 100644 block/raw.c
Makefile.objs +1 -1
@@ -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
block.c +45 -29
118 lines not on this page · raw message
block.h +1 -0
@@ -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);
block/raw-posix.c +10 -5
@@ -768,8 +768,9 @@ static QEMUOptionParameter raw_create_options[] = { { NULL } }; -static BlockDriver bdrv_raw = { - .format_name ="raw" , +static BlockDriver bdrv_file = { + .format_name ="file" , + .protocol_name ="file" , .instance_size =sizeof (BDRVRawState), .bdrv_probe =NULL ,/* no probe for protocols */ .bdrv_open = raw_open,
@@ -1026,6 +1027,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)static BlockDriver bdrv_host_device = { .format_name ="host_device" , + .protocol_name ="host_device" , .instance_size =sizeof (BDRVRawState), .bdrv_probe_device = hdev_probe_device, .bdrv_open = hdev_open,
@@ -1140,6 +1142,7 @@ static int floppy_eject(BlockDriverState *bs, int eject_flag)static BlockDriver bdrv_host_floppy = { .format_name ="host_floppy" , + .protocol_name ="host_floppy" , .instance_size =sizeof (BDRVRawState), .bdrv_probe_device = floppy_probe_device, .bdrv_open = floppy_open,
@@ -1239,6 +1242,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)static BlockDriver bdrv_host_cdrom = { .format_name ="host_cdrom" , + .protocol_name ="host_cdrom" , .instance_size =sizeof (BDRVRawState), .bdrv_probe_device = cdrom_probe_device, .bdrv_open = cdrom_open,
@@ -1361,6 +1365,7 @@ static int cdrom_set_locked(BlockDriverState *bs, int locked)static BlockDriver bdrv_host_cdrom = { .format_name ="host_cdrom" , + .protocol_name ="host_cdrom" , .instance_size =sizeof (BDRVRawState), .bdrv_probe_device = cdrom_probe_device, .bdrv_open = cdrom_open,
@@ -1385,13 +1390,13 @@ static BlockDriver bdrv_host_cdrom = { };#endif /* __FreeBSD__ */ -static void bdrv_raw_init (void ) +static void bdrv_file_init (void ) {/* * Register all the drivers. Note that order is important, the driver * registered last will get probed first. */ -bdrv_register (&bdrv_raw); +bdrv_register (&bdrv_file);bdrv_register (&bdrv_host_device);#ifdef __linux__bdrv_register (&bdrv_host_floppy);
@@ -1402,4 +1407,4 @@ static void bdrv_raw_init(void)#endif } -block_init (bdrv_raw_init); +block_init (bdrv_file_init);
block/raw-win32.c +7 -5
@@ -238,8 +238,9 @@ static QEMUOptionParameter raw_create_options[] = { { NULL } }; -static BlockDriver bdrv_raw = { - .format_name ="raw" , +static BlockDriver bdrv_file = { + .format_name ="file" , + .protocol_name ="file" , .instance_size =sizeof (BDRVRawState), .bdrv_open = raw_open, .bdrv_close = raw_close,
@@ -395,6 +396,7 @@ static int raw_set_locked(BlockDriverState *bs, int locked)static BlockDriver bdrv_host_device = { .format_name ="host_device" , + .protocol_name ="host_device" , .instance_size =sizeof (BDRVRawState), .bdrv_probe_device = hdev_probe_device, .bdrv_open = hdev_open,
@@ -406,10 +408,10 @@ static BlockDriver bdrv_host_device = { .bdrv_getlength = raw_getlength, }; -static void bdrv_raw_init (void ) +static void bdrv_file_init (void ) { -bdrv_register (&bdrv_raw); +bdrv_register (&bdrv_file);bdrv_register (&bdrv_host_device); } -block_init (bdrv_raw_init); +block_init (bdrv_file_init);
block/raw.c new file +171 -0
171 lines not on this page · raw message
Signature · 1 line
1.6.6.1
PATCH 2/18 block: Split bdrv_open
In reply to Kevin Wolfbdrv_open contains quite some code that is only useful for opening images (as opposed to opening files by a protocol), for example snapshots.
This patch splits the code so that we have bdrv_open_file() for files (uses protocols), bdrv_open() for images (uses format drivers) and bdrv_open_common() for the code common for opening both images and files.
--- block.c | 135 ++++++++++++++++++++++++++++++++++++++++----------------------- 1 files changed, 86 insertions(+), 49 deletions(-)
block.c +86 -49
@@ -42,6 +42,9 @@#include <windows.h> #endif +static int bdrv_open_common (BlockDriverState *bs,const char *filename, +int flags,BlockDriver *drv); +static BlockDriverAIOCB *bdrv_aio_readv_em (BlockDriverState *bs,int64_t sector_num,QEMUIOVector *qiov,int nb_sectors,BlockDriverCompletionFunc *cb,void *opaque);
@@ -350,6 +353,9 @@ static BlockDriver *find_image_format(const char *filename)return drv; } +/* +* Opens a file using a protocol (file, host_device, nbd, ...) +*/ int bdrv_file_open (BlockDriverState **pbs,const char *filename,int flags) {BlockDriverState *bs;
@@ -362,7 +368,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags) } bs =bdrv_new ("" ); - ret =bdrv_open (bs, filename, flags, drv); + ret =bdrv_open_common (bs, filename, flags, drv);if (ret <0 ) {bdrv_delete (bs);return ret;
@@ -372,19 +378,13 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)return 0 ; } +/* +* Opens a disk image (raw, qcow2, vmdk, ...) +*/ int bdrv_open (BlockDriverState *bs,const char *filename,int flags,BlockDriver *drv) { -int ret, open_flags; -char tmp_filename[PATH_MAX ]; -char backing_filename[PATH_MAX ]; - - bs->is_temporary =0 ; - bs->encrypted =0 ; - bs->valid_key =0 ; - bs->open_flags = flags; -/* buffer_alignment defaulted to 512, drivers can change this value */ - bs->buffer_alignment =512 ; +int ret;if (flags &BDRV_O_SNAPSHOT ) {BlockDriverState *bs1;
@@ -392,6 +392,8 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,int is_protocol =0 ;BlockDriver *bdrv_qcow2;QEMUOptionParameter *options; +char tmp_filename[PATH_MAX ]; +char backing_filename[PATH_MAX ];/* if snapshot, we create a temporary backing file and open it instead of opening 'filename' directly */
@@ -439,8 +441,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, bs->is_temporary =1 ; } -pstrcpy (bs->filename,sizeof (bs->filename), filename); - +/* Find the right image format driver */ if (!drv) { drv =find_image_format (filename); }
@@ -449,11 +450,81 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, ret = -ENOENT ; goto unlink_and_fail; } -if (use_bdrv_whitelist && !bdrv_is_whitelisted (drv)) { - ret = -ENOTSUP ; + +/* Open the image */ + ret =bdrv_open_common (bs, filename, flags, drv); +if (ret <0 ) { goto unlink_and_fail; } +/* If there is a backing file, use it */ +if ((flags &BDRV_O_NO_BACKING ) ==0 && bs->backing_file[0 ] !='\0' ) { +char backing_filename[PATH_MAX ]; +int back_flags; +BlockDriver *back_drv =NULL ; + + bs->backing_hd =bdrv_new ("" ); +path_combine (backing_filename,sizeof (backing_filename), + filename, bs->backing_file); +if (bs->backing_format[0 ] !='\0' ) + back_drv =bdrv_find_format (bs->backing_format); + +/* backing files always opened read-only */ + back_flags = + flags & ~(BDRV_O_RDWR |BDRV_O_SNAPSHOT |BDRV_O_NO_BACKING ); + + ret =bdrv_open (bs->backing_hd, backing_filename, back_flags, back_drv); +if (ret <0 ) { +bdrv_close (bs); +return ret; + } +if (bs->is_temporary) { + bs->backing_hd->keep_read_only = !(flags &BDRV_O_RDWR ); + }else { +/* base image inherits from "parent" */ + bs->backing_hd->keep_read_only = bs->keep_read_only; + } + } + +if (!bdrv_key_required (bs)) { +/* call the change callback */ + bs->media_changed =1 ; +if (bs->change_cb) + bs->change_cb (bs->change_opaque); + } + +return 0 ; + +unlink_and_fail: +if (bs->is_temporary) { +unlink (filename); + } +return ret; +} + +/* +* Common part for opening disk images and files +*/ +static int bdrv_open_common (BlockDriverState *bs,const char *filename, +int flags,BlockDriver *drv) +{ +int ret, open_flags; + +assert (drv !=NULL ); + + bs->is_temporary =0 ; + bs->encrypted =0 ; + bs->valid_key =0 ; + bs->open_flags = flags; +/* buffer_alignment defaulted to 512, drivers can change this value */ + bs->buffer_alignment =512 ; + +pstrcpy (bs->filename,sizeof (bs->filename), filename); + +if (use_bdrv_whitelist && !bdrv_is_whitelisted (drv)) { +return -ENOTSUP ; + } + bs->drv = drv; bs->opaque =qemu_mallocz (drv->instance_size);
@@ -493,46 +564,12 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, unlink(filename); }#endif -if ((flags &BDRV_O_NO_BACKING ) ==0 && bs->backing_file[0 ] !='\0' ) { -/* if there is a backing file, use it */ -BlockDriver *back_drv =NULL ; - bs->backing_hd =bdrv_new ("" ); -path_combine (backing_filename,sizeof (backing_filename), - filename, bs->backing_file); -if (bs->backing_format[0 ] !='\0' ) - back_drv =bdrv_find_format (bs->backing_format); - -/* backing files always opened read-only */ - open_flags &= ~BDRV_O_RDWR ; - - ret =bdrv_open (bs->backing_hd, backing_filename, open_flags, back_drv); -if (ret <0 ) { -bdrv_close (bs); -return ret; - } -if (bs->is_temporary) { - bs->backing_hd->keep_read_only = !(flags &BDRV_O_RDWR ); - }else { -/* base image inherits from "parent" */ - bs->backing_hd->keep_read_only = bs->keep_read_only; - } - } - -if (!bdrv_key_required (bs)) { -/* call the change callback */ - bs->media_changed =1 ; -if (bs->change_cb) - bs->change_cb (bs->change_opaque); - }return 0 ; free_and_fail:qemu_free (bs->opaque); bs->opaque =NULL ; bs->drv =NULL ; -unlink_and_fail: -if (bs->is_temporary) -unlink (filename);return ret; }
Signature · 1 line
1.6.6.1
PATCH 3/18 block: Avoid forward declaration of bdrv_open_common
In reply to Kevin WolfMove bdrv_open_common so it's defined before its callers and remove the forward declaration.
--- block.c | 145 +++++++++++++++++++++++++++++++-------------------------------- 1 files changed, 71 insertions(+), 74 deletions(-)
block.c +71 -74
@@ -42,9 +42,6 @@#include <windows.h> #endif -static int bdrv_open_common (BlockDriverState *bs,const char *filename, -int flags,BlockDriver *drv); -static BlockDriverAIOCB *bdrv_aio_readv_em (BlockDriverState *bs,int64_t sector_num,QEMUIOVector *qiov,int nb_sectors,BlockDriverCompletionFunc *cb,void *opaque);
@@ -354,6 +351,77 @@ static BlockDriver *find_image_format(const char *filename) }/* +* Common part for opening disk images and files +*/ +static int bdrv_open_common (BlockDriverState *bs,const char *filename, +int flags,BlockDriver *drv) +{ +int ret, open_flags; + +assert (drv !=NULL ); + + bs->is_temporary =0 ; + bs->encrypted =0 ; + bs->valid_key =0 ; + bs->open_flags = flags; +/* buffer_alignment defaulted to 512, drivers can change this value */ + bs->buffer_alignment =512 ; + +pstrcpy (bs->filename,sizeof (bs->filename), filename); + +if (use_bdrv_whitelist && !bdrv_is_whitelisted (drv)) { +return -ENOTSUP ; + } + + bs->drv = drv; + bs->opaque =qemu_mallocz (drv->instance_size); + +/* +* Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a +* write cache to the guest. We do need the fdatasync to flush +* out transactions for block allocations, and we maybe have a +* volatile write cache in our backing device to deal with. +*/ +if (flags & (BDRV_O_CACHE_WB |BDRV_O_NOCACHE )) + bs->enable_write_cache =1 ; + +/* +* Clear flags that are internal to the block layer before opening the +* image. +*/ + open_flags = flags & ~(BDRV_O_SNAPSHOT |BDRV_O_NO_BACKING ); + +/* +* Snapshots should be writeable. +*/ +if (bs->is_temporary) { + open_flags |=BDRV_O_RDWR ; + } + + ret = drv->bdrv_open (bs, filename, open_flags); +if (ret <0 ) { + goto free_and_fail; + } + + bs->keep_read_only = bs->read_only = !(open_flags &BDRV_O_RDWR ); +if (drv->bdrv_getlength) { + bs->total_sectors =bdrv_getlength (bs) >>BDRV_SECTOR_BITS ; + } +#ifndef _WIN32 +if (bs->is_temporary) { +unlink (filename); + } +#endif +return 0 ; + +free_and_fail: +qemu_free (bs->opaque); + bs->opaque =NULL ; + bs->drv =NULL ; +return ret; +} + +/* * Opens a file using a protocol (file, host_device, nbd, ...) */ int bdrv_file_open (BlockDriverState **pbs,const char *filename,int flags)
@@ -502,77 +570,6 @@ unlink_and_fail:return ret; } -/* -* Common part for opening disk images and files -*/ -static int bdrv_open_common (BlockDriverState *bs,const char *filename, -int flags,BlockDriver *drv) -{ -int ret, open_flags; - -assert (drv !=NULL ); - - bs->is_temporary =0 ; - bs->encrypted =0 ; - bs->valid_key =0 ; - bs->open_flags = flags; -/* buffer_alignment defaulted to 512, drivers can change this value */ - bs->buffer_alignment =512 ; - -pstrcpy (bs->filename,sizeof (bs->filename), filename); - -if (use_bdrv_whitelist && !bdrv_is_whitelisted (drv)) { -return -ENOTSUP ; - } - - bs->drv = drv; - bs->opaque =qemu_mallocz (drv->instance_size); - -/* -* Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a -* write cache to the guest. We do need the fdatasync to flush -* out transactions for block allocations, and we maybe have a -* volatile write cache in our backing device to deal with. -*/ -if (flags & (BDRV_O_CACHE_WB |BDRV_O_NOCACHE )) - bs->enable_write_cache =1 ; - -/* -* Clear flags that are internal to the block layer before opening the -* image. -*/ - open_flags = flags & ~(BDRV_O_SNAPSHOT |BDRV_O_NO_BACKING ); - -/* -* Snapshots should be writeable. -*/ -if (bs->is_temporary) { - open_flags |=BDRV_O_RDWR ; - } - - ret = drv->bdrv_open (bs, filename, open_flags); -if (ret <0 ) { - goto free_and_fail; - } - - bs->keep_read_only = bs->read_only = !(open_flags &BDRV_O_RDWR ); -if (drv->bdrv_getlength) { - bs->total_sectors =bdrv_getlength (bs) >>BDRV_SECTOR_BITS ; - } -#ifndef _WIN32 -if (bs->is_temporary) { -unlink (filename); - } -#endif -return 0 ; - -free_and_fail: -qemu_free (bs->opaque); - bs->opaque =NULL ; - bs->drv =NULL ; -return ret; -} -void bdrv_close (BlockDriverState *bs) {if (bs->drv) {
Signature · 1 line
1.6.6.1
PATCH 4/18 block: Open the underlying image file in generic code
In reply to Kevin WolfFormat drivers shouldn't need to bother with things like file names, but rather just get an open BlockDriverState for the underlying protocol. This patch introduces this behaviour for bdrv_open implementation. For protocols which need to access the filename to open their file/device/connection/... a new callback bdrv_file_open is introduced which doesn't get an underlying file opened.
For now, also some of the more obscure formats use bdrv_file_open because they open() the file themselves instead of using the block.c functions. They need to be fixed in later patches.
--- block.c | 26 +++++++++++++++- block/blkdebug.c | 17 +++------ block/bochs.c | 2 +- block/cloop.c | 2 +- block/cow.c | 2 +- block/curl.c | 10 +++--- block/dmg.c | 2 +- block/nbd.c | 2 +- block/parallels.c | 2 +- block/qcow.c | 67 ++++++++++++++++++---------------------- block/qcow2-cluster.c | 64 ++++++++++++++++++++------------------ block/qcow2-refcount.c | 80 ++++++++++++++++++++++++------------------------ block/qcow2-snapshot.c | 22 ++++++------ block/qcow2.c | 66 +++++++++++++++++----------------------- block/qcow2.h | 2 +- block/raw-posix.c | 10 +++--- block/raw-win32.c | 4 +- block/raw.c | 63 +++++++++++--------------------------- block/vdi.c | 29 +++++------------ block/vmdk.c | 2 +- block/vpc.c | 32 +++++++------------ block/vvfat.c | 2 +- block_int.h | 5 ++- 23 files changed, 237 insertions(+), 276 deletions(-)
block.c +25 -1
@@ -288,6 +288,8 @@ static BlockDriver *find_protocol(const char *filename)int len;const char *p; +/* TODO Drivers without bdrv_file_open must be specified explicitly */ +#ifdef _WIN32if (is_windows_drive (filename) ||is_windows_drive_prefix (filename))
@@ -360,6 +362,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,assert (drv !=NULL ); + bs->file =NULL ; bs->is_temporary =0 ; bs->encrypted =0 ; bs->valid_key =0 ;
@@ -398,7 +401,16 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename, open_flags |=BDRV_O_RDWR ; } - ret = drv->bdrv_open (bs, filename, open_flags); +/* Open the image, either directly or using a protocol */ +if (drv->bdrv_file_open) { + ret = drv->bdrv_file_open (bs, filename, open_flags); + }else { + ret =bdrv_file_open (&bs->file, filename, open_flags); +if (ret >=0 ) { + ret = drv->bdrv_open (bs, open_flags); + } + } +if (ret <0 ) { goto free_and_fail; }
@@ -415,6 +427,10 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,return 0 ; free_and_fail: +if (bs->file) { +bdrv_delete (bs->file); + bs->file =NULL ; + }qemu_free (bs->opaque); bs->opaque =NULL ; bs->drv =NULL ;
@@ -585,6 +601,10 @@ void bdrv_close(BlockDriverState *bs) bs->opaque =NULL ; bs->drv =NULL ; +if (bs->file !=NULL ) { +bdrv_close (bs->file); + } +/* call the change callback */ bs->media_changed =1 ;if (bs->change_cb)
@@ -600,6 +620,10 @@ void bdrv_delete(BlockDriverState *bs) }bdrv_close (bs); +if (bs->file !=NULL ) { +bdrv_delete (bs->file); + } +qemu_free (bs); }
block/blkdebug.c +6 -11
@@ -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,
block/bochs.c +1 -1
@@ -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, };
block/cloop.c +1 -1
@@ -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, };
block/cow.c +1 -1
@@ -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,
block/curl.c +5 -5
@@ -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,
block/dmg.c +1 -1
@@ -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, };
block/nbd.c +1 -1
@@ -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,
block/parallels.c +1 -1
@@ -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, };
block/qcow.c +30 -37
220 lines not on this page · raw message
block/qcow2-cluster.c +33 -31
188 lines not on this page · raw message
block/qcow2-refcount.c +40 -40
258 lines not on this page · raw message
block/qcow2-snapshot.c +11 -11
@@ -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++) {
block/qcow2.c +28 -38
221 lines not on this page · raw message
block/qcow2.h +1 -1
@@ -184,7 +184,7 @@ int qcow2_check_refcounts(BlockDriverState *bs);/* qcow2-cluster.c functions */ int qcow2_grow_l1_table (BlockDriverState *bs,int min_size);void qcow2_l2_cache_reset (BlockDriverState *bs); -int qcow2_decompress_cluster (BDRVQcowState *s,uint64_t cluster_offset); +int qcow2_decompress_cluster (BlockDriverState *bs,uint64_t cluster_offset); void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num, uint8_t *out_buf, const uint8_t *in_buf, int nb_sectors, int enc,
block/raw-posix.c +5 -5
@@ -773,7 +773,7 @@ static BlockDriver bdrv_file = { .protocol_name = "file", .instance_size = sizeof(BDRVRawState), .bdrv_probe = NULL, /* no probe for protocols */ - .bdrv_open = raw_open, + .bdrv_file_open = raw_open, .bdrv_read = raw_read, .bdrv_write = raw_write, .bdrv_close = raw_close,
@@ -1030,7 +1030,7 @@ static BlockDriver bdrv_host_device = { .protocol_name = "host_device", .instance_size = sizeof(BDRVRawState), .bdrv_probe_device = hdev_probe_device, - .bdrv_open = hdev_open, + .bdrv_file_open = hdev_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, .create_options = raw_create_options,
@@ -1145,7 +1145,7 @@ static BlockDriver bdrv_host_floppy = { .protocol_name = "host_floppy", .instance_size = sizeof(BDRVRawState), .bdrv_probe_device = floppy_probe_device, - .bdrv_open = floppy_open, + .bdrv_file_open = floppy_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, .create_options = raw_create_options,
@@ -1245,7 +1245,7 @@ static BlockDriver bdrv_host_cdrom = { .protocol_name = "host_cdrom", .instance_size = sizeof(BDRVRawState), .bdrv_probe_device = cdrom_probe_device, - .bdrv_open = cdrom_open, + .bdrv_file_open = cdrom_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, .create_options = raw_create_options,
@@ -1368,7 +1368,7 @@ static BlockDriver bdrv_host_cdrom = { .protocol_name = "host_cdrom", .instance_size = sizeof(BDRVRawState), .bdrv_probe_device = cdrom_probe_device, - .bdrv_open = cdrom_open, + .bdrv_file_open = cdrom_open, .bdrv_close = raw_close, .bdrv_create = hdev_create, .create_options = raw_create_options,
block/raw-win32.c +2 -2
@@ -242,7 +242,7 @@ static BlockDriver bdrv_file = { .format_name = "file", .protocol_name = "file", .instance_size = sizeof(BDRVRawState), - .bdrv_open = raw_open, + .bdrv_file_open = raw_open, .bdrv_close = raw_close, .bdrv_create = raw_create, .bdrv_flush = raw_flush,
@@ -399,7 +399,7 @@ static BlockDriver bdrv_host_device = { .protocol_name = "host_device", .instance_size = sizeof(BDRVRawState), .bdrv_probe_device = hdev_probe_device, - .bdrv_open = hdev_open, + .bdrv_file_open = hdev_open, .bdrv_close = raw_close, .bdrv_flush = raw_flush,
block/raw.c +18 -45
144 lines not on this page · raw message
block/vdi.c +9 -20
@@ -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); }
block/vmdk.c +1 -1
@@ -914,7 +914,7 @@ static BlockDriver bdrv_vmdk = { .format_name = "vmdk", .instance_size = sizeof(BDRVVmdkState), .bdrv_probe = vmdk_probe, - .bdrv_open = vmdk_open, + .bdrv_file_open = vmdk_open, .bdrv_read = vmdk_read, .bdrv_write = vmdk_write, .bdrv_close = vmdk_close,
block/vpc.c +12 -20
@@ -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[] = {
block/vvfat.c +1 -1
@@ -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,
block_int.h +4 -1
@@ -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;
Signature · 1 line
1.6.6.1
PATCH 5/18 block: bdrv_has_zero_init
In reply to Kevin WolfThis fixes the problem that qemu-img's use of no_zero_init only considered the no_zero_init flag of the format driver, but not of the underlying protocols.
Between the raw/file split and this fix, converting to host devices is broken.
--- block.c | 13 +++++++++++++ block.h | 1 + qemu-img.c | 6 ++++-- 3 files changed, 18 insertions(+), 2 deletions(-)
block.c +13 -0
@@ -1282,6 +1282,19 @@ void bdrv_flush_all(void) } } +int bdrv_has_zero_init (BlockDriverState *bs) +{ +assert (bs->drv); + +if (bs->drv->no_zero_init) { +return 0 ; + }else if (bs->file) { +return bdrv_has_zero_init (bs->file); + } + +return 1 ; +} +/* * Returns true iff the specified sector is present in the disk image. Drivers * not implementing the functionality are assumed to not support backing files,
block.h +1 -0
@@ -122,6 +122,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,void bdrv_flush (BlockDriverState *bs);void bdrv_flush_all (void ); +int bdrv_has_zero_init (BlockDriverState *bs);int bdrv_is_allocated (BlockDriverState *bs,int64_t sector_num,int nb_sectors,int *pnum);
qemu-img.c +4 -2
@@ -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" );
Signature · 1 line
1.6.6.1
PATCH 6/18 vmdk: Fix COW
In reply to Kevin WolfWhen trying to do COW, VMDK wrote the data back to the backing file. This problem was revealed by the patch that made backing files read-only. This patch does not only fix the problem, but also simplifies the VMDK code a bit.
This fixes the backing file qemu-iotests cases for VMDK.
--- block/vmdk.c | 35 +++++++++++------------------------ 1 files changed, 11 insertions(+), 24 deletions(-)
block/vmdk.c +11 -24
@@ -87,14 +87,6 @@ typedef struct VmdkMetaData {int valid; } VmdkMetaData; -typedef struct ActiveBDRVState { -BlockDriverState *hd;// active image handler -uint64_t cluster_offset;// current write offset -}ActiveBDRVState ; - -static ActiveBDRVState activeBDRV; - -static int vmdk_probe (const uint8_t *buf,int buf_size,const char *filename) {uint32_t magic;
@@ -492,30 +484,28 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,static int get_whole_cluster (BlockDriverState *bs,uint64_t cluster_offset,uint64_t offset,int allocate) { -uint64_t parent_cluster_offset;BDRVVmdkState *s = bs->opaque;uint8_t whole_grain[s->cluster_sectors*512 ];// 128 sectors * 512 bytes each = grain size 64KB // we will be here if it's first write on non-exist grain(cluster). // try to read from parent image, if exist if (bs->backing_hd) { -BDRVVmdkState *ps = bs->backing_hd->opaque; +int ret;if (!vmdk_is_cid_valid (bs))return -1 ; - parent_cluster_offset =get_cluster_offset (bs->backing_hd,NULL , - offset, allocate); - -if (parent_cluster_offset) { -BDRVVmdkState *act_s = activeBDRV.hd->opaque; - -if (bdrv_pread (ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512 ) != ps->cluster_sectors*512 ) -return -1 ; + ret =bdrv_read (bs->backing_hd, offset >>9 , whole_grain, + s->cluster_sectors); +if (ret <0 ) { +return -1 ; + } -//Write grain only into the active image -if (bdrv_pwrite (act_s->hd, activeBDRV.cluster_offset <<9 , whole_grain,sizeof (whole_grain)) !=sizeof (whole_grain)) -return -1 ; +//Write grain only into the active image + ret =bdrv_write (s->hd, cluster_offset, whole_grain, + s->cluster_sectors); +if (ret <0 ) { +return -1 ; } }return 0 ;
@@ -601,9 +591,6 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data, cluster_offset >>=9 ; tmp =cpu_to_le32 (cluster_offset); l2_table[l2_index] = tmp; -// Save the active image state - activeBDRV.cluster_offset = cluster_offset; - activeBDRV.hd = bs; }/* First of all we write grain itself, to avoid race condition * that may to corrupt the image.
Signature · 1 line
1.6.6.1
PATCH 7/18 vmdk: Clean up backing file handling
In reply to Kevin WolfVMDK is doing interesting things when it needs to open a backing file. This patch changes that part to look more like in other drivers. The nice side effect is that the file name isn't needed any more in the open function.
--- block/vmdk.c | 58 +++++++++------------------------------------------------- 1 files changed, 9 insertions(+), 49 deletions(-)
block/vmdk.c +9 -49
@@ -76,7 +76,6 @@ typedef struct BDRVVmdkState {unsigned int cluster_sectors;uint32_t parent_cid; -int is_parent; } BDRVVmdkState; typedef struct VmdkMetaData {
@@ -338,19 +337,11 @@ fail:return ret; } -static void vmdk_parent_close (BlockDriverState *bs) -{ -if (bs->backing_hd) -bdrv_close (bs->backing_hd); -} - -static int parent_open =0 ; -static int vmdk_parent_open (BlockDriverState *bs,const char * filename) +static int vmdk_parent_open (BlockDriverState *bs) {BDRVVmdkState *s = bs->opaque;char *p_name;char desc[DESC_SIZE ]; -char parent_img_name[1024 ];/* the descriptor offset = 0x200 */ if (bdrv_pread (s->hd,0x200 , desc,DESC_SIZE ) !=DESC_SIZE )
@@ -358,7 +349,6 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)if ((p_name =strstr (desc,"parentFileNameHint" )) !=NULL ) {char *end_name; -struct stat file_buf; p_name +=sizeof ("parentFileNameHint" ) +1 ;if ((end_name =strchr (p_name,'\"' )) ==NULL )
@@ -367,24 +357,6 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)return -1 ;pstrcpy (bs->backing_file, end_name - p_name +1 , p_name); -if (stat (bs->backing_file, &file_buf) !=0 ) { -path_combine (parent_img_name,sizeof (parent_img_name), - filename, bs->backing_file); - }else { -pstrcpy (parent_img_name,sizeof (parent_img_name), - bs->backing_file); - } - - bs->backing_hd =bdrv_new ("" ); -if (!bs->backing_hd) { - failure: -bdrv_close (s->hd); -return -1 ; - } - parent_open =1 ; -if (bdrv_open (bs->backing_hd, parent_img_name,0 ,NULL ) <0 ) - goto failure; - parent_open =0 ; }return 0 ;
@@ -396,11 +368,6 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)uint32_t magic;int l1_size, i, ret; -if (parent_open) { -/* Parent must be opened as RO, no RDWR. */ - flags =0 ; - } - ret =bdrv_file_open (&s->hd, filename, flags);if (ret <0 )return ret;
@@ -436,13 +403,8 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags) s->l1_table_offset =le64_to_cpu (header.rgd_offset) <<9 ; s->l1_backup_table_offset =le64_to_cpu (header.gd_offset) <<9 ; -if (parent_open) - s->is_parent =1 ; -else - s->is_parent =0 ; -// try to open parent images, if exist -if (vmdk_parent_open (bs, filename) !=0 ) +if (vmdk_parent_open (bs) !=0 ) goto fail;// write the CID once after the image creation s->parent_cid =vmdk_read_cid (bs,1 );
@@ -583,15 +545,15 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,if (!cluster_offset) {if (!allocate)return 0 ; +// Avoid the L2 tables update for the images that have snapshots. -if (!s->is_parent) { - cluster_offset =bdrv_getlength (s->hd); -bdrv_truncate (s->hd, cluster_offset + (s->cluster_sectors <<9 )); + cluster_offset =bdrv_getlength (s->hd); +bdrv_truncate (s->hd, cluster_offset + (s->cluster_sectors <<9 )); + + cluster_offset >>=9 ; + tmp =cpu_to_le32 (cluster_offset); + l2_table[l2_index] = tmp; - cluster_offset >>=9 ; - tmp =cpu_to_le32 (cluster_offset); - l2_table[l2_index] = tmp; - }/* First of all we write grain itself, to avoid race condition * that may to corrupt the image. * This problem may occur because of insufficient space on host disk
@@ -866,8 +828,6 @@ static void vmdk_close(BlockDriverState *bs)qemu_free (s->l1_table);qemu_free (s->l2_cache); -// try to close parent image, if exist -vmdk_parent_close (s->hd);bdrv_delete (s->hd); }
Signature · 1 line
1.6.6.1
PATCH 8/18 vmdk: Convert to bdrv_open
In reply to Kevin WolfIt's a format driver, so implement bdrv_open instead of bdrv_file_open.
--- block/vmdk.c | 51 +++++++++++++++++++++------------------------------ 1 files changed, 21 insertions(+), 30 deletions(-)
block/vmdk.c +21 -30
@@ -108,14 +108,13 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)static uint32_t vmdk_read_cid (BlockDriverState *bs,int parent) { -BDRVVmdkState *s = bs->opaque;char desc[DESC_SIZE ];uint32_t cid;const char *p_name, *cid_str;size_t cid_str_size;/* the descriptor offset = 0x200 */ -if (bdrv_pread (s->hd,0x200 , desc,DESC_SIZE ) !=DESC_SIZE ) +if (bdrv_pread (bs->file,0x200 , desc,DESC_SIZE ) !=DESC_SIZE )return 0 ;if (parent) {
@@ -136,12 +135,11 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)static int vmdk_write_cid (BlockDriverState *bs,uint32_t cid) { -BDRVVmdkState *s = bs->opaque;char desc[DESC_SIZE ], tmp_desc[DESC_SIZE ];char *p_name, *tmp_str;/* the descriptor offset = 0x200 */ -if (bdrv_pread (s->hd,0x200 , desc,DESC_SIZE ) !=DESC_SIZE ) +if (bdrv_pread (bs->file,0x200 , desc,DESC_SIZE ) !=DESC_SIZE )return -1 ; tmp_str =strstr (desc,"parentCID" );
@@ -152,7 +150,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)pstrcat (desc,sizeof (desc), tmp_desc); } -if (bdrv_pwrite (s->hd,0x200 , desc,DESC_SIZE ) !=DESC_SIZE ) +if (bdrv_pwrite (bs->file,0x200 , desc,DESC_SIZE ) !=DESC_SIZE )return -1 ;return 0 ; }
@@ -339,12 +337,11 @@ fail:static int vmdk_parent_open (BlockDriverState *bs) { -BDRVVmdkState *s = bs->opaque;char *p_name;char desc[DESC_SIZE ];/* the descriptor offset = 0x200 */ -if (bdrv_pread (s->hd,0x200 , desc,DESC_SIZE ) !=DESC_SIZE ) +if (bdrv_pread (bs->file,0x200 , desc,DESC_SIZE ) !=DESC_SIZE )return -1 ;if ((p_name =strstr (desc,"parentFileNameHint" )) !=NULL ) {
@@ -362,23 +359,20 @@ static int vmdk_parent_open(BlockDriverState *bs)return 0 ; } -static int vmdk_open (BlockDriverState *bs,const char *filename,int flags) +static int vmdk_open (BlockDriverState *bs,int flags) {BDRVVmdkState *s = bs->opaque;uint32_t magic; -int l1_size, i, ret; +int l1_size, i; - ret =bdrv_file_open (&s->hd, filename, flags); -if (ret <0 ) -return ret; -if (bdrv_pread (s->hd,0 , &magic,sizeof (magic)) !=sizeof (magic)) +if (bdrv_pread (bs->file,0 , &magic,sizeof (magic)) !=sizeof (magic)) goto fail; magic =be32_to_cpu (magic);if (magic ==VMDK3_MAGIC ) {VMDK3Header header; -if (bdrv_pread (s->hd,sizeof (magic), &header,sizeof (header)) !=sizeof (header)) +if (bdrv_pread (bs->file,sizeof (magic), &header,sizeof (header)) !=sizeof (header)) goto fail; s->cluster_sectors =le32_to_cpu (header.granularity); s->l2_size =1 <<9 ;
@@ -390,7 +384,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags) }else if (magic ==VMDK4_MAGIC ) {VMDK4Header header; -if (bdrv_pread (s->hd,sizeof (magic), &header,sizeof (header)) !=sizeof (header)) +if (bdrv_pread (bs->file,sizeof (magic), &header,sizeof (header)) !=sizeof (header)) goto fail; bs->total_sectors =le64_to_cpu (header.capacity); s->cluster_sectors =le64_to_cpu (header.granularity);
@@ -415,7 +409,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)/* read the L1 table */ l1_size = s->l1_size *sizeof (uint32_t ); s->l1_table =qemu_malloc (l1_size); -if (bdrv_pread (s->hd, s->l1_table_offset, s->l1_table, l1_size) != l1_size) +if (bdrv_pread (bs->file, s->l1_table_offset, s->l1_table, l1_size) != l1_size) goto fail;for (i =0 ; i < s->l1_size; i++) {le32_to_cpus (&s->l1_table[i]);
@@ -423,7 +417,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)if (s->l1_backup_table_offset) { s->l1_backup_table =qemu_malloc (l1_size); -if (bdrv_pread (s->hd, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size) +if (bdrv_pread (bs->file, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size) goto fail;for (i =0 ; i < s->l1_size; i++) {le32_to_cpus (&s->l1_backup_table[i]);
@@ -436,7 +430,6 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)qemu_free (s->l1_backup_table);qemu_free (s->l1_table);qemu_free (s->l2_cache); -bdrv_delete (s->hd);return -1 ; }
@@ -464,7 +457,7 @@ static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset, }//Write grain only into the active image - ret =bdrv_write (s->hd, cluster_offset, whole_grain, + ret =bdrv_write (bs->file, cluster_offset, whole_grain, s->cluster_sectors);if (ret <0 ) {return -1 ;
@@ -478,13 +471,13 @@ static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data)BDRVVmdkState *s = bs->opaque;/* update L2 table */ -if (bdrv_pwrite (s->hd, ((int64_t )m_data->l2_offset *512 ) + (m_data->l2_index *sizeof (m_data->offset)), +if (bdrv_pwrite (bs->file, ((int64_t )m_data->l2_offset *512 ) + (m_data->l2_index *sizeof (m_data->offset)), &(m_data->offset),sizeof (m_data->offset)) !=sizeof (m_data->offset))return -1 ;/* update backup L2 table */ if (s->l1_backup_table_offset !=0 ) { m_data->l2_offset = s->l1_backup_table[m_data->l1_index]; -if (bdrv_pwrite (s->hd, ((int64_t )m_data->l2_offset *512 ) + (m_data->l2_index *sizeof (m_data->offset)), +if (bdrv_pwrite (bs->file, ((int64_t )m_data->l2_offset *512 ) + (m_data->l2_index *sizeof (m_data->offset)), &(m_data->offset),sizeof (m_data->offset)) !=sizeof (m_data->offset))return -1 ; }
@@ -532,7 +525,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data, } } l2_table = s->l2_cache + (min_index * s->l2_size); -if (bdrv_pread (s->hd, (int64_t )l2_offset *512 , l2_table, s->l2_size *sizeof (uint32_t )) != +if (bdrv_pread (bs->file, (int64_t )l2_offset *512 , l2_table, s->l2_size *sizeof (uint32_t )) != s->l2_size *sizeof (uint32_t ))return 0 ;
@@ -547,8 +540,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,return 0 ;// Avoid the L2 tables update for the images that have snapshots. - cluster_offset =bdrv_getlength (s->hd); -bdrv_truncate (s->hd, cluster_offset + (s->cluster_sectors <<9 )); + cluster_offset =bdrv_getlength (bs->file); +bdrv_truncate (bs->file, cluster_offset + (s->cluster_sectors <<9 )); cluster_offset >>=9 ; tmp =cpu_to_le32 (cluster_offset);
@@ -615,7 +608,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,memset (buf,0 ,512 * n); } }else { -if (bdrv_pread (s->hd, cluster_offset + index_in_cluster *512 , buf, n *512 ) != n *512 ) +if (bdrv_pread (bs->file, cluster_offset + index_in_cluster *512 , buf, n *512 ) != n *512 )return -1 ; } nb_sectors -= n;
@@ -651,7 +644,7 @@ static int vmdk_write(BlockDriverState *bs, int64_t sector_num,if (!cluster_offset)return -1 ; -if (bdrv_pwrite (s->hd, cluster_offset + index_in_cluster *512 , buf, n *512 ) != n *512 ) +if (bdrv_pwrite (bs->file, cluster_offset + index_in_cluster *512 , buf, n *512 ) != n *512 )return -1 ;if (m_data.valid) {/* update L2 tables */
@@ -828,13 +821,11 @@ static void vmdk_close(BlockDriverState *bs)qemu_free (s->l1_table);qemu_free (s->l2_cache); -bdrv_delete (s->hd); }static void vmdk_flush (BlockDriverState *bs) { -BDRVVmdkState *s = bs->opaque; -bdrv_flush (s->hd); +bdrv_flush (bs->file); }
@@ -861,7 +852,7 @@ static BlockDriver bdrv_vmdk = { .format_name = "vmdk", .instance_size = sizeof(BDRVVmdkState), .bdrv_probe = vmdk_probe, - .bdrv_file_open = vmdk_open, + .bdrv_open = vmdk_open, .bdrv_read = vmdk_read, .bdrv_write = vmdk_write, .bdrv_close = vmdk_close,
Signature · 1 line
1.6.6.1
PATCH 9/18 block: Set backing_hd to NULL after deleting it
In reply to Kevin WolfFrom: Stefan Hajnoczi <[email protected]>
It is safer to set backing_hd to NULL after deleting it so that any use after deletion is obvious during development. Happy segfaulting!
This patch should be applied after Kevin Wolf's "vmdk: Convert to bdrv_open" so that vmdk does not segfault on close.
--- block.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
block.c +3 -1
@@ -589,8 +589,10 @@ unlink_and_fail:void bdrv_close (BlockDriverState *bs) {if (bs->drv) { -if (bs->backing_hd) +if (bs->backing_hd) {bdrv_delete (bs->backing_hd); + bs->backing_hd =NULL ; + } bs->drv->bdrv_close (bs);qemu_free (bs->opaque);#ifdef _WIN32
Signature · 1 line
1.6.6.1
PATCH 10/18 qcow2: Avoid shadowing variable in alloc_clusters_noref()
In reply to Kevin WolfFrom: Stefan Hajnoczi <[email protected]>
The i loop iterator is shadowed by the next free cluster index. Both using the variable name 'i' makes the code harder to read.
--- block/qcow2-refcount.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
block/qcow2-refcount.c +2 -2
@@ -556,8 +556,8 @@ static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size) nb_clusters =size_to_clusters (s, size); retry:for (i =0 ; i < nb_clusters; i++) { -int64_t i = s->free_cluster_index++; -if (get_refcount (bs, i) !=0 ) +int64_t next_cluster_index = s->free_cluster_index++; +if (get_refcount (bs, next_cluster_index) !=0 ) goto retry; }#ifdef DEBUG_ALLOC2
Signature · 1 line
1.6.6.1
PATCH 11/18 raw-posix: Use pread/pwrite instead of lseek+read/write
In reply to Kevin WolfFrom: Stefan Hajnoczi <[email protected]>
This patch combines the lseek+read/write calls to use pread/pwrite instead. This will result in fewer system calls and is already used by AIO.
Thanks to Jan Kiszka <[email protected]> for identifying excessive lseek and Christoph Hellwig <[email protected]> for confirming that this approach should work.
--- block/raw-posix.c | 37 ++++--------------------------------- 1 files changed, 4 insertions(+), 33 deletions(-)
block/raw-posix.c +4 -33
@@ -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;
Signature · 1 line
1.6.6.1
PATCH 12/18 block: Cache total_sectors to reduce bdrv_getlength calls
In reply to Kevin WolfFrom: Stefan Hajnoczi <[email protected]>
The BlockDriver bdrv_getlength function is called from the I/O code path when checking that the request falls within the device. Unfortunately this involves an lseek system call in the raw protocol; every read or write request will incur this lseek cost.
Jan Kiszka <[email protected]> identified this issue and its latency overhead. This patch caches device length in the existing total_sectors variable so lseek calls can be avoided for fixed size devices.
Growable devices fall back to the full bdrv_getlength code path because I have not added logic to detect extending the size of the device in a write.
--- block.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 files changed, 38 insertions(+), 5 deletions(-)
block.c +38 -5
@@ -352,6 +352,26 @@ static BlockDriver *find_image_format(const char *filename)return drv; } +/** +* Set the current 'total_sectors' value +*/ +static int refresh_total_sectors (BlockDriverState *bs,int64_t hint) +{ +BlockDriver *drv = bs->drv; + +/* query actual device if possible, otherwise just trust the hint */ +if (drv->bdrv_getlength) { +int64_t length = drv->bdrv_getlength (bs); +if (length <0 ) { +return length; + } + hint = length >>BDRV_SECTOR_BITS ; + } + + bs->total_sectors = hint; +return 0 ; +} +/* * Common part for opening disk images and files */
@@ -363,6 +383,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,assert (drv !=NULL ); bs->file =NULL ; + bs->total_sectors =0 ; bs->is_temporary =0 ; bs->encrypted =0 ; bs->valid_key =0 ;
@@ -416,9 +437,12 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename, } bs->keep_read_only = bs->read_only = !(open_flags &BDRV_O_RDWR ); -if (drv->bdrv_getlength) { - bs->total_sectors =bdrv_getlength (bs) >>BDRV_SECTOR_BITS ; + + ret =refresh_total_sectors (bs, bs->total_sectors); +if (ret <0 ) { + goto free_and_fail; } +#ifndef _WIN32if (bs->is_temporary) {unlink (filename);
@@ -959,13 +983,18 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,int bdrv_truncate (BlockDriverState *bs,int64_t offset) {BlockDriver *drv = bs->drv; +int ret;if (!drv)return -ENOMEDIUM ;if (!drv->bdrv_truncate)return -ENOTSUP ;if (bs->read_only)return -EACCES ; -return drv->bdrv_truncate (bs, offset); + ret = drv->bdrv_truncate (bs, offset); +if (ret ==0 ) { + ret =refresh_total_sectors (bs, offset >>BDRV_SECTOR_BITS ); + } +return ret; }/**
@@ -976,8 +1005,12 @@ int64_t bdrv_getlength(BlockDriverState *bs)BlockDriver *drv = bs->drv;if (!drv)return -ENOMEDIUM ; -if (!drv->bdrv_getlength) { -/* legacy mode */ + +/* Fixed size devices use the total_sectors value for speed instead of +issuing a length query (like lseek) on each call. Also, legacy block +drivers don't provide a bdrv_getlength function and must use +total_sectors. */ +if (!bs->growable || !drv->bdrv_getlength) {return bs->total_sectors *BDRV_SECTOR_SIZE ; }return drv->bdrv_getlength (bs);
Signature · 1 line
1.6.6.1
PATCH 13/18 qemu-img: Add 'resize' command to grow/shrink disk images
In reply to Kevin WolfFrom: Stefan Hajnoczi <[email protected]>
This patch adds a 'resize' command to grow/shrink disk images. This allows changing the size of disk images without copying to a new image file. Currently only raw files support resize.
--- qemu-img-cmds.hx | 6 +++ qemu-img.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-img.texi | 12 +++++++ 3 files changed, 110 insertions(+), 0 deletions(-)
qemu-img-cmds.hx +6 -0
@@ -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
qemu-img.c +92 -0
98 lines not on this page · raw message
qemu-img.texi +12 -0
@@ -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:
Signature · 1 line
1.6.6.1
PATCH 14/18 qcow2: Remove abort on free_clusters failure
In reply to Kevin WolfWhile it's true that during regular operation free_clusters failure would be a bug, an I/O error can always happen. There's no need to kill the VM, the worst thing that can happen (and it will) is that we leak some clusters.
--- block/qcow2-refcount.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
block/qcow2-refcount.c +1 -1
@@ -638,7 +638,7 @@ void qcow2_free_clusters(BlockDriverState *bs, ret =update_refcount (bs, offset, size,-1 );if (ret <0 ) {fprintf (stderr,"qcow2_free_clusters failed: %s\n" ,strerror (-ret)); -abort (); +/* TODO Remember the clusters to free them later and avoid leaking */ } }
Signature · 1 line
1.6.6.1
PATCH 15/18 qcow2: Implement bdrv_truncate() for growing images
In reply to Kevin WolfFrom: Stefan Hajnoczi <[email protected]>
This patch adds the ability to grow qcow2 images in-place using bdrv_truncate(). This enables qemu-img resize command support for qcow2.
Snapshots are not supported and bdrv_truncate() will return -ENOTSUP. The notion of resizing an image with snapshots could lead to confusion:
users may expect snapshots to remain unchanged, but this is not possible with the current qcow2 on-disk format where the header.size field is global instead of per-snapshot. Others may expect snapshots to change size along with the current image data. I think it is safest to not support snapshots and perhaps add behavior later if there is a consensus.
Backing images continue to work. If the image is now larger than its backing image, zeroes are read when accessing beyond the end of the backing image.
--- block/qcow2.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- block/qcow2.h | 6 ++++++ 2 files changed, 48 insertions(+), 4 deletions(-)
block/qcow2.c +42 -4
@@ -140,7 +140,7 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,static int qcow_open (BlockDriverState *bs,int flags) {BDRVQcowState *s = bs->opaque; -int len, i, shift; +int len, i;QCowHeader header;uint64_t ext_end;
@@ -188,8 +188,7 @@ static int qcow_open(BlockDriverState *bs, int flags)/* read the level 1 table */ s->l1_size = header.l1_size; - shift = s->cluster_bits + s->l2_bits; - s->l1_vm_state_index = (header.size + (1LL << shift) -1 ) >> shift; + s->l1_vm_state_index =size_to_l1 (s, header.size);/* the L1 table must contain at least enough entries to put header.size bytes */ if (s->l1_size < s->l1_vm_state_index)
@@ -851,6 +850,43 @@ static int qcow_make_empty(BlockDriverState *bs)return 0 ; } +static int qcow2_truncate (BlockDriverState *bs,int64_t offset) +{ +BDRVQcowState *s = bs->opaque; +int ret, new_l1_size; + +if (offset &511 ) { +return -EINVAL ; + } + +/* cannot proceed if image has snapshots */ +if (s->nb_snapshots) { +return -ENOTSUP ; + } + +/* shrinking is currently not supported */ +if (offset < bs->total_sectors *512 ) { +return -ENOTSUP ; + } + + new_l1_size =size_to_l1 (s, offset); + ret =qcow2_grow_l1_table (bs, new_l1_size); +if (ret <0 ) { +return ret; + } + +/* write updated header.size */ + offset =cpu_to_be64 (offset); + ret =bdrv_pwrite (bs->file, offsetof(QCowHeader , size), + &offset,sizeof (uint64_t )); +if (ret <0 ) { +return ret; + } + + s->l1_vm_state_index = new_l1_size; +return 0 ; +} +/* XXX: put compressed sectors first, then all the cluster aligned tables to avoid losing bytes in alignment */ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
@@ -1050,7 +1086,9 @@ static BlockDriver bdrv_qcow2 = { .bdrv_aio_readv = qcow_aio_readv, .bdrv_aio_writev = qcow_aio_writev, .bdrv_aio_flush = qcow_aio_flush, - .bdrv_write_compressed = qcow_write_compressed, + + .bdrv_truncate = qcow2_truncate, + .bdrv_write_compressed = qcow_write_compressed, .bdrv_snapshot_create = qcow2_snapshot_create, .bdrv_snapshot_goto = qcow2_snapshot_goto,
block/qcow2.h +6 -0
@@ -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 );
Signature · 1 line
1.6.6.1
PATCH 16/18 block: Add wr_highest_sector blockstat
In reply to Kevin WolfThis adds the wr_highest_sector blockstat which implements what is generally known as the high watermark. It is the highest offset of a sector written to the respective BlockDriverState since it has been opened.
The query-blockstat QMP command is extended to add this value to the result, and also to add the statistics of the underlying protocol in a new "parent" field. Note that to get the "high watermark" of a qcow2 image, you need to look into the wr_highest_sector field of the parent (which can be a file, a host_device, ...). The wr_highest_sector of the qcow2 BlockDriverState itself is the highest offset on the _virtual_ disk that the guest has written to.
--- block.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++------------ block_int.h | 1 + 2 files changed, 59 insertions(+), 15 deletions(-)
block.c +58 -15
@@ -880,6 +880,10 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,set_dirty_bitmap (bs, sector_num, nb_sectors,1 ); } +if (bs->wr_highest_sector < sector_num + nb_sectors -1 ) { + bs->wr_highest_sector = sector_num + nb_sectors -1 ; + } +return drv->bdrv_write (bs, sector_num, buf, nb_sectors); }
@@ -1530,6 +1534,35 @@ void bdrv_stats_print(Monitor *mon, const QObject *data)qlist_iter (qobject_to_qlist (data), bdrv_stats_iter, mon); } +static QObject *bdrv_info_stats_bs (BlockDriverState *bs) +{ +QObject *res; +QDict *dict; + + res =qobject_from_jsonf ("{ 'stats': {" +"'rd_bytes': %" PRId64"," +"'wr_bytes': %" PRId64"," +"'rd_operations': %" PRId64"," +"'wr_operations': %" PRId64"," +"'wr_highest_offset': %" PRId64 +"} }" , + bs->rd_bytes, bs->wr_bytes, + bs->rd_ops, bs->wr_ops, + bs->wr_highest_sector *512 ); + dict =qobject_to_qdict (res); + +if (*bs->device_name) { +qdict_put (dict,"device" ,qstring_from_str (bs->device_name)); + } + +if (bs->file) { +QObject *parent =bdrv_info_stats_bs (bs->file); +qdict_put_obj (dict,"parent" , parent); + } + +return res; +} +/** * bdrv_info_stats(): show block device statistics *
@@ -1544,19 +1577,34 @@ void bdrv_stats_print(Monitor *mon, const QObject *data)* - "wr_bytes": bytes written * - "rd_operations": read operations * - "wr_operations": write operations -* +* - "wr_highest_offset": Highest offset of a sector written since the +* BlockDriverState has been opened +* - "parent": Contains recursively the statistics of the underlying +* protocol (e.g. the host file for a qcow2 image). If there is no +* underlying protocol, this field is omitted. +* * Example: * * [ { "device": "ide0-hd0", * "stats": { "rd_bytes": 512, * "wr_bytes": 0, * "rd_operations": 1, -* "wr_operations": 0 } }, +* "wr_operations": 0, +* "wr_highest_offset": 0, +* "parent": { +* "stats": { "rd_bytes": 1024, +* "wr_bytes": 0, +* "rd_operations": 2, +* "wr_operations": 0, +* "wr_highest_offset": 0, +* } +* } } }, * { "device": "ide1-cd0", * "stats": { "rd_bytes": 0, * "wr_bytes": 0, * "rd_operations": 0, -* "wr_operations": 0 } } ] +* "wr_operations": 0, +* "wr_highest_offset": 0 } }, */ void bdrv_info_stats (Monitor *mon,QObject **ret_data) {
@@ -1567,15 +1615,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data) devices =qlist_new (); QTAILQ_FOREACH(bs, &bdrv_states, list) { - obj =qobject_from_jsonf ("{ 'device': %s, 'stats': {" -"'rd_bytes': %" PRId64"," -"'wr_bytes': %" PRId64"," -"'rd_operations': %" PRId64"," -"'wr_operations': %" PRId64 -"} }" , - bs->device_name, - bs->rd_bytes, bs->wr_bytes, - bs->rd_ops, bs->wr_ops); + obj =bdrv_info_stats_bs (bs);qlist_append_obj (devices, obj); }
@@ -1834,9 +1874,12 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num, cb, opaque);if (ret) { -/* Update stats even though technically transfer has not happened. */ - bs->wr_bytes += (unsigned ) nb_sectors *BDRV_SECTOR_SIZE ; - bs->wr_ops ++; +/* Update stats even though technically transfer has not happened. */ + bs->wr_bytes += (unsigned ) nb_sectors *BDRV_SECTOR_SIZE ; + bs->wr_ops ++; +if (bs->wr_highest_sector < sector_num + nb_sectors -1 ) { + bs->wr_highest_sector = sector_num + nb_sectors -1 ; + } }return ret;
block_int.h +1 -0
@@ -167,6 +167,7 @@ struct BlockDriverState {uint64_t wr_bytes;uint64_t rd_ops;uint64_t wr_ops; +uint64_t wr_highest_sector;/* Whether the disk can expand beyond total_sectors */ int growable;
Signature · 1 line
1.6.6.1
PATCH 17/18 qemu-img rebase: Fix output image corruption
In reply to Kevin Wolfqemu-img rebase must always give clusters in the COW file priority over those in the backing file. As it failed to use number of non-allocated clusters but assumed the maximum, it was possible that allocated clusters were taken from the backing file instead, leading to a corrupted output image.
--- qemu-img.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
qemu-img.c +3 -3
@@ -1136,7 +1136,7 @@ static int img_rebase(int argc, char **argv)if (!unsafe) {uint64_t num_sectors;uint64_t sector; -int n, n1; +int n;uint8_t * buf_old;uint8_t * buf_new;
@@ -1155,8 +1155,8 @@ static int img_rebase(int argc, char **argv) }/* If the cluster is allocated, we don't need to take action */ -if (bdrv_is_allocated (bs, sector, n, &n1)) { - n = n1; + ret =bdrv_is_allocated (bs, sector, n, &n); +if (ret) {continue ; }
Signature · 1 line
1.6.6.1
PATCH 18/18 block: Release allocated options after bdrv_open
In reply to Kevin WolfFrom: Jan Kiszka <[email protected]>
They aren't used afterwards nor supposed to be stored by a bdrv_create handler.
--- block.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
block.c +1 -0
@@ -540,6 +540,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags, } ret =bdrv_create (bdrv_qcow2, tmp_filename, options); +free_option_parameters (options);if (ret <0 ) {return ret; }
Signature · 1 line
1.6.6.1
Quoted 9 lines · Kevin Wolf
Hi Anthony,
this is the second part of the block patches in my queue that I promised in the pull request last week. I also included the high watermark patch even if it didn't sit on the list for a very long time - but the people that I expected to comment on it have already done so, either on the list or internally.
Kevin
Quoted 8 lines
The following changes since commit
9ed7b059ef776a3921cfd085e891f45076922542:
Amit Shah (1):
virtio-serial: Implement flow control for individual portsare available in the git repository at:
git://repo.or.cz/qemu/kevin.gitfor-anthony
Pulled. Thanks.
Regards,
Anthony Liguori
Quoted 57 lines
Christoph Hellwig (1):
block: separate raw images from the file protocolJan Kiszka (1):
block: Release allocated options afterbdrv_openKevin Wolf (10):
block: Splitbdrv_open
block: Avoid forward declaration ofbdrv_open_common
block: Open the underlying image file in generic code
block:bdrv_has_zero_init
vmdk: Fix COW
vmdk: Clean up backing file handling
vmdk: Convert tobdrv_open
qcow2: Remove abort onfree_clustersfailure
block: Addwr_highest_sectorblockstat qemu-img rebase: Fix output image corruptionStefan Hajnoczi (6):
block: Setbacking_hdto NULL after deleting it
qcow2: Avoid shadowing variable inalloc_clusters_noref()
raw-posix: Use pread/pwrite instead of lseek+read/write
block: Cachetotal_sectorsto reducebdrv_getlengthcalls
qemu-img: Add 'resize' command to grow/shrink disk images
qcow2: Implementbdrv_truncate()for growing imagesMakefile.objs | 2 +- block.c | 384 ++++++++++++++++++++++++++++++++++-------------- block.h | 2 + block/blkdebug.c | 17 +-- block/bochs.c | 2 +- block/cloop.c | 2 +- block/cow.c | 2 +- block/curl.c | 10 +- block/dmg.c | 2 +- block/nbd.c | 2 +- block/parallels.c | 2 +- block/qcow.c | 67 ++++----- block/qcow2-cluster.c | 64 ++++---- block/qcow2-refcount.c | 86 ++++++------ block/qcow2-snapshot.c | 22 ++-- block/qcow2.c | 110 +++++++++----- block/qcow2.h | 8 +- block/raw-posix.c | 62 +++------ block/raw-win32.c | 16 +- block/raw.c | 144 ++++++++++++++++++ block/vdi.c | 29 +--- block/vmdk.c | 140 +++++------------- block/vpc.c | 32 ++--- block/vvfat.c | 2 +- block_int.h | 6 +- qemu-img-cmds.hx | 6 + qemu-img.c | 104 +++++++++++++- qemu-img.texi | 12 ++ 28 files changed, 843 insertions(+), 494 deletions(-)create mode 100644
block/raw.c