summaryrefslogtreecommitdiff
path: root/block/qed.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2010-12-17 15:58:22 +0000
committerKevin Wolf <kwolf@redhat.com>2011-04-13 12:06:41 +0200
commit21df65b6444858ddee3a86d8666571bb41695614 (patch)
tree142793b8ae8e6fef8b1aa412cf39e2340091fdf9 /block/qed.c
parentd54f10bba7635b5ad8b750afd2bb2f0f8eb68b45 (diff)
qed: Add support for zero clusters
Zero clusters are similar to unallocated clusters except instead of reading their value from a backing file when one is available, the cluster is always read as zero. This implements read support only. At this stage, QED will never write a zero cluster. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block/qed.c')
-rw-r--r--block/qed.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/block/qed.c b/block/qed.c
index 75ae2440ee..c8c5930448 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -573,7 +573,7 @@ static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t l
{
QEDIsAllocatedCB *cb = opaque;
*cb->pnum = len / BDRV_SECTOR_SIZE;
- cb->is_allocated = ret == QED_CLUSTER_FOUND;
+ cb->is_allocated = (ret == QED_CLUSTER_FOUND || ret == QED_CLUSTER_ZERO);
}
static int bdrv_qed_is_allocated(BlockDriverState *bs, int64_t sector_num,
@@ -745,7 +745,10 @@ static void qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos,
* @table: L2 table
* @index: First cluster index
* @n: Number of contiguous clusters
- * @cluster: First cluster byte offset in image file
+ * @cluster: First cluster offset
+ *
+ * The cluster offset may be an allocated byte offset in the image file, the
+ * zero cluster marker, or the unallocated cluster marker.
*/
static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
unsigned int n, uint64_t cluster)
@@ -753,7 +756,10 @@ static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
int i;
for (i = index; i < index + n; i++) {
table->offsets[i] = cluster;
- cluster += s->header.cluster_size;
+ if (!qed_offset_is_unalloc_cluster(cluster) &&
+ !qed_offset_is_zero_cluster(cluster)) {
+ cluster += s->header.cluster_size;
+ }
}
}
@@ -1075,6 +1081,7 @@ static void qed_aio_write_data(void *opaque, int ret,
case QED_CLUSTER_L2:
case QED_CLUSTER_L1:
+ case QED_CLUSTER_ZERO:
qed_aio_write_alloc(acb, len);
break;
@@ -1114,8 +1121,12 @@ static void qed_aio_read_data(void *opaque, int ret,
qemu_iovec_copy(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len);
- /* Handle backing file and unallocated sparse hole reads */
- if (ret != QED_CLUSTER_FOUND) {
+ /* Handle zero cluster and backing file reads */
+ if (ret == QED_CLUSTER_ZERO) {
+ qemu_iovec_memset(&acb->cur_qiov, 0, acb->cur_qiov.size);
+ qed_aio_next_io(acb, 0);
+ return;
+ } else if (ret != QED_CLUSTER_FOUND) {
qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov,
qed_aio_next_io, acb);
return;