summaryrefslogtreecommitdiff
path: root/block/qed-cluster.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-cluster.c
parentd54f10bba7635b5ad8b750afd2bb2f0f8eb68b45 (diff)
downloadqemu-21df65b6444858ddee3a86d8666571bb41695614.tar.gz
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-cluster.c')
-rw-r--r--block/qed-cluster.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/block/qed-cluster.c b/block/qed-cluster.c
index 0ec864b14c..3e19ad1766 100644
--- a/block/qed-cluster.c
+++ b/block/qed-cluster.c
@@ -23,7 +23,8 @@
* @n: Maximum number of clusters
* @offset: Set to first cluster offset
*
- * This function scans tables for contiguous allocated or free clusters.
+ * This function scans tables for contiguous clusters. A contiguous run of
+ * clusters may be allocated, unallocated, or zero.
*/
static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
QEDTable *table,
@@ -38,9 +39,14 @@ static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
*offset = last;
for (i = index + 1; i < end; i++) {
- if (last == 0) {
- /* Counting free clusters */
- if (table->offsets[i] != 0) {
+ if (qed_offset_is_unalloc_cluster(last)) {
+ /* Counting unallocated clusters */
+ if (!qed_offset_is_unalloc_cluster(table->offsets[i])) {
+ break;
+ }
+ } else if (qed_offset_is_zero_cluster(last)) {
+ /* Counting zero clusters */
+ if (!qed_offset_is_zero_cluster(table->offsets[i])) {
break;
}
} else {
@@ -87,14 +93,19 @@ static void qed_find_cluster_cb(void *opaque, int ret)
n = qed_count_contiguous_clusters(s, request->l2_table->table,
index, n, &offset);
- ret = offset ? QED_CLUSTER_FOUND : QED_CLUSTER_L2;
- len = MIN(find_cluster_cb->len, n * s->header.cluster_size -
- qed_offset_into_cluster(s, find_cluster_cb->pos));
-
- if (offset && !qed_check_cluster_offset(s, offset)) {
+ if (qed_offset_is_unalloc_cluster(offset)) {
+ ret = QED_CLUSTER_L2;
+ } else if (qed_offset_is_zero_cluster(offset)) {
+ ret = QED_CLUSTER_ZERO;
+ } else if (qed_check_cluster_offset(s, offset)) {
+ ret = QED_CLUSTER_FOUND;
+ } else {
ret = -EINVAL;
}
+ len = MIN(find_cluster_cb->len, n * s->header.cluster_size -
+ qed_offset_into_cluster(s, find_cluster_cb->pos));
+
out:
find_cluster_cb->cb(find_cluster_cb->opaque, ret, offset, len);
qemu_free(find_cluster_cb);
@@ -132,7 +143,7 @@ void qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos,
len = MIN(len, (((pos >> s->l1_shift) + 1) << s->l1_shift) - pos);
l2_offset = s->l1_table->offsets[qed_l1_index(s, pos)];
- if (!l2_offset) {
+ if (qed_offset_is_unalloc_cluster(l2_offset)) {
cb(opaque, QED_CLUSTER_L1, 0, len);
return;
}