Revision 018faafd block/qcow2-refcount.c
b/block/qcow2-refcount.c | ||
---|---|---|
105 | 105 |
return 0; |
106 | 106 |
} |
107 | 107 |
|
108 |
/* |
|
109 |
* Returns the refcount of the cluster given by its index. Any non-negative |
|
110 |
* return value is the refcount of the cluster, negative values are -errno |
|
111 |
* and indicate an error. |
|
112 |
*/ |
|
108 | 113 |
static int get_refcount(BlockDriverState *bs, int64_t cluster_index) |
109 | 114 |
{ |
110 | 115 |
BDRVQcowState *s = bs->opaque; |
111 | 116 |
int refcount_table_index, block_index; |
112 | 117 |
int64_t refcount_block_offset; |
118 |
int ret; |
|
113 | 119 |
|
114 | 120 |
refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); |
115 | 121 |
if (refcount_table_index >= s->refcount_table_size) |
... | ... | |
119 | 125 |
return 0; |
120 | 126 |
if (refcount_block_offset != s->refcount_block_cache_offset) { |
121 | 127 |
/* better than nothing: return allocated if read error */ |
122 |
if (load_refcount_block(bs, refcount_block_offset) < 0) |
|
123 |
return 1; |
|
128 |
ret = load_refcount_block(bs, refcount_block_offset); |
|
129 |
if (ret < 0) { |
|
130 |
return ret; |
|
131 |
} |
|
124 | 132 |
} |
125 | 133 |
block_index = cluster_index & |
126 | 134 |
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); |
... | ... | |
538 | 546 |
return ret; |
539 | 547 |
} |
540 | 548 |
|
541 |
/* addend must be 1 or -1 */ |
|
549 |
/* |
|
550 |
* Increases or decreases the refcount of a given cluster by one. |
|
551 |
* addend must be 1 or -1. |
|
552 |
* |
|
553 |
* If the return value is non-negative, it is the new refcount of the cluster. |
|
554 |
* If it is negative, it is -errno and indicates an error. |
|
555 |
*/ |
|
542 | 556 |
static int update_cluster_refcount(BlockDriverState *bs, |
543 | 557 |
int64_t cluster_index, |
544 | 558 |
int addend) |
... | ... | |
779 | 793 |
} else { |
780 | 794 |
refcount = get_refcount(bs, offset >> s->cluster_bits); |
781 | 795 |
} |
796 |
|
|
797 |
if (refcount < 0) { |
|
798 |
goto fail; |
|
799 |
} |
|
782 | 800 |
} |
783 | 801 |
|
784 | 802 |
if (refcount == 1) { |
... | ... | |
801 | 819 |
} else { |
802 | 820 |
refcount = get_refcount(bs, l2_offset >> s->cluster_bits); |
803 | 821 |
} |
804 |
if (refcount == 1) { |
|
822 |
if (refcount < 0) { |
|
823 |
goto fail; |
|
824 |
} else if (refcount == 1) { |
|
805 | 825 |
l2_offset |= QCOW_OFLAG_COPIED; |
806 | 826 |
} |
807 | 827 |
if (l2_offset != old_l2_offset) { |
... | ... | |
934 | 954 |
uint64_t entry = offset; |
935 | 955 |
offset &= ~QCOW_OFLAG_COPIED; |
936 | 956 |
refcount = get_refcount(bs, offset >> s->cluster_bits); |
957 |
if (refcount < 0) { |
|
958 |
fprintf(stderr, "Can't get refcount for offset %" |
|
959 |
PRIx64 ": %s\n", entry, strerror(-refcount)); |
|
960 |
} |
|
937 | 961 |
if ((refcount == 1) != ((entry & QCOW_OFLAG_COPIED) != 0)) { |
938 | 962 |
fprintf(stderr, "ERROR OFLAG_COPIED: offset=%" |
939 | 963 |
PRIx64 " refcount=%d\n", entry, refcount); |
... | ... | |
1011 | 1035 |
if (check_copied) { |
1012 | 1036 |
refcount = get_refcount(bs, (l2_offset & ~QCOW_OFLAG_COPIED) |
1013 | 1037 |
>> s->cluster_bits); |
1038 |
if (refcount < 0) { |
|
1039 |
fprintf(stderr, "Can't get refcount for l2_offset %" |
|
1040 |
PRIx64 ": %s\n", l2_offset, strerror(-refcount)); |
|
1041 |
} |
|
1014 | 1042 |
if ((refcount == 1) != ((l2_offset & QCOW_OFLAG_COPIED) != 0)) { |
1015 | 1043 |
fprintf(stderr, "ERROR OFLAG_COPIED: l2_offset=%" PRIx64 |
1016 | 1044 |
" refcount=%d\n", l2_offset, refcount); |
... | ... | |
1118 | 1146 |
/* compare ref counts */ |
1119 | 1147 |
for(i = 0; i < nb_clusters; i++) { |
1120 | 1148 |
refcount1 = get_refcount(bs, i); |
1149 |
if (refcount1 < 0) { |
|
1150 |
fprintf(stderr, "Can't get refcount for cluster %d: %s\n", |
|
1151 |
i, strerror(-refcount1)); |
|
1152 |
} |
|
1153 |
|
|
1121 | 1154 |
refcount2 = refcount_table[i]; |
1122 | 1155 |
if (refcount1 != refcount2) { |
1123 | 1156 |
fprintf(stderr, "ERROR cluster %d refcount=%d reference=%d\n", |
Also available in: Unified diff