2 * QEMU Enhanced Disk Format Cluster functions
4 * Copyright IBM, Corp. 2010
7 * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
8 * Anthony Liguori <aliguori@us.ibm.com>
10 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
11 * See the COPYING.LIB file in the top-level directory.
18 * Count the number of contiguous data clusters
22 * @index: First cluster index
23 * @n: Maximum number of clusters
24 * @offset: Set to first cluster offset
26 * This function scans tables for contiguous clusters. A contiguous run of
27 * clusters may be allocated, unallocated, or zero.
29 static unsigned int qed_count_contiguous_clusters(BDRVQEDState
*s
,
35 unsigned int end
= MIN(index
+ n
, s
->table_nelems
);
36 uint64_t last
= table
->offsets
[index
];
41 for (i
= index
+ 1; i
< end
; i
++) {
42 if (qed_offset_is_unalloc_cluster(last
)) {
43 /* Counting unallocated clusters */
44 if (!qed_offset_is_unalloc_cluster(table
->offsets
[i
])) {
47 } else if (qed_offset_is_zero_cluster(last
)) {
48 /* Counting zero clusters */
49 if (!qed_offset_is_zero_cluster(table
->offsets
[i
])) {
53 /* Counting allocated clusters */
54 if (table
->offsets
[i
] != last
+ s
->header
.cluster_size
) {
57 last
= table
->offsets
[i
];
71 QEDFindClusterFunc
*cb
;
75 static void qed_find_cluster_cb(void *opaque
, int ret
)
77 QEDFindClusterCB
*find_cluster_cb
= opaque
;
78 BDRVQEDState
*s
= find_cluster_cb
->s
;
79 QEDRequest
*request
= find_cluster_cb
->request
;
89 index
= qed_l2_index(s
, find_cluster_cb
->pos
);
90 n
= qed_bytes_to_clusters(s
,
91 qed_offset_into_cluster(s
, find_cluster_cb
->pos
) +
92 find_cluster_cb
->len
);
93 n
= qed_count_contiguous_clusters(s
, request
->l2_table
->table
,
96 if (qed_offset_is_unalloc_cluster(offset
)) {
98 } else if (qed_offset_is_zero_cluster(offset
)) {
99 ret
= QED_CLUSTER_ZERO
;
100 } else if (qed_check_cluster_offset(s
, offset
)) {
101 ret
= QED_CLUSTER_FOUND
;
106 len
= MIN(find_cluster_cb
->len
, n
* s
->header
.cluster_size
-
107 qed_offset_into_cluster(s
, find_cluster_cb
->pos
));
110 find_cluster_cb
->cb(find_cluster_cb
->opaque
, ret
, offset
, len
);
111 g_free(find_cluster_cb
);
115 * Find the offset of a data cluster
118 * @request: L2 cache entry
119 * @pos: Byte position in device
120 * @len: Number of bytes
121 * @cb: Completion function
122 * @opaque: User data for completion function
124 * This function translates a position in the block device to an offset in the
125 * image file. It invokes the cb completion callback to report back the
126 * translated offset or unallocated range in the image file.
128 * If the L2 table exists, request->l2_table points to the L2 table cache entry
129 * and the caller must free the reference when they are finished. The cache
130 * entry is exposed in this way to avoid callers having to read the L2 table
131 * again later during request processing. If request->l2_table is non-NULL it
132 * will be unreferenced before taking on the new cache entry.
134 void qed_find_cluster(BDRVQEDState
*s
, QEDRequest
*request
, uint64_t pos
,
135 size_t len
, QEDFindClusterFunc
*cb
, void *opaque
)
137 QEDFindClusterCB
*find_cluster_cb
;
140 /* Limit length to L2 boundary. Requests are broken up at the L2 boundary
141 * so that a request acts on one L2 table at a time.
143 len
= MIN(len
, (((pos
>> s
->l1_shift
) + 1) << s
->l1_shift
) - pos
);
145 l2_offset
= s
->l1_table
->offsets
[qed_l1_index(s
, pos
)];
146 if (qed_offset_is_unalloc_cluster(l2_offset
)) {
147 cb(opaque
, QED_CLUSTER_L1
, 0, len
);
150 if (!qed_check_table_offset(s
, l2_offset
)) {
151 cb(opaque
, -EINVAL
, 0, 0);
155 find_cluster_cb
= g_malloc(sizeof(*find_cluster_cb
));
156 find_cluster_cb
->s
= s
;
157 find_cluster_cb
->pos
= pos
;
158 find_cluster_cb
->len
= len
;
159 find_cluster_cb
->cb
= cb
;
160 find_cluster_cb
->opaque
= opaque
;
161 find_cluster_cb
->request
= request
;
163 qed_read_l2_table(s
, request
, l2_offset
,
164 qed_find_cluster_cb
, find_cluster_cb
);