As can be seen in the final patch of this series, there are certain cases where the current repair implementation of qcow2 actually damages the image further because it allocates new clusters for the refcount structure which overlap with existing but according to the on-disk refcounts (which are assumed to be wrong to begin with) unallocated clusters.
This series fixes this by completely recreating the refcount structure based on the in-memory information calculated during the check operation if the possibility of damaging the image while repairing the refcount structures in-place exists. v8: - Patches 7 to 10 let inc_refcounts() resize the reftable; if this isn't done, rebuilding the refcount structures may lead to data clusters conflicting with refcount structures [Kevin] - Patch 7: Just use int64_t instead of int throughout all check functions for the in-memory refcount table size so that the following patches are smaller - Patch 8: The fail path in the L1 and L2 check functions was not a pure cleanup path, but also hard-coded what errors might occur (only EIO), this fixes that - Patch 9: Patch 10 requires inc_refcounts() to be able to return an error, so this patch prepares for that - Patch 10: Allows inc_refcounts() to resize the in-memory refcount table - Patch 12 (prev. 8): - Drop a superfluous validation [Kevin] - Fix leak of *refcount_table due to g_try_realloc() (which I forgot to do here in v7) [Kevin] - Rebase conflicts due to patch 9 - Patch 13 (prev. 9): Rebase conflicts due to patch 9 - Patch 14 (prev. 10): Keep *imrt_nb_clusters in case g_try_realloc() fails [Kevin] - Patch 15 (prev. 11): res->leaks does not account for fixed leaks, so don't subtract them to get the number of unfixed leaks [Kevin] git-backport-diff against v7: Key: [----] : patches are identical [####] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively 001/17:[----] [--] 'block: Add qemu_{,try_}blockalign0()' 002/17:[----] [--] 'qcow2: Calculate refcount block entry count' 003/17:[----] [--] 'qcow2: Fix leaks in dirty images' 004/17:[----] [--] 'qcow2: Split qcow2_check_refcounts()' 005/17:[----] [--] 'qcow2: Use sizeof(**refcount_table)' 006/17:[----] [--] 'qcow2: Pull check_refblocks() up' 007/17:[down] 'qcow2: Use int64_t for in-memory reftable size' 008/17:[down] 'qcow2: Split fail code in L1 and L2 checks' 009/17:[down] 'qcow2: Let inc_refcounts() return -errno' 010/17:[down] 'qcow2: Let inc_refcounts() resize the reftable' 011/17:[----] [--] 'qcow2: Reuse refcount table in calculate_refcounts()' 012/17:[0022] [FC] 'qcow2: Fix refcount blocks beyond image end' 013/17:[0007] [FC] 'qcow2: Do not perform potentially damaging repairs' 014/17:[0001] [FC] 'qcow2: Rebuild refcount structure during check' 015/17:[0002] [FC] 'qcow2: Clean up after refcount rebuild' 016/17:[----] [--] 'iotests: Fix test outputs' 017/17:[----] [--] 'iotests: Add test for potentially damaging repairs' Max Reitz (17): block: Add qemu_{,try_}blockalign0() qcow2: Calculate refcount block entry count qcow2: Fix leaks in dirty images qcow2: Split qcow2_check_refcounts() qcow2: Use sizeof(**refcount_table) qcow2: Pull check_refblocks() up qcow2: Use int64_t for in-memory reftable size qcow2: Split fail code in L1 and L2 checks qcow2: Let inc_refcounts() return -errno qcow2: Let inc_refcounts() resize the reftable qcow2: Reuse refcount table in calculate_refcounts() qcow2: Fix refcount blocks beyond image end qcow2: Do not perform potentially damaging repairs qcow2: Rebuild refcount structure during check qcow2: Clean up after refcount rebuild iotests: Fix test outputs iotests: Add test for potentially damaging repairs block.c | 16 + block/qcow2-refcount.c | 841 ++++++++++++++++++++++++++++++++------------- block/qcow2.c | 5 +- block/qcow2.h | 2 + include/block/block.h | 2 + tests/qemu-iotests/039.out | 10 +- tests/qemu-iotests/060.out | 10 +- tests/qemu-iotests/061.out | 18 +- tests/qemu-iotests/108 | 141 ++++++++ tests/qemu-iotests/108.out | 110 ++++++ tests/qemu-iotests/group | 1 + 11 files changed, 907 insertions(+), 249 deletions(-) create mode 100755 tests/qemu-iotests/108 create mode 100644 tests/qemu-iotests/108.out -- 1.9.3