[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 12/19] qcow2: Support reading zero clusters
From: |
Kevin Wolf |
Subject: |
[Qemu-devel] [PATCH 12/19] qcow2: Support reading zero clusters |
Date: |
Thu, 12 Apr 2012 17:01:13 +0200 |
This adds support for reading zero clusters in version 3 images.
Signed-off-by: Kevin Wolf <address@hidden>
---
block/qcow2-cluster.c | 17 +++++++++++++----
block/qcow2-refcount.c | 7 +++++++
block/qcow2.c | 8 ++++++++
block/qcow2.h | 5 +++++
4 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index b120b92..4853f1f 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -453,6 +453,12 @@ int qcow2_get_cluster_offset(BlockDriverState *bs,
uint64_t offset,
c = 1;
*cluster_offset &= L2E_COMPRESSED_OFFSET_SIZE_MASK;
break;
+ case QCOW2_CLUSTER_ZERO:
+ c = count_contiguous_clusters(nb_clusters, s->cluster_size,
+ &l2_table[l2_index], 0,
+ QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
+ *cluster_offset = 0;
+ break;
case QCOW2_CLUSTER_UNALLOCATED:
/* how many empty clusters ? */
c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]);
@@ -461,7 +467,8 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t
offset,
case QCOW2_CLUSTER_NORMAL:
/* how many allocated clusters ? */
c = count_contiguous_clusters(nb_clusters, s->cluster_size,
- &l2_table[l2_index], 0, QCOW_OFLAG_COMPRESSED);
+ &l2_table[l2_index], 0,
+ QCOW_OFLAG_COMPRESSED | QCOW_OFLAG_ZERO);
*cluster_offset &= L2E_OFFSET_MASK;
break;
}
@@ -720,6 +727,7 @@ static int count_cow_clusters(BDRVQcowState *s, int
nb_clusters,
break;
case QCOW2_CLUSTER_UNALLOCATED:
case QCOW2_CLUSTER_COMPRESSED:
+ case QCOW2_CLUSTER_ZERO:
break;
default:
abort();
@@ -868,9 +876,10 @@ again:
&& (cluster_offset & QCOW_OFLAG_COPIED))
{
/* We keep all QCOW_OFLAG_COPIED clusters */
- keep_clusters = count_contiguous_clusters(nb_clusters, s->cluster_size,
- &l2_table[l2_index], 0,
- QCOW_OFLAG_COPIED);
+ keep_clusters =
+ count_contiguous_clusters(nb_clusters, s->cluster_size,
+ &l2_table[l2_index], 0,
+ QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
assert(keep_clusters <= nb_clusters);
nb_clusters -= keep_clusters;
} else {
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index c5d3171..60e2fb5 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -697,6 +697,7 @@ void qcow2_free_any_clusters(BlockDriverState *bs,
nb_clusters << s->cluster_bits);
break;
case QCOW2_CLUSTER_UNALLOCATED:
+ case QCOW2_CLUSTER_ZERO:
break;
default:
abort();
@@ -967,6 +968,12 @@ static int check_refcounts_l2(BlockDriverState *bs,
BdrvCheckResult *res,
l2_entry & ~511, nb_csectors * 512);
break;
+ case QCOW2_CLUSTER_ZERO:
+ if ((l2_entry & L2E_OFFSET_MASK) == 0) {
+ break;
+ }
+ /* fall through */
+
case QCOW2_CLUSTER_NORMAL:
{
/* QCOW_OFLAG_COPIED must be set iff refcount == 1 */
diff --git a/block/qcow2.c b/block/qcow2.c
index c1f113d..aef8282 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -536,6 +536,14 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState
*bs, int64_t sector_num,
}
break;
+ case QCOW2_CLUSTER_ZERO:
+ if (s->qcow_version < 3) {
+ ret = -EIO;
+ goto fail;
+ }
+ qemu_iovec_memset(&hd_qiov, 0, 512 * cur_nr_sectors);
+ break;
+
case QCOW2_CLUSTER_COMPRESSED:
/* add AIO support for compressed blocks ? */
ret = qcow2_decompress_cluster(bs, cluster_offset);
diff --git a/block/qcow2.h b/block/qcow2.h
index 9757c0b..9817c81 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -43,6 +43,8 @@
#define QCOW_OFLAG_COPIED (1LL << 63)
/* indicate that the cluster is compressed (they never have the copied flag) */
#define QCOW_OFLAG_COMPRESSED (1LL << 62)
+/* The cluster reads as all zeros */
+#define QCOW_OFLAG_ZERO (1LL << 0)
#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */
@@ -184,6 +186,7 @@ enum {
QCOW2_CLUSTER_UNALLOCATED,
QCOW2_CLUSTER_NORMAL,
QCOW2_CLUSTER_COMPRESSED,
+ QCOW2_CLUSTER_ZERO
};
#define L1E_OFFSET_MASK 0x00ffffffffffff00ULL
@@ -213,6 +216,8 @@ static inline int qcow2_get_cluster_type(uint64_t l2_entry)
{
if (l2_entry & QCOW_OFLAG_COMPRESSED) {
return QCOW2_CLUSTER_COMPRESSED;
+ } else if (l2_entry & QCOW_OFLAG_ZERO) {
+ return QCOW2_CLUSTER_ZERO;
} else if (!(l2_entry & L2E_OFFSET_MASK)) {
return QCOW2_CLUSTER_UNALLOCATED;
} else {
--
1.7.6.5
- [Qemu-devel] [PATCH 02/19] qcow2: Save disk size in snapshot header, (continued)
- [Qemu-devel] [PATCH 02/19] qcow2: Save disk size in snapshot header, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 09/19] qcow2: Ignore reserved bits in refcount table entries, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 07/19] qcow2: Refactor qcow2_free_any_clusters, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 10/19] qcow2: Ignore reserved bits in check_refcounts, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 18/19] [RFC] Possible qcow2 specification extensions, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 06/19] qcow2: Ignore reserved bits in L1/L2 entries, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 11/19] qcow2: Version 3 images, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 08/19] qcow2: Simplify count_cow_clusters, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 12/19] qcow2: Support reading zero clusters,
Kevin Wolf <=
- [Qemu-devel] [PATCH 14/19] qemu-iotests: add a simple test for write_zeroes, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 15/19] qemu-iotests: Test backing file COW with zero clusters, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 17/19] qemu-iotests: Add -o and make v3 the default for qcow2, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 13/19] qcow2: Support for feature table header extension, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 17.5/19] qemu-iotests: Fix test 031 for qcow2 v3 support, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 16/19] qcow2: Zero write support, Kevin Wolf, 2012/04/12
- [Qemu-devel] [PATCH 19/19] [RFC] Add feature table entries for new flags, Kevin Wolf, 2012/04/12