mirror of https://github.com/xemu-project/xemu.git
qcow2: Clean up after refcount rebuild
Because the old refcount structure will be leaked after having rebuilt it, we need to recalculate the refcounts and run a leak-fixing operation afterwards (if leaks should be fixed at all). Signed-off-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
c7c0681bc8
commit
791230d8bb
|
@ -2011,12 +2011,57 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
|
||||||
nb_clusters);
|
nb_clusters);
|
||||||
|
|
||||||
if (rebuild && (fix & BDRV_FIX_ERRORS)) {
|
if (rebuild && (fix & BDRV_FIX_ERRORS)) {
|
||||||
|
BdrvCheckResult old_res = *res;
|
||||||
|
int fresh_leaks = 0;
|
||||||
|
|
||||||
fprintf(stderr, "Rebuilding refcount structure\n");
|
fprintf(stderr, "Rebuilding refcount structure\n");
|
||||||
ret = rebuild_refcount_structure(bs, res, &refcount_table,
|
ret = rebuild_refcount_structure(bs, res, &refcount_table,
|
||||||
&nb_clusters);
|
&nb_clusters);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res->corruptions = 0;
|
||||||
|
res->leaks = 0;
|
||||||
|
|
||||||
|
/* Because the old reftable has been exchanged for a new one the
|
||||||
|
* references have to be recalculated */
|
||||||
|
rebuild = false;
|
||||||
|
memset(refcount_table, 0, nb_clusters * sizeof(uint16_t));
|
||||||
|
ret = calculate_refcounts(bs, res, 0, &rebuild, &refcount_table,
|
||||||
|
&nb_clusters);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fix & BDRV_FIX_LEAKS) {
|
||||||
|
/* The old refcount structures are now leaked, fix it; the result
|
||||||
|
* can be ignored, aside from leaks which were introduced by
|
||||||
|
* rebuild_refcount_structure() that could not be fixed */
|
||||||
|
BdrvCheckResult saved_res = *res;
|
||||||
|
*res = (BdrvCheckResult){ 0 };
|
||||||
|
|
||||||
|
compare_refcounts(bs, res, BDRV_FIX_LEAKS, &rebuild,
|
||||||
|
&highest_cluster, refcount_table, nb_clusters);
|
||||||
|
if (rebuild) {
|
||||||
|
fprintf(stderr, "ERROR rebuilt refcount structure is still "
|
||||||
|
"broken\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Any leaks accounted for here were introduced by
|
||||||
|
* rebuild_refcount_structure() because that function has created a
|
||||||
|
* new refcount structure from scratch */
|
||||||
|
fresh_leaks = res->leaks;
|
||||||
|
*res = saved_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res->corruptions < old_res.corruptions) {
|
||||||
|
res->corruptions_fixed += old_res.corruptions - res->corruptions;
|
||||||
|
}
|
||||||
|
if (res->leaks < old_res.leaks) {
|
||||||
|
res->leaks_fixed += old_res.leaks - res->leaks;
|
||||||
|
}
|
||||||
|
res->leaks += fresh_leaks;
|
||||||
} else if (fix) {
|
} else if (fix) {
|
||||||
if (rebuild) {
|
if (rebuild) {
|
||||||
fprintf(stderr, "ERROR need to rebuild refcount structures\n");
|
fprintf(stderr, "ERROR need to rebuild refcount structures\n");
|
||||||
|
|
Loading…
Reference in New Issue