Revision 91b85bd3 block/vmdk.c

b/block/vmdk.c
665 665
    return 0;
666 666
}
667 667

  
668
static uint64_t get_cluster_offset(BlockDriverState *bs,
668
static int get_cluster_offset(BlockDriverState *bs,
669 669
                                    VmdkExtent *extent,
670 670
                                    VmdkMetaData *m_data,
671
                                    uint64_t offset, int allocate)
671
                                    uint64_t offset,
672
                                    int allocate,
673
                                    uint64_t *cluster_offset)
672 674
{
673 675
    unsigned int l1_index, l2_offset, l2_index;
674 676
    int min_index, i, j;
675 677
    uint32_t min_count, *l2_table, tmp = 0;
676
    uint64_t cluster_offset;
677 678

  
678 679
    if (m_data)
679 680
        m_data->valid = 0;
681
    if (extent->flat) {
682
        *cluster_offset = 0;
683
        return 0;
684
    }
680 685

  
681 686
    l1_index = (offset >> 9) / extent->l1_entry_sectors;
682 687
    if (l1_index >= extent->l1_size) {
683
        return 0;
688
        return -1;
684 689
    }
685 690
    l2_offset = extent->l1_table[l1_index];
686 691
    if (!l2_offset) {
687
        return 0;
692
        return -1;
688 693
    }
689 694
    for (i = 0; i < L2_CACHE_SIZE; i++) {
690 695
        if (l2_offset == extent->l2_cache_offsets[i]) {
......
714 719
                l2_table,
715 720
                extent->l2_size * sizeof(uint32_t)
716 721
            ) != extent->l2_size * sizeof(uint32_t)) {
717
        return 0;
722
        return -1;
718 723
    }
719 724

  
720 725
    extent->l2_cache_offsets[min_index] = l2_offset;
721 726
    extent->l2_cache_counts[min_index] = 1;
722 727
 found:
723 728
    l2_index = ((offset >> 9) / extent->cluster_sectors) % extent->l2_size;
724
    cluster_offset = le32_to_cpu(l2_table[l2_index]);
729
    *cluster_offset = le32_to_cpu(l2_table[l2_index]);
725 730

  
726
    if (!cluster_offset) {
727
        if (!allocate)
728
            return 0;
731
    if (!*cluster_offset) {
732
        if (!allocate) {
733
            return -1;
734
        }
729 735

  
730 736
        // Avoid the L2 tables update for the images that have snapshots.
731
        cluster_offset = bdrv_getlength(extent->file);
737
        *cluster_offset = bdrv_getlength(extent->file);
732 738
        bdrv_truncate(
733 739
            extent->file,
734
            cluster_offset + (extent->cluster_sectors << 9)
740
            *cluster_offset + (extent->cluster_sectors << 9)
735 741
        );
736 742

  
737
        cluster_offset >>= 9;
738
        tmp = cpu_to_le32(cluster_offset);
743
        *cluster_offset >>= 9;
744
        tmp = cpu_to_le32(*cluster_offset);
739 745
        l2_table[l2_index] = tmp;
740 746

  
741 747
        /* First of all we write grain itself, to avoid race condition
......
744 750
         * or inappropriate VM shutdown.
745 751
         */
746 752
        if (get_whole_cluster(
747
                bs, extent, cluster_offset, offset, allocate) == -1)
748
            return 0;
753
                bs, extent, *cluster_offset, offset, allocate) == -1)
754
            return -1;
749 755

  
750 756
        if (m_data) {
751 757
            m_data->offset = tmp;
......
755 761
            m_data->valid = 1;
756 762
        }
757 763
    }
758
    cluster_offset <<= 9;
759
    return cluster_offset;
764
    *cluster_offset <<= 9;
765
    return 0;
760 766
}
761 767

  
762 768
static VmdkExtent *find_extent(BDRVVmdkState *s,
......
780 786
                             int nb_sectors, int *pnum)
781 787
{
782 788
    BDRVVmdkState *s = bs->opaque;
783

  
784 789
    int64_t index_in_cluster, n, ret;
785 790
    uint64_t offset;
786 791
    VmdkExtent *extent;
......
789 794
    if (!extent) {
790 795
        return 0;
791 796
    }
792
    if (extent->flat) {
793
        n = extent->end_sector - sector_num;
794
        ret = 1;
795
    } else {
796
        offset = get_cluster_offset(bs, extent, NULL, sector_num * 512, 0);
797
        index_in_cluster = sector_num % extent->cluster_sectors;
798
        n = extent->cluster_sectors - index_in_cluster;
799
        ret = offset ? 1 : 0;
800
    }
797
    ret = get_cluster_offset(bs, extent, NULL,
798
                            sector_num * 512, 0, &offset);
799
    /* get_cluster_offset returning 0 means success */
800
    ret = !ret;
801

  
802
    index_in_cluster = sector_num % extent->cluster_sectors;
803
    n = extent->cluster_sectors - index_in_cluster;
801 804
    if (n > nb_sectors)
802 805
        n = nb_sectors;
803 806
    *pnum = n;
......
818 821
        if (!extent) {
819 822
            return -EIO;
820 823
        }
821
        cluster_offset = get_cluster_offset(
822
                            bs, extent, NULL, sector_num << 9, 0);
824
        ret = get_cluster_offset(
825
                            bs, extent, NULL,
826
                            sector_num << 9, 0, &cluster_offset);
823 827
        index_in_cluster = sector_num % extent->cluster_sectors;
824 828
        n = extent->cluster_sectors - index_in_cluster;
825 829
        if (n > nb_sectors)
826 830
            n = nb_sectors;
827
        if (!cluster_offset) {
828
            // try to read from parent image, if exist
831
        if (ret) {
832
            /* if not allocated, try to read from parent image, if exist */
829 833
            if (bs->backing_hd) {
830 834
                if (!vmdk_is_cid_valid(bs))
831 835
                    return -1;
......
851 855
{
852 856
    BDRVVmdkState *s = bs->opaque;
853 857
    VmdkExtent *extent = NULL;
854
    int n;
858
    int n, ret;
855 859
    int64_t index_in_cluster;
856 860
    uint64_t cluster_offset;
857 861
    VmdkMetaData m_data;
......
869 873
        if (!extent) {
870 874
            return -EIO;
871 875
        }
872
        cluster_offset = get_cluster_offset(
876
        ret = get_cluster_offset(
873 877
                                bs,
874 878
                                extent,
875 879
                                &m_data,
876
                                sector_num << 9, 1);
877
        if (!cluster_offset) {
878
            return -1;
880
                                sector_num << 9, 1,
881
                                &cluster_offset);
882
        if (ret) {
883
            return -EINVAL;
879 884
        }
880 885
        index_in_cluster = sector_num % extent->cluster_sectors;
881 886
        n = extent->cluster_sectors - index_in_cluster;

Also available in: Unified diff