|
|
298366 |
From da4e203efa76f2d2ee0a17670c241881963d033d Mon Sep 17 00:00:00 2001
|
|
|
298366 |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
298366 |
Date: Wed, 4 Sep 2013 19:00:25 +0200
|
|
|
298366 |
Subject: [PATCH] block: expect errors from bdrv_co_is_allocated
|
|
|
298366 |
|
|
|
298366 |
Some bdrv_is_allocated callers do not expect errors, but the fallback
|
|
|
298366 |
in qcow2.c might make other callers trip on assertion failures or
|
|
|
298366 |
infinite loops.
|
|
|
298366 |
|
|
|
298366 |
Fix the callers to always look for errors.
|
|
|
298366 |
|
|
|
298366 |
Cc: qemu-stable@nongnu.org
|
|
|
298366 |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
298366 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
298366 |
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
298366 |
(cherry picked from commit d663640c04f2aab810915c556390211d75457704)
|
|
|
298366 |
|
|
|
298366 |
Conflicts:
|
|
|
298366 |
|
|
|
298366 |
block/cow.c
|
|
|
298366 |
|
|
|
298366 |
*modified to avoid dependency on upstream's e641c1e8
|
|
|
298366 |
|
|
|
298366 |
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
|
|
|
298366 |
---
|
|
|
298366 |
block.c | 7 +++++--
|
|
|
298366 |
block/cow.c | 6 +++++-
|
|
|
298366 |
block/qcow2.c | 4 +---
|
|
|
298366 |
block/stream.c | 2 +-
|
|
|
298366 |
qemu-img.c | 16 ++++++++++++++--
|
|
|
298366 |
qemu-io-cmds.c | 4 ++++
|
|
|
298366 |
6 files changed, 30 insertions(+), 9 deletions(-)
|
|
|
298366 |
|
|
|
298366 |
diff --git a/block.c b/block.c
|
|
|
298366 |
index d5ce8d3..8ce8b91 100644
|
|
|
298366 |
--- a/block.c
|
|
|
298366 |
+++ b/block.c
|
|
|
298366 |
@@ -1803,8 +1803,11 @@ int bdrv_commit(BlockDriverState *bs)
|
|
|
298366 |
buf = g_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
|
|
|
298366 |
|
|
|
298366 |
for (sector = 0; sector < total_sectors; sector += n) {
|
|
|
298366 |
- if (bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) {
|
|
|
298366 |
-
|
|
|
298366 |
+ ret = bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n);
|
|
|
298366 |
+ if (ret < 0) {
|
|
|
298366 |
+ goto ro_cleanup;
|
|
|
298366 |
+ }
|
|
|
298366 |
+ if (ret) {
|
|
|
298366 |
if (bdrv_read(bs, sector, buf, n) != 0) {
|
|
|
298366 |
ret = -EIO;
|
|
|
298366 |
goto ro_cleanup;
|
|
|
298366 |
diff --git a/block/cow.c b/block/cow.c
|
|
|
298366 |
index 1cc2e89..e1b73d6 100644
|
|
|
298366 |
--- a/block/cow.c
|
|
|
298366 |
+++ b/block/cow.c
|
|
|
298366 |
@@ -189,7 +189,11 @@ static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num,
|
|
|
298366 |
int ret, n;
|
|
|
298366 |
|
|
|
298366 |
while (nb_sectors > 0) {
|
|
|
298366 |
- if (bdrv_co_is_allocated(bs, sector_num, nb_sectors, &n)) {
|
|
|
298366 |
+ ret = bdrv_co_is_allocated(bs, sector_num, nb_sectors, &n);
|
|
|
298366 |
+ if (ret < 0) {
|
|
|
298366 |
+ return ret;
|
|
|
298366 |
+ }
|
|
|
298366 |
+ if (ret) {
|
|
|
298366 |
ret = bdrv_pread(bs->file,
|
|
|
298366 |
s->cow_sectors_offset + sector_num * 512,
|
|
|
298366 |
buf, n * 512);
|
|
|
298366 |
diff --git a/block/qcow2.c b/block/qcow2.c
|
|
|
298366 |
index 3376901..7f7282e 100644
|
|
|
298366 |
--- a/block/qcow2.c
|
|
|
298366 |
+++ b/block/qcow2.c
|
|
|
298366 |
@@ -648,13 +648,11 @@ static int coroutine_fn qcow2_co_is_allocated(BlockDriverState *bs,
|
|
|
298366 |
int ret;
|
|
|
298366 |
|
|
|
298366 |
*pnum = nb_sectors;
|
|
|
298366 |
- /* FIXME We can get errors here, but the bdrv_co_is_allocated interface
|
|
|
298366 |
- * can't pass them on today */
|
|
|
298366 |
qemu_co_mutex_lock(&s->lock);
|
|
|
298366 |
ret = qcow2_get_cluster_offset(bs, sector_num << 9, pnum, &cluster_offset);
|
|
|
298366 |
qemu_co_mutex_unlock(&s->lock);
|
|
|
298366 |
if (ret < 0) {
|
|
|
298366 |
- *pnum = 0;
|
|
|
298366 |
+ return ret;
|
|
|
298366 |
}
|
|
|
298366 |
|
|
|
298366 |
return (cluster_offset != 0) || (ret == QCOW2_CLUSTER_ZERO);
|
|
|
298366 |
diff --git a/block/stream.c b/block/stream.c
|
|
|
298366 |
index 7fe9e48..4e8d177 100644
|
|
|
298366 |
--- a/block/stream.c
|
|
|
298366 |
+++ b/block/stream.c
|
|
|
298366 |
@@ -120,7 +120,7 @@ wait:
|
|
|
298366 |
if (ret == 1) {
|
|
|
298366 |
/* Allocated in the top, no need to copy. */
|
|
|
298366 |
copy = false;
|
|
|
298366 |
- } else {
|
|
|
298366 |
+ } else if (ret >= 0) {
|
|
|
298366 |
/* Copy if allocated in the intermediate images. Limit to the
|
|
|
298366 |
* known-unallocated area [sector_num, sector_num+n). */
|
|
|
298366 |
ret = bdrv_co_is_allocated_above(bs->backing_hd, base,
|
|
|
298366 |
diff --git a/qemu-img.c b/qemu-img.c
|
|
|
298366 |
index b9a848d..b01998b 100644
|
|
|
298366 |
--- a/qemu-img.c
|
|
|
298366 |
+++ b/qemu-img.c
|
|
|
298366 |
@@ -1485,8 +1485,15 @@ static int img_convert(int argc, char **argv)
|
|
|
298366 |
are present in both the output's and input's base images (no
|
|
|
298366 |
need to copy them). */
|
|
|
298366 |
if (out_baseimg) {
|
|
|
298366 |
- if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
|
|
|
298366 |
- n, &n1)) {
|
|
|
298366 |
+ ret = bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
|
|
|
298366 |
+ n, &n1;;
|
|
|
298366 |
+ if (ret < 0) {
|
|
|
298366 |
+ error_report("error while reading metadata for sector "
|
|
|
298366 |
+ "%" PRId64 ": %s",
|
|
|
298366 |
+ sector_num - bs_offset, strerror(-ret));
|
|
|
298366 |
+ goto out;
|
|
|
298366 |
+ }
|
|
|
298366 |
+ if (!ret) {
|
|
|
298366 |
sector_num += n1;
|
|
|
298366 |
continue;
|
|
|
298366 |
}
|
|
|
298366 |
@@ -2076,6 +2083,11 @@ static int img_rebase(int argc, char **argv)
|
|
|
298366 |
|
|
|
298366 |
/* If the cluster is allocated, we don't need to take action */
|
|
|
298366 |
ret = bdrv_is_allocated(bs, sector, n, &n);
|
|
|
298366 |
+ if (ret < 0) {
|
|
|
298366 |
+ error_report("error while reading image metadata: %s",
|
|
|
298366 |
+ strerror(-ret));
|
|
|
298366 |
+ goto out;
|
|
|
298366 |
+ }
|
|
|
298366 |
if (ret) {
|
|
|
298366 |
continue;
|
|
|
298366 |
}
|
|
|
298366 |
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
|
|
|
298366 |
index ffbcf31..ffe48ad 100644
|
|
|
298366 |
--- a/qemu-io-cmds.c
|
|
|
298366 |
+++ b/qemu-io-cmds.c
|
|
|
298366 |
@@ -1829,6 +1829,10 @@ static int alloc_f(BlockDriverState *bs, int argc, char **argv)
|
|
|
298366 |
sector_num = offset >> 9;
|
|
|
298366 |
while (remaining) {
|
|
|
298366 |
ret = bdrv_is_allocated(bs, sector_num, remaining, &num);
|
|
|
298366 |
+ if (ret < 0) {
|
|
|
298366 |
+ printf("is_allocated failed: %s\n", strerror(-ret));
|
|
|
298366 |
+ return 0;
|
|
|
298366 |
+ }
|
|
|
298366 |
sector_num += num;
|
|
|
298366 |
remaining -= num;
|
|
|
298366 |
if (ret) {
|