Skip to contentSkip to conversation

Block patches for stable-0.14

GIT PULL New Kevin Wolf 2 participants 11 messages Feb 11, 2011

lore
Share & tools
lore

Kevin Wolf

author
#0 lore raw

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(-)
author
#1 lore raw

PATCH 1/9 Change snapshot_blkdev hmp to use correct argument type for device

From: Jes Sorensen <[email protected]>

Pointed out by Markus

(cherry picked from commit 982aa95532a3a7b549695d5b3e18442975eecfb5)
---
 hmp-commands.hx |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
hmp-commands.hx +1 -1
index 38e1eb7..372bef4 100644
@@ -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
author
#2 lore raw

PATCH 2/9 QCOW2: bug fix - read base image beyond its size

In reply to Kevin Wolf

From: 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

(cherry picked from commit e0d9c6f93729c9bfc98fcafcd73098bb8e131aeb)
---
 block/qcow2.c |    5 ++---
 cutils.c      |   31 +++++++++++++++++++++++++++++++
 qemu-common.h |    2 ++
 3 files changed, 35 insertions(+), 3 deletions(-)
block/qcow2.c +2 -3
index a1773e4..28338bf 100644
@@ -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
index 8d562b2..f9a7e36 100644
@@ -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
index c7ff280..cb4b7e0 100644
@@ -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
author
#3 lore raw

PATCH 3/9 qcow2: Fix error handling for immediate backing file read failure

In reply to Kevin Wolf

Requests could return success even though they failed when bdrv_aio_readv returned NULL for a backing file read.

(cherry picked from commit 3ab4c7e92d39d40e6dc0bdb1c2320889543691cb)
---
 block/qcow2.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)
block/qcow2.c +3 -1
index 28338bf..647c2a4 100644
@@ -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
author
#4 lore raw

PATCH 4/9 qcow2: Fix error handling for reading compressed clusters

In reply to Kevin Wolf

When reading a compressed cluster failed, qcow2 falsely returned success.

(cherry picked from commit 8af364884355b3f0c5d60a2d2f427927739658ea)
---
 block/qcow2-cluster.c |    4 ++--
 block/qcow2.c         |    4 +++-
 2 files changed, 5 insertions(+), 3 deletions(-)
block/qcow2-cluster.c +2 -2
index 5fb8c66..437aaa8 100644
@@ -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
index 647c2a4..551b3c2 100644
@@ -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
author
#5 lore raw

PATCH 5/9 qerror: Add QERR_UNKNOWN_BLOCK_FORMAT_FEATURE

In reply to Kevin Wolf
(cherry picked from commit f54e3641122e51c6343d587805422642f307462e)
---
 qerror.c |    5 +++++
 qerror.h |    3 +++
 2 files changed, 8 insertions(+), 0 deletions(-)
qerror.c +5 -0
index 9d0cdeb..4855604 100644
@@ -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
index b0f69da..f732d45 100644
@@ -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
author
#6 lore raw

PATCH 6/9 qcow2: Report error for version > 2

In reply to Kevin Wolf

The 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.

(cherry picked from commit e8cdcec123facf0ed273d941caeeeb9b08f14955)
---
 block/qcow2.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)
block/qcow2.c +11 -2
index 551b3c2..75b8bec 100644
@@ -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
author
#7 lore raw

PATCH 7/9 qed: Report error for unsupported features

In reply to Kevin Wolf

Instead 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.

(cherry picked from commit 10b758e85c9b38b4b370cff81435f6ed26024a26)
---
 block/qed.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
block/qed.c +8 -1
index 3273448..75ae244 100644
@@ -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
author
#8 lore raw

PATCH 8/9 qemu-img: Improve error messages for failed bdrv_open

In reply to Kevin Wolf

Output 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.

(cherry picked from commit b9eaf9ecb15a9c69a592f386159163d5efc3b919)
---
 qemu-img.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)
qemu-img.c +7 -3
index 4a37358..7e3cc4c 100644
@@ -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
author
#9 lore raw

PATCH 9/9 qcow2: Fix order in L2 table COW

In reply to Kevin Wolf

When 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.

(cherry picked from commit 16fde5f2c2788232b16c06d34d0459a5c1ec1f6c)
---
 block/qcow2-cluster.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)
block/qcow2-cluster.c +6 -3
index 437aaa8..750abe3 100644
@@ -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
#10 lore raw
In reply to Kevin Wolf
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.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

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