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