Revision 68d000a3 block/qcow2-cluster.c
b/block/qcow2-cluster.c | ||
---|---|---|
367 | 367 |
* |
368 | 368 |
* on exit, *num is the number of contiguous sectors we can read. |
369 | 369 |
* |
370 |
* Return 0, if the offset is found |
|
371 |
* Return -errno, otherwise. |
|
372 |
* |
|
370 |
* Returns the cluster type (QCOW2_CLUSTER_*) on success, -errno in error |
|
371 |
* cases. |
|
373 | 372 |
*/ |
374 |
|
|
375 | 373 |
int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset, |
376 | 374 |
int *num, uint64_t *cluster_offset) |
377 | 375 |
{ |
... | ... | |
407 | 405 |
/* seek the the l2 offset in the l1 table */ |
408 | 406 |
|
409 | 407 |
l1_index = offset >> l1_bits; |
410 |
if (l1_index >= s->l1_size) |
|
408 |
if (l1_index >= s->l1_size) { |
|
409 |
ret = QCOW2_CLUSTER_UNALLOCATED; |
|
411 | 410 |
goto out; |
411 |
} |
|
412 | 412 |
|
413 |
l2_offset = s->l1_table[l1_index]; |
|
414 |
|
|
415 |
/* seek the l2 table of the given l2 offset */ |
|
416 |
|
|
417 |
if (!l2_offset) |
|
413 |
l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK; |
|
414 |
if (!l2_offset) { |
|
415 |
ret = QCOW2_CLUSTER_UNALLOCATED; |
|
418 | 416 |
goto out; |
417 |
} |
|
419 | 418 |
|
420 | 419 |
/* load the l2 table in memory */ |
421 | 420 |
|
422 |
l2_offset &= ~QCOW_OFLAG_COPIED; |
|
423 | 421 |
ret = l2_load(bs, l2_offset, &l2_table); |
424 | 422 |
if (ret < 0) { |
425 | 423 |
return ret; |
... | ... | |
431 | 429 |
*cluster_offset = be64_to_cpu(l2_table[l2_index]); |
432 | 430 |
nb_clusters = size_to_clusters(s, nb_needed << 9); |
433 | 431 |
|
434 |
if (!*cluster_offset) { |
|
432 |
ret = qcow2_get_cluster_type(*cluster_offset); |
|
433 |
switch (ret) { |
|
434 |
case QCOW2_CLUSTER_COMPRESSED: |
|
435 |
/* Compressed clusters can only be processed one by one */ |
|
436 |
c = 1; |
|
437 |
*cluster_offset &= L2E_COMPRESSED_OFFSET_SIZE_MASK; |
|
438 |
break; |
|
439 |
case QCOW2_CLUSTER_UNALLOCATED: |
|
435 | 440 |
/* how many empty clusters ? */ |
436 | 441 |
c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]); |
437 |
} else { |
|
442 |
*cluster_offset = 0; |
|
443 |
break; |
|
444 |
case QCOW2_CLUSTER_NORMAL: |
|
438 | 445 |
/* how many allocated clusters ? */ |
439 | 446 |
c = count_contiguous_clusters(nb_clusters, s->cluster_size, |
440 | 447 |
&l2_table[l2_index], 0, QCOW_OFLAG_COPIED); |
448 |
*cluster_offset &= L2E_OFFSET_MASK; |
|
449 |
break; |
|
441 | 450 |
} |
442 | 451 |
|
443 | 452 |
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table); |
444 | 453 |
|
445 |
nb_available = (c * s->cluster_sectors); |
|
454 |
nb_available = (c * s->cluster_sectors); |
|
455 |
|
|
446 | 456 |
out: |
447 | 457 |
if (nb_available > nb_needed) |
448 | 458 |
nb_available = nb_needed; |
449 | 459 |
|
450 | 460 |
*num = nb_available - index_in_cluster; |
451 | 461 |
|
452 |
*cluster_offset &=~QCOW_OFLAG_COPIED; |
|
453 |
return 0; |
|
462 |
return ret; |
|
454 | 463 |
} |
455 | 464 |
|
456 | 465 |
/* |
Also available in: Unified diff