Commit 5d4cbd78aa33f6d034a62207c99ad0b64af44621
1 parent
f18be901
block-qcow2: keep highest allocated byte (Uri Lublin)
We want to know the highest written offset for qcow2 images. This gives a pretty good (and easy to calculate) estimation to how much more allocation can be done for the block device. It can be usefull for allocating more diskspace for that image (if possible, e.g. lvm) before we run out-of-disk-space Signed-off-by: Uri Lublin <uril@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6404 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
34 additions
and
0 deletions
block-qcow2.c
... | ... | @@ -143,6 +143,9 @@ typedef struct BDRVQcowState { |
143 | 143 | uint32_t crypt_method_header; |
144 | 144 | AES_KEY aes_encrypt_key; |
145 | 145 | AES_KEY aes_decrypt_key; |
146 | + | |
147 | + int64_t highest_alloc; /* highest cluester allocated (in clusters) */ | |
148 | + | |
146 | 149 | uint64_t snapshots_offset; |
147 | 150 | int snapshots_size; |
148 | 151 | int nb_snapshots; |
... | ... | @@ -170,6 +173,8 @@ static void free_clusters(BlockDriverState *bs, |
170 | 173 | #ifdef DEBUG_ALLOC |
171 | 174 | static void check_refcounts(BlockDriverState *bs); |
172 | 175 | #endif |
176 | +static void scan_refcount(BlockDriverState *bs, int64_t *high); | |
177 | + | |
173 | 178 | |
174 | 179 | static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) |
175 | 180 | { |
... | ... | @@ -278,6 +283,8 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags) |
278 | 283 | if (refcount_init(bs) < 0) |
279 | 284 | goto fail; |
280 | 285 | |
286 | + scan_refcount(bs, &s->highest_alloc); | |
287 | + | |
281 | 288 | /* read the backing file name */ |
282 | 289 | if (header.backing_file_offset != 0) { |
283 | 290 | len = header.backing_file_size; |
... | ... | @@ -2206,6 +2213,29 @@ static int load_refcount_block(BlockDriverState *bs, |
2206 | 2213 | return 0; |
2207 | 2214 | } |
2208 | 2215 | |
2216 | +static void scan_refcount(BlockDriverState *bs, int64_t *high) | |
2217 | +{ | |
2218 | + BDRVQcowState *s = bs->opaque; | |
2219 | + int64_t refcnt_index, cluster_index, cluster_end, h = 0; | |
2220 | + | |
2221 | + for (refcnt_index=0; refcnt_index < s->refcount_table_size; refcnt_index++){ | |
2222 | + if (s->refcount_table[refcnt_index] == 0) { | |
2223 | + continue; | |
2224 | + } | |
2225 | + cluster_index = refcnt_index << (s->cluster_bits - REFCOUNT_SHIFT); | |
2226 | + cluster_end = (refcnt_index + 1) << (s->cluster_bits - REFCOUNT_SHIFT); | |
2227 | + for ( ; cluster_index < cluster_end; cluster_index++) { | |
2228 | + if (get_refcount(bs, cluster_index) == 0) | |
2229 | + /* do nothing -- reserved for free counting */; | |
2230 | + else | |
2231 | + h = cluster_index; | |
2232 | + } | |
2233 | + } | |
2234 | + | |
2235 | + if (high) | |
2236 | + *high = (h+1); | |
2237 | +} | |
2238 | + | |
2209 | 2239 | static int get_refcount(BlockDriverState *bs, int64_t cluster_index) |
2210 | 2240 | { |
2211 | 2241 | BDRVQcowState *s = bs->opaque; |
... | ... | @@ -2246,6 +2276,10 @@ retry: |
2246 | 2276 | size, |
2247 | 2277 | (s->free_cluster_index - nb_clusters) << s->cluster_bits); |
2248 | 2278 | #endif |
2279 | + | |
2280 | + if (s->highest_alloc < s->free_cluster_index) | |
2281 | + s->highest_alloc = s->free_cluster_index; | |
2282 | + | |
2249 | 2283 | return (s->free_cluster_index - nb_clusters) << s->cluster_bits; |
2250 | 2284 | } |
2251 | 2285 | ... | ... |