Commit 5d4cbd78aa33f6d034a62207c99ad0b64af44621

Authored by aliguori
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  
... ...