[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 09/14] qcow2: Allow qcow2_get_cluster_offset to retu
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PATCH 09/14] qcow2: Allow qcow2_get_cluster_offset to return errors |
Date: |
Fri, 28 May 2010 18:46:08 +0200 |
qcow2_get_cluster_offset() looks up a given virtual disk offset and returns the
offset of the corresponding cluster in the image file. Errors (e.g. L2 table
can't be read) are currenctly indicated by a return value of 0, which is
unfortuately the same as for any unallocated cluster. So in effect we can't
check for errors.
This makes the old return value a by-reference parameter and returns the usual
0/-errno error code.
Signed-off-by: Kevin Wolf <address@hidden>
---
block/qcow2-cluster.c | 36 ++++++++++++++++++++++--------------
block/qcow2.c | 16 +++++++++++++---
block/qcow2.h | 4 ++--
3 files changed, 37 insertions(+), 19 deletions(-)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 244b4a7..ea98afc 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -345,7 +345,13 @@ static int qcow_read(BlockDriverState *bs, int64_t
sector_num,
while (nb_sectors > 0) {
n = nb_sectors;
- cluster_offset = qcow2_get_cluster_offset(bs, sector_num << 9, &n);
+
+ ret = qcow2_get_cluster_offset(bs, sector_num << 9, &n,
+ &cluster_offset);
+ if (ret < 0) {
+ return ret;
+ }
+
index_in_cluster = sector_num & (s->cluster_sectors - 1);
if (!cluster_offset) {
if (bs->backing_hd) {
@@ -412,25 +418,25 @@ static int copy_sectors(BlockDriverState *bs, uint64_t
start_sect,
/*
* get_cluster_offset
*
- * For a given offset of the disk image, return cluster offset in
- * qcow2 file.
+ * For a given offset of the disk image, find the cluster offset in
+ * qcow2 file. The offset is stored in *cluster_offset.
*
* on entry, *num is the number of contiguous clusters we'd like to
* access following offset.
*
* on exit, *num is the number of contiguous clusters we can read.
*
- * Return 1, if the offset is found
- * Return 0, otherwise.
+ * Return 0, if the offset is found
+ * Return -errno, otherwise.
*
*/
-uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
- int *num)
+int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
+ int *num, uint64_t *cluster_offset)
{
BDRVQcowState *s = bs->opaque;
unsigned int l1_index, l2_index;
- uint64_t l2_offset, *l2_table, cluster_offset;
+ uint64_t l2_offset, *l2_table;
int l1_bits, c;
unsigned int index_in_cluster, nb_clusters;
uint64_t nb_available, nb_needed;
@@ -454,7 +460,7 @@ uint64_t qcow2_get_cluster_offset(BlockDriverState *bs,
uint64_t offset,
nb_needed = nb_available;
}
- cluster_offset = 0;
+ *cluster_offset = 0;
/* seek the the l2 offset in the l1 table */
@@ -473,16 +479,17 @@ uint64_t qcow2_get_cluster_offset(BlockDriverState *bs,
uint64_t offset,
l2_offset &= ~QCOW_OFLAG_COPIED;
l2_table = l2_load(bs, l2_offset);
- if (l2_table == NULL)
- return 0;
+ if (l2_table == NULL) {
+ return -EIO;
+ }
/* find the cluster offset for the given disk offset */
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
- cluster_offset = be64_to_cpu(l2_table[l2_index]);
+ *cluster_offset = be64_to_cpu(l2_table[l2_index]);
nb_clusters = size_to_clusters(s, nb_needed << 9);
- if (!cluster_offset) {
+ if (!*cluster_offset) {
/* how many empty clusters ? */
c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]);
} else {
@@ -498,7 +505,8 @@ out:
*num = nb_available - index_in_cluster;
- return cluster_offset & ~QCOW_OFLAG_COPIED;
+ *cluster_offset &=~QCOW_OFLAG_COPIED;
+ return 0;
}
/*
diff --git a/block/qcow2.c b/block/qcow2.c
index 5b72758..33fa9a9 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -297,9 +297,15 @@ static int qcow_is_allocated(BlockDriverState *bs, int64_t
sector_num,
int nb_sectors, int *pnum)
{
uint64_t cluster_offset;
+ int ret;
*pnum = nb_sectors;
- cluster_offset = qcow2_get_cluster_offset(bs, sector_num << 9, pnum);
+ /* FIXME We can get errors here, but the bdrv_is_allocated interface can't
+ * pass them on today */
+ ret = qcow2_get_cluster_offset(bs, sector_num << 9, pnum, &cluster_offset);
+ if (ret < 0) {
+ *pnum = 0;
+ }
return (cluster_offset != 0);
}
@@ -409,8 +415,12 @@ static void qcow_aio_read_cb(void *opaque, int ret)
/* prepare next AIO request */
acb->cur_nr_sectors = acb->remaining_sectors;
- acb->cluster_offset = qcow2_get_cluster_offset(bs, acb->sector_num << 9,
- &acb->cur_nr_sectors);
+ ret = qcow2_get_cluster_offset(bs, acb->sector_num << 9,
+ &acb->cur_nr_sectors, &acb->cluster_offset);
+ if (ret < 0) {
+ goto done;
+ }
+
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
if (!acb->cluster_offset) {
diff --git a/block/qcow2.h b/block/qcow2.h
index 01053b7..c59b827 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -196,8 +196,8 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t
sector_num,
int nb_sectors, int enc,
const AES_KEY *key);
-uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
- int *num);
+int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
+ int *num, uint64_t *cluster_offset);
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
int n_start, int n_end, int *num, QCowL2Meta *m);
uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
--
1.6.6.1
- [Qemu-devel] [PULL 00/14] Block patches, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 01/14] qcow2: Clear L2 table cache after write error, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 02/14] qcow2: Fix error handling in l2_allocate, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 03/14] block: Fix multiwrite with overlapping requests, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 04/14] qemu-io: Add multiwrite command, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 05/14] add support for protocol driver create_options, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 06/14] drive: allow rerror, werror and readonly for if=none, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 07/14] posix-aio-compat: Expand tabs that have crept in, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 08/14] block.h: Make BDRV_SECTOR_SIZE 64 bit safe, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 09/14] qcow2: Allow qcow2_get_cluster_offset to return errors,
Kevin Wolf <=
- [Qemu-devel] [PATCH 10/14] qcow2: Change l2_load to return 0/-errno, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 11/14] qcow2: Return right error code in write_refcount_block_entries, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 12/14] qcow2: Fix corruption after refblock allocation, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 13/14] qcow2: Fix corruption after error in update_refcount, Kevin Wolf, 2010/05/28
- [Qemu-devel] [PATCH 14/14] block: Add missing bdrv_delete() for SG_IO BlockDriver in find_image_format(), Kevin Wolf, 2010/05/28
- [Qemu-devel] Re: [PULL 00/14] Block patches, Anthony Liguori, 2010/05/28