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 allocated or free clusters.
28 static unsigned int qed_count_contiguous_clusters(BDRVQEDState
*s
,
34 unsigned int end
= MIN(index
+ n
, s
->table_nelems
);
35 uint64_t last
= table
->offsets
[index
];
40 for (i
= index
+ 1; i
< end
; i
++) {
42 /* Counting free clusters */
43 if (table
->offsets
[i
] != 0) {
47 /* Counting allocated clusters */
48 if (table
->offsets
[i
] != last
+ s
->header
.cluster_size
) {
51 last
= table
->offsets
[i
];
65 QEDFindClusterFunc
*cb
;
69 static void qed_find_cluster_cb(void *opaque
, int ret
)
71 QEDFindClusterCB
*find_cluster_cb
= opaque
;
72 BDRVQEDState
*s
= find_cluster_cb
->s
;
73 QEDRequest
*request
= find_cluster_cb
->request
;
83 index
= qed_l2_index(s
, find_cluster_cb
->pos
);
84 n
= qed_bytes_to_clusters(s
,
85 qed_offset_into_cluster(s
, find_cluster_cb
->pos
) +
86 find_cluster_cb
->len
);
87 n
= qed_count_contiguous_clusters(s
, request
->l2_table
->table
,
90 ret
= offset
? QED_CLUSTER_FOUND
: QED_CLUSTER_L2
;
91 len
= MIN(find_cluster_cb
->len
, n
* s
->header
.cluster_size
-
92 qed_offset_into_cluster(s
, find_cluster_cb
->pos
));
94 if (offset
&& !qed_check_cluster_offset(s
, offset
)) {
99 find_cluster_cb
->cb(find_cluster_cb
->opaque
, ret
, offset
, len
);
100 qemu_free(find_cluster_cb
);
104 * Find the offset of a data cluster
107 * @request: L2 cache entry
108 * @pos: Byte position in device
109 * @len: Number of bytes
110 * @cb: Completion function
111 * @opaque: User data for completion function
113 * This function translates a position in the block device to an offset in the
114 * image file. It invokes the cb completion callback to report back the
115 * translated offset or unallocated range in the image file.
117 * If the L2 table exists, request->l2_table points to the L2 table cache entry
118 * and the caller must free the reference when they are finished. The cache
119 * entry is exposed in this way to avoid callers having to read the L2 table
120 * again later during request processing. If request->l2_table is non-NULL it
121 * will be unreferenced before taking on the new cache entry.
123 void qed_find_cluster(BDRVQEDState
*s
, QEDRequest
*request
, uint64_t pos
,
124 size_t len
, QEDFindClusterFunc
*cb
, void *opaque
)
126 QEDFindClusterCB
*find_cluster_cb
;
129 /* Limit length to L2 boundary. Requests are broken up at the L2 boundary
130 * so that a request acts on one L2 table at a time.
132 len
= MIN(len
, (((pos
>> s
->l1_shift
) + 1) << s
->l1_shift
) - pos
);
134 l2_offset
= s
->l1_table
->offsets
[qed_l1_index(s
, pos
)];
136 cb(opaque
, QED_CLUSTER_L1
, 0, len
);
139 if (!qed_check_table_offset(s
, l2_offset
)) {
140 cb(opaque
, -EINVAL
, 0, 0);
144 find_cluster_cb
= qemu_malloc(sizeof(*find_cluster_cb
));
145 find_cluster_cb
->s
= s
;
146 find_cluster_cb
->pos
= pos
;
147 find_cluster_cb
->len
= len
;
148 find_cluster_cb
->cb
= cb
;
149 find_cluster_cb
->opaque
= opaque
;
150 find_cluster_cb
->request
= request
;
152 qed_read_l2_table(s
, request
, l2_offset
,
153 qed_find_cluster_cb
, find_cluster_cb
);