Block patches for stable-0.14
The following changes since commit b03088c32f8a88e4674f6cdab47da79ef4188d88:
linux-user: Fix possible realloc memory leak (2011-02-09 21:24:05 +0100)
are available in the git repository at:
git://repo.or.cz/qemu/kevin.git for-stable-0.14
Chunqiang Tang (1):
QCOW2: bug fix - read base image beyond its size
Jes Sorensen (1):
Change snapshot_blkdev hmp to use correct argument type for device
Kevin Wolf (7):
qcow2: Fix error handling for immediate backing file read failure
qcow2: Fix error handling for reading compressed clusters
qerror: Add QERR_UNKNOWN_BLOCK_FORMAT_FEATURE
qcow2: Report error for version > 2
qed: Report error for unsupported features
qemu-img: Improve error messages for failed bdrv_open
qcow2: Fix order in L2 table COW
block/qcow2-cluster.c | 13 ++++++++----- block/qcow2.c | 26 +++++++++++++++++++------- block/qed.c | 9 ++++++++- cutils.c | 31 +++++++++++++++++++++++++++++++ hmp-commands.hx | 2 +- qemu-common.h | 2 ++ qemu-img.c | 10 +++++++--- qerror.c | 5 +++++ qerror.h | 3 +++ 9 files changed, 84 insertions(+), 17 deletions(-)
PATCH 1/9 Change snapshot_blkdev hmp to use correct argument type for device
From: Jes Sorensen <[email protected]>
Pointed out by Markus
--- hmp-commands.hx | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
hmp-commands.hx +1 -1
@@ -822,7 +822,7 @@ ETEXI { .name = "snapshot_blkdev", - .args_type = "device:s,snapshot_file:s?,format:s?", + .args_type = "device:B,snapshot_file:s?,format:s?", .params = "device [new-image-file] [format]", .help = "initiates a live snapshot\n\t\t\t" "of device. If a new image file is specified, the\n\t\t\t"
Signature · 1 line
1.7.2.3
PATCH 2/9 QCOW2: bug fix - read base image beyond its size
In reply to Kevin WolfFrom: Chunqiang Tang <[email protected]>
This patch fixes the following bug in QCOW2. For a QCOW2 image that is larger than its base image, when handling a read request straddling over the end of the base image, the QCOW2 driver attempts to read beyond the end of the base image and the request would fail.
This bug was found by Fast Virtual Disk (FVD)'s fully automated testing tool. The following test triggered the bug.
dd if=/dev/zero of=/var/ramdisk/truth.raw count=0 bs=1 seek=1098561536
dd if=/dev/zero of=/var/ramdisk/zero-500M.raw count=0 bs=1 seek=593099264
./qemu-img create -f qcow2 -ocluster_size=65536,backing_fmt=blksim -b /var/ramdisk/zero-500M.raw /var/ramdisk/test.qcow2 1098561536
./qemu-io --auto --seed=30477694 --truth=/var/ramdisk/truth.raw --format=qcow2 --test=blksim:/var/ramdisk/test.qcow2 --verify_write=true --compare_before=false --compare_after=true --round=100000 --parallel=100 --io_size=10485760 --fail_prob=0 --cancel_prob=0 --instant_qemubh=true
--- block/qcow2.c | 5 ++--- cutils.c | 31 +++++++++++++++++++++++++++++++ qemu-common.h | 2 ++ 3 files changed, 35 insertions(+), 3 deletions(-)
block/qcow2.c +2 -3
@@ -355,7 +355,7 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov,else n1 = bs->total_sectors - sector_num; -qemu_iovec_memset (qiov,0 ,512 * (nb_sectors - n1)); +qemu_iovec_memset_skip (qiov,0 ,512 * (nb_sectors - n1),512 * n1);return n1; }
@@ -478,8 +478,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret)if (n1 >0 ) {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, - qcow2_aio_read_cb, acb); + &acb->hd_qiov, n1, qcow2_aio_read_cb, acb);if (acb->hd_aiocb ==NULL ) goto done; }else {
cutils.c +31 -0
@@ -267,6 +267,37 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count) } } +void qemu_iovec_memset_skip (QEMUIOVector *qiov,int c,size_t count, +size_t skip) +{ +int i; +size_t done; +void *iov_base; +uint64_t iov_len; + + done =0 ; +for (i =0 ; (i < qiov->niov) && (done != count); i++) { +if (skip >= qiov->iov[i].iov_len) { +/* Skip the whole iov */ + skip -= qiov->iov[i].iov_len; +continue ; + }else { +/* Skip only part (or nothing) of the iov */ + iov_base = (uint8_t *) qiov->iov[i].iov_base + skip; + iov_len = qiov->iov[i].iov_len - skip; + skip =0 ; + } + +if (done + iov_len > count) { +memset (iov_base, c, count - done); +break ; + }else { +memset (iov_base, c, iov_len); + } + done += iov_len; + } +} +#ifndef _WIN32/* Sets a specific flag */ int fcntl_setfl (int fd,int flag)
qemu-common.h +2 -0
@@ -322,6 +322,8 @@ void qemu_iovec_reset(QEMUIOVector *qiov);void qemu_iovec_to_buffer (QEMUIOVector *qiov,void *buf);void qemu_iovec_from_buffer (QEMUIOVector *qiov,const void *buf,size_t count);void qemu_iovec_memset (QEMUIOVector *qiov,int c,size_t count); +void qemu_iovec_memset_skip (QEMUIOVector *qiov,int c,size_t count, +size_t skip);struct Monitor ;typedef struct Monitor Monitor ;
Signature · 1 line
1.7.2.3
PATCH 3/9 qcow2: Fix error handling for immediate backing file read failure
In reply to Kevin WolfRequests could return success even though they failed when bdrv_aio_readv returned NULL for a backing file read.
--- block/qcow2.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
block/qcow2.c +3 -1
@@ -479,8 +479,10 @@ static void qcow2_aio_read_cb(void *opaque, int ret)BLKDBG_EVENT (bs->file,BLKDBG_READ_BACKING_AIO ); acb->hd_aiocb =bdrv_aio_readv (bs->backing_hd, acb->sector_num, &acb->hd_qiov, n1, qcow2_aio_read_cb, acb); -if (acb->hd_aiocb ==NULL ) +if (acb->hd_aiocb ==NULL ) { + ret = -EIO ; goto done; + } }else { ret =qcow2_schedule_bh (qcow2_aio_read_bh, acb);if (ret <0 )
Signature · 1 line
1.7.2.3
PATCH 4/9 qcow2: Fix error handling for reading compressed clusters
In reply to Kevin WolfWhen reading a compressed cluster failed, qcow2 falsely returned success.
--- block/qcow2-cluster.c | 4 ++-- block/qcow2.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-)
block/qcow2-cluster.c +2 -2
@@ -878,11 +878,11 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)BLKDBG_EVENT (bs->file,BLKDBG_READ_COMPRESSED ); ret =bdrv_read (bs->file, coffset >>9 , s->cluster_data, nb_csectors);if (ret <0 ) { -return -1 ; +return ret; }if (decompress_buffer (s->cluster_cache, s->cluster_size, s->cluster_data + sector_offset, csize) <0 ) { -return -1 ; +return -EIO ; } s->cluster_cache_offset = coffset; }
block/qcow2.c +3 -1
@@ -497,8 +497,10 @@ static void qcow2_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 (bs, acb->cluster_offset) <0 ) + ret =qcow2_decompress_cluster (bs, acb->cluster_offset); +if (ret <0 ) { goto done; + } qemu_iovec_from_buffer(&acb->hd_qiov, s->cluster_cache + index_in_cluster * 512,
Signature · 1 line
1.7.2.3
PATCH 5/9 qerror: Add QERR_UNKNOWN_BLOCK_FORMAT_FEATURE
In reply to Kevin Wolf--- qerror.c | 5 +++++ qerror.h | 3 +++ 2 files changed, 8 insertions(+), 0 deletions(-)
qerror.c +5 -0
@@ -201,6 +201,11 @@ static const QErrorStringTable qerror_table[] = { .desc = "An undefined error has ocurred", }, { + .error_fmt = QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, + .desc = "'%(device)' uses a %(format) feature which is not " + "supported by this qemu version: %(feature)", + }, + { .error_fmt = QERR_VNC_SERVER_FAILED, .desc = "Could not start VNC server on %(target)", },
qerror.h +3 -0
@@ -165,6 +165,9 @@ QError *qobject_to_qerror(const QObject *obj);#define QERR_UNDEFINED_ERROR \ "{ 'class': 'UndefinedError', 'data': {} }" +#define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \ + "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }" +#define QERR_VNC_SERVER_FAILED \ "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
Signature · 1 line
1.7.2.3
PATCH 6/9 qcow2: Report error for version > 2
In reply to Kevin WolfThe qcow2 driver is now declared responsible for any QCOW image that has version 2 or greater (before this, version 3 would be detected as raw).
For everything newer than version 2, an error is reported.
--- block/qcow2.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-)
block/qcow2.c +11 -2
@@ -28,6 +28,7 @@#include "aes.h" #include "block/qcow2.h" #include "qemu-error.h" +#include "qerror.h" /* Differences with QCOW:
@@ -59,7 +60,7 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)if (buf_size >=sizeof (QCowHeader) &&be32_to_cpu (cow_header->magic) ==QCOW_MAGIC && -be32_to_cpu (cow_header->version) ==QCOW_VERSION ) +be32_to_cpu (cow_header->version) >=QCOW_VERSION )return 100 ;else return 0 ;
@@ -163,10 +164,18 @@ static int qcow2_open(BlockDriverState *bs, int flags)be64_to_cpus (&header.snapshots_offset);be32_to_cpus (&header.nb_snapshots); -if (header.magic !=QCOW_MAGIC || header.version !=QCOW_VERSION ) { +if (header.magic !=QCOW_MAGIC ) { ret = -EINVAL ; goto fail; } +if (header.version !=QCOW_VERSION ) { +char version[64 ]; +snprintf (version,sizeof (version),"QCOW version %d" , header.version); +qerror_report (QERR_UNKNOWN_BLOCK_FORMAT_FEATURE , + bs->device_name,"qcow2" , version); + ret = -ENOTSUP ; + goto fail; + }if (header.cluster_bits <MIN_CLUSTER_BITS || header.cluster_bits >MAX_CLUSTER_BITS ) { ret = -EINVAL ;
Signature · 1 line
1.7.2.3
PATCH 7/9 qed: Report error for unsupported features
In reply to Kevin WolfInstead of just returning -ENOTSUP, generate a more detailed error.
Unfortunately we don't have a helpful text for features that we don't know yet, so just print the feature mask. It might be useful at least if someone asks for help.
--- block/qed.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
block/qed.c +8 -1
@@ -14,6 +14,7 @@#include "trace.h" #include "qed.h" +#include "qerror.h" static void qed_aio_cancel (BlockDriverAIOCB *blockacb) {
@@ -311,7 +312,13 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)return -EINVAL ; }if (s->header.features & ~QED_FEATURE_MASK ) { -return -ENOTSUP ;/* image uses unsupported feature bits */ +/* image uses unsupported feature bits */ +char buf[64 ]; +snprintf (buf,sizeof (buf),"%" PRIx64, + s->header.features & ~QED_FEATURE_MASK ); +qerror_report (QERR_UNKNOWN_BLOCK_FORMAT_FEATURE , + bs->device_name,"QED" , buf); +return -ENOTSUP ; }if (!qed_is_cluster_size_valid (s->header.cluster_size)) {return -EINVAL ;
Signature · 1 line
1.7.2.3
PATCH 8/9 qemu-img: Improve error messages for failed bdrv_open
In reply to Kevin WolfOutput the error message string of the bdrv_open return code. Also set a non-empty device name for the images because the unknown feature error message includes it.
--- qemu-img.c | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-)
qemu-img.c +7 -3
@@ -213,8 +213,9 @@ static BlockDriverState *bdrv_new_open(const char *filename,BlockDriverState *bs;BlockDriver *drv;char password[256 ]; +int ret; - bs =bdrv_new ("" ); + bs =bdrv_new ("image" );if (fmt) { drv =bdrv_find_format (fmt);
@@ -225,10 +226,13 @@ static BlockDriverState *bdrv_new_open(const char *filename, }else { drv =NULL ; } -if (bdrv_open (bs, filename, flags, drv) <0 ) { -error_report ("Could not open '%s'" , filename); + + ret =bdrv_open (bs, filename, flags, drv); +if (ret <0 ) { +error_report ("Could not open '%s': %s" , filename,strerror (-ret)); goto fail; } +if (bdrv_is_encrypted (bs)) {printf ("Disk image '%s' is encrypted.\n" , filename);if (read_password (password,sizeof (password)) <0 ) {
Signature · 1 line
1.7.2.3
PATCH 9/9 qcow2: Fix order in L2 table COW
In reply to Kevin WolfWhen copying L2 tables (this happens only with internal snapshots), the order wasn't completely safe, so that after a crash you could end up with a L2 table that has too low refcount, possibly leading to corruption in the long run.
This patch puts the operations in the right order: First allocate the new L2 table and replace the reference, and only then decrease the refcount of the old table.
--- block/qcow2-cluster.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-)
block/qcow2-cluster.c +6 -3
@@ -515,13 +515,16 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,return ret; } }else { -/* FIXME Order */ -if (l2_offset) -qcow2_free_clusters (bs, l2_offset, s->l2_size *sizeof (uint64_t )); +/* First allocate a new L2 table (and do COW if needed) */ ret =l2_allocate (bs, l1_index, &l2_table);if (ret <0 ) {return ret; } + +/* Then decrease the refcount of the old table */ +if (l2_offset) { +qcow2_free_clusters (bs, l2_offset, s->l2_size *sizeof (uint64_t )); + } l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED ; }
Signature · 1 line
1.7.2.3
Quoted 22 lines · Kevin Wolf
The following changes since commit
b03088c32f8a88e4674f6cdab47da79ef4188d88:linux-user: Fix possible realloc memory leak (2011-02-09 21:24:05 +0100)
are available in the git repository at:
git://repo.or.cz/qemu/kevin.gitfor-stable-0.14Chunqiang Tang (1):
QCOW2: bug fix - read base image beyond its sizeJes Sorensen (1):
Changesnapshot_blkdevhmp to use correct argument type for deviceKevin Wolf (7):
qcow2: Fix error handling for immediate backing file read failure
qcow2: Fix error handling for reading compressed clusters
qerror: AddQERR_UNKNOWN_BLOCK_FORMAT_FEATURE
qcow2: Report error for version > 2
qed: Report error for unsupported features
qemu-img: Improve error messages for failedbdrv_open
qcow2: Fix order in L2 table COW
Quoted 10 lines
block/qcow2-cluster.c | 13 ++++++++----- block/qcow2.c | 26 +++++++++++++++++++------- block/qed.c | 9 ++++++++- cutils.c | 31 +++++++++++++++++++++++++++++++ hmp-commands.hx | 2 +- qemu-common.h | 2 ++ qemu-img.c | 10 +++++++--- qerror.c | 5 +++++ qerror.h | 3 +++ 9 files changed, 84 insertions(+), 17 deletions(-)
Pulled.
Thanks,
Justin