Revision a980c98c block/qcow2.c
b/block/qcow2.c | ||
---|---|---|
2578 | 2578 |
{ |
2579 | 2579 |
BDRVQcowState *s = bs->opaque; |
2580 | 2580 |
int64_t start, last, cluster_offset; |
2581 |
int64_t refcount_block_offset = 0; |
|
2582 |
int64_t table_index = -1, old_table_index; |
|
2583 |
int first_index = -1, last_index = -1; |
|
2581 | 2584 |
|
2582 | 2585 |
#ifdef DEBUG_ALLOC2 |
2583 | 2586 |
printf("update_refcount: offset=%lld size=%lld addend=%d\n", |
... | ... | |
2590 | 2593 |
for(cluster_offset = start; cluster_offset <= last; |
2591 | 2594 |
cluster_offset += s->cluster_size) |
2592 | 2595 |
{ |
2593 |
int64_t refcount_block_offset; |
|
2594 | 2596 |
int block_index, refcount; |
2595 | 2597 |
int64_t cluster_index = cluster_offset >> s->cluster_bits; |
2596 | 2598 |
|
2599 |
/* Only write refcount block to disk when we are done with it */ |
|
2600 |
old_table_index = table_index; |
|
2601 |
table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); |
|
2602 |
if ((old_table_index >= 0) && (table_index != old_table_index)) { |
|
2603 |
size_t size = (last_index - first_index + 1) << REFCOUNT_SHIFT; |
|
2604 |
if (bdrv_pwrite(s->hd, |
|
2605 |
refcount_block_offset + (first_index << REFCOUNT_SHIFT), |
|
2606 |
&s->refcount_block_cache[first_index], size) != size) |
|
2607 |
{ |
|
2608 |
return -EIO; |
|
2609 |
} |
|
2610 |
|
|
2611 |
first_index = -1; |
|
2612 |
last_index = -1; |
|
2613 |
} |
|
2614 |
|
|
2597 | 2615 |
/* Load the refcount block and allocate it if needed */ |
2598 | 2616 |
refcount_block_offset = alloc_refcount_block(bs, cluster_index); |
2599 | 2617 |
if (refcount_block_offset < 0) { |
... | ... | |
2603 | 2621 |
/* we can update the count and save it */ |
2604 | 2622 |
block_index = cluster_index & |
2605 | 2623 |
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); |
2624 |
if (first_index == -1 || block_index < first_index) { |
|
2625 |
first_index = block_index; |
|
2626 |
} |
|
2627 |
if (block_index > last_index) { |
|
2628 |
last_index = block_index; |
|
2629 |
} |
|
2630 |
|
|
2606 | 2631 |
refcount = be16_to_cpu(s->refcount_block_cache[block_index]); |
2607 | 2632 |
refcount += addend; |
2608 | 2633 |
if (refcount < 0 || refcount > 0xffff) |
... | ... | |
2611 | 2636 |
s->free_cluster_index = cluster_index; |
2612 | 2637 |
} |
2613 | 2638 |
s->refcount_block_cache[block_index] = cpu_to_be16(refcount); |
2639 |
} |
|
2640 |
|
|
2641 |
/* Write last changed block to disk */ |
|
2642 |
if (refcount_block_offset != 0) { |
|
2643 |
size_t size = (last_index - first_index + 1) << REFCOUNT_SHIFT; |
|
2614 | 2644 |
if (bdrv_pwrite(s->hd, |
2615 |
refcount_block_offset + (block_index << REFCOUNT_SHIFT), |
|
2616 |
&s->refcount_block_cache[block_index], 2) != 2) |
|
2645 |
refcount_block_offset + (first_index << REFCOUNT_SHIFT), |
|
2646 |
&s->refcount_block_cache[first_index], size) != size) |
|
2647 |
{ |
|
2617 | 2648 |
return -EIO; |
2618 |
|
|
2649 |
} |
|
2619 | 2650 |
} |
2651 |
|
|
2620 | 2652 |
return 0; |
2621 | 2653 |
} |
2622 | 2654 |
|
Also available in: Unified diff