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 | /* | ... | ... |