Commit 44ff42de1c2df7255108d88e98c2bfe6e7bdbf88
Committed by
Anthony Liguori
1 parent
ade40677
qcow2: Refactor update_refcount
This is a preparation patch with no functional changes. It moves the allocation of new refcounts block to a new function and makes update_cluster_refcount (for one cluster) call update_refcount (for multiple clusters) instead the other way round. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing
1 changed file
with
56 additions
and
30 deletions
block/qcow2.c
| ... | ... | @@ -173,7 +173,7 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index); |
| 173 | 173 | static int update_cluster_refcount(BlockDriverState *bs, |
| 174 | 174 | int64_t cluster_index, |
| 175 | 175 | int addend); |
| 176 | -static void update_refcount(BlockDriverState *bs, | |
| 176 | +static int update_refcount(BlockDriverState *bs, | |
| 177 | 177 | int64_t offset, int64_t length, |
| 178 | 178 | int addend); |
| 179 | 179 | static int64_t alloc_clusters(BlockDriverState *bs, int64_t size); |
| ... | ... | @@ -2508,29 +2508,25 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size) |
| 2508 | 2508 | return -EIO; |
| 2509 | 2509 | } |
| 2510 | 2510 | |
| 2511 | -/* addend must be 1 or -1 */ | |
| 2512 | -/* XXX: cache several refcount block clusters ? */ | |
| 2513 | -static int update_cluster_refcount(BlockDriverState *bs, | |
| 2514 | - int64_t cluster_index, | |
| 2515 | - int addend) | |
| 2511 | + | |
| 2512 | +static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index) | |
| 2516 | 2513 | { |
| 2517 | 2514 | BDRVQcowState *s = bs->opaque; |
| 2518 | 2515 | int64_t offset, refcount_block_offset; |
| 2519 | - int ret, refcount_table_index, block_index, refcount; | |
| 2516 | + int ret, refcount_table_index; | |
| 2520 | 2517 | uint64_t data64; |
| 2521 | 2518 | |
| 2519 | + /* Find L1 index and grow refcount table if needed */ | |
| 2522 | 2520 | refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); |
| 2523 | 2521 | if (refcount_table_index >= s->refcount_table_size) { |
| 2524 | - if (addend < 0) | |
| 2525 | - return -EINVAL; | |
| 2526 | 2522 | ret = grow_refcount_table(bs, refcount_table_index + 1); |
| 2527 | 2523 | if (ret < 0) |
| 2528 | 2524 | return ret; |
| 2529 | 2525 | } |
| 2526 | + | |
| 2527 | + /* Load or allocate the refcount block */ | |
| 2530 | 2528 | refcount_block_offset = s->refcount_table[refcount_table_index]; |
| 2531 | 2529 | if (!refcount_block_offset) { |
| 2532 | - if (addend < 0) | |
| 2533 | - return -EINVAL; | |
| 2534 | 2530 | /* create a new refcount block */ |
| 2535 | 2531 | /* Note: we cannot update the refcount now to avoid recursion */ |
| 2536 | 2532 | offset = alloc_clusters_noref(bs, s->cluster_size); |
| ... | ... | @@ -2555,25 +2551,28 @@ static int update_cluster_refcount(BlockDriverState *bs, |
| 2555 | 2551 | return -EIO; |
| 2556 | 2552 | } |
| 2557 | 2553 | } |
| 2558 | - /* we can update the count and save it */ | |
| 2559 | - block_index = cluster_index & | |
| 2560 | - ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); | |
| 2561 | - refcount = be16_to_cpu(s->refcount_block_cache[block_index]); | |
| 2562 | - refcount += addend; | |
| 2563 | - if (refcount < 0 || refcount > 0xffff) | |
| 2564 | - return -EINVAL; | |
| 2565 | - if (refcount == 0 && cluster_index < s->free_cluster_index) { | |
| 2566 | - s->free_cluster_index = cluster_index; | |
| 2554 | + | |
| 2555 | + return refcount_block_offset; | |
| 2556 | +} | |
| 2557 | + | |
| 2558 | +/* addend must be 1 or -1 */ | |
| 2559 | +static int update_cluster_refcount(BlockDriverState *bs, | |
| 2560 | + int64_t cluster_index, | |
| 2561 | + int addend) | |
| 2562 | +{ | |
| 2563 | + BDRVQcowState *s = bs->opaque; | |
| 2564 | + int ret; | |
| 2565 | + | |
| 2566 | + ret = update_refcount(bs, cluster_index << s->cluster_bits, 1, addend); | |
| 2567 | + if (ret < 0) { | |
| 2568 | + return ret; | |
| 2567 | 2569 | } |
| 2568 | - s->refcount_block_cache[block_index] = cpu_to_be16(refcount); | |
| 2569 | - if (bdrv_pwrite(s->hd, | |
| 2570 | - refcount_block_offset + (block_index << REFCOUNT_SHIFT), | |
| 2571 | - &s->refcount_block_cache[block_index], 2) != 2) | |
| 2572 | - return -EIO; | |
| 2573 | - return refcount; | |
| 2570 | + | |
| 2571 | + return get_refcount(bs, cluster_index); | |
| 2574 | 2572 | } |
| 2575 | 2573 | |
| 2576 | -static void update_refcount(BlockDriverState *bs, | |
| 2574 | +/* XXX: cache several refcount block clusters ? */ | |
| 2575 | +static int update_refcount(BlockDriverState *bs, | |
| 2577 | 2576 | int64_t offset, int64_t length, |
| 2578 | 2577 | int addend) |
| 2579 | 2578 | { |
| ... | ... | @@ -2585,13 +2584,40 @@ static void update_refcount(BlockDriverState *bs, |
| 2585 | 2584 | offset, length, addend); |
| 2586 | 2585 | #endif |
| 2587 | 2586 | if (length <= 0) |
| 2588 | - return; | |
| 2587 | + return -EINVAL; | |
| 2589 | 2588 | start = offset & ~(s->cluster_size - 1); |
| 2590 | 2589 | last = (offset + length - 1) & ~(s->cluster_size - 1); |
| 2591 | 2590 | for(cluster_offset = start; cluster_offset <= last; |
| 2592 | - cluster_offset += s->cluster_size) { | |
| 2593 | - update_cluster_refcount(bs, cluster_offset >> s->cluster_bits, addend); | |
| 2591 | + cluster_offset += s->cluster_size) | |
| 2592 | + { | |
| 2593 | + int64_t refcount_block_offset; | |
| 2594 | + int block_index, refcount; | |
| 2595 | + int64_t cluster_index = cluster_offset >> s->cluster_bits; | |
| 2596 | + | |
| 2597 | + /* Load the refcount block and allocate it if needed */ | |
| 2598 | + refcount_block_offset = alloc_refcount_block(bs, cluster_index); | |
| 2599 | + if (refcount_block_offset < 0) { | |
| 2600 | + return refcount_block_offset; | |
| 2601 | + } | |
| 2602 | + | |
| 2603 | + /* we can update the count and save it */ | |
| 2604 | + block_index = cluster_index & | |
| 2605 | + ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); | |
| 2606 | + refcount = be16_to_cpu(s->refcount_block_cache[block_index]); | |
| 2607 | + refcount += addend; | |
| 2608 | + if (refcount < 0 || refcount > 0xffff) | |
| 2609 | + return -EINVAL; | |
| 2610 | + if (refcount == 0 && cluster_index < s->free_cluster_index) { | |
| 2611 | + s->free_cluster_index = cluster_index; | |
| 2612 | + } | |
| 2613 | + s->refcount_block_cache[block_index] = cpu_to_be16(refcount); | |
| 2614 | + if (bdrv_pwrite(s->hd, | |
| 2615 | + refcount_block_offset + (block_index << REFCOUNT_SHIFT), | |
| 2616 | + &s->refcount_block_cache[block_index], 2) != 2) | |
| 2617 | + return -EIO; | |
| 2618 | + | |
| 2594 | 2619 | } |
| 2620 | + return 0; | |
| 2595 | 2621 | } |
| 2596 | 2622 | |
| 2597 | 2623 | /* | ... | ... |