Revision 91b85bd3
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