提交 166acf54 编写于 作者: K Kevin Wolf

qcow2: Support for fixing refcount inconsistencies

Signed-off-by: NKevin Wolf <kwolf@redhat.com>
上级 ccf34716
......@@ -1122,11 +1122,12 @@ fail:
* Returns 0 if no errors are found, the number of errors in case the image is
* detected as corrupted, and -errno when an internal error occurred.
*/
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
BdrvCheckMode fix)
{
BDRVQcowState *s = bs->opaque;
int64_t size;
int nb_clusters, refcount1, refcount2, i;
int64_t size, i;
int nb_clusters, refcount1, refcount2;
QCowSnapshot *sn;
uint16_t *refcount_table;
int ret;
......@@ -1170,14 +1171,15 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
/* Refcount blocks are cluster aligned */
if (offset & (s->cluster_size - 1)) {
fprintf(stderr, "ERROR refcount block %d is not "
fprintf(stderr, "ERROR refcount block %" PRId64 " is not "
"cluster aligned; refcount table entry corrupted\n", i);
res->corruptions++;
continue;
}
if (cluster >= nb_clusters) {
fprintf(stderr, "ERROR refcount block %d is outside image\n", i);
fprintf(stderr, "ERROR refcount block %" PRId64
" is outside image\n", i);
res->corruptions++;
continue;
}
......@@ -1186,7 +1188,8 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
inc_refcounts(bs, res, refcount_table, nb_clusters,
offset, s->cluster_size);
if (refcount_table[cluster] != 1) {
fprintf(stderr, "ERROR refcount block %d refcount=%d\n",
fprintf(stderr, "ERROR refcount block %" PRId64
" refcount=%d\n",
i, refcount_table[cluster]);
res->corruptions++;
}
......@@ -1197,7 +1200,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
for(i = 0; i < nb_clusters; i++) {
refcount1 = get_refcount(bs, i);
if (refcount1 < 0) {
fprintf(stderr, "Can't get refcount for cluster %d: %s\n",
fprintf(stderr, "Can't get refcount for cluster %" PRId64 ": %s\n",
i, strerror(-refcount1));
res->check_errors++;
continue;
......@@ -1205,9 +1208,31 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
refcount2 = refcount_table[i];
if (refcount1 != refcount2) {
fprintf(stderr, "%s cluster %d refcount=%d reference=%d\n",
refcount1 < refcount2 ? "ERROR" : "Leaked",
/* Check if we're allowed to fix the mismatch */
int *num_fixed = NULL;
if (refcount1 > refcount2 && (fix & BDRV_FIX_LEAKS)) {
num_fixed = &res->leaks_fixed;
} else if (refcount1 < refcount2 && (fix & BDRV_FIX_ERRORS)) {
num_fixed = &res->corruptions_fixed;
}
fprintf(stderr, "%s cluster %" PRId64 " refcount=%d reference=%d\n",
num_fixed != NULL ? "Repairing" :
refcount1 < refcount2 ? "ERROR" :
"Leaked",
i, refcount1, refcount2);
if (num_fixed) {
ret = update_refcount(bs, i << s->cluster_bits, 1,
refcount2 - refcount1);
if (ret >= 0) {
(*num_fixed)++;
continue;
}
}
/* And if we couldn't, print an error */
if (refcount1 < refcount2) {
res->corruptions++;
} else {
......
......@@ -1473,11 +1473,7 @@ static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
static int qcow2_check(BlockDriverState *bs, BdrvCheckResult *result,
BdrvCheckMode fix)
{
if (fix) {
return -ENOTSUP;
}
return qcow2_check_refcounts(bs, result);
return qcow2_check_refcounts(bs, result, fix);
}
#if 0
......
......@@ -261,7 +261,8 @@ void qcow2_free_any_clusters(BlockDriverState *bs,
int qcow2_update_snapshot_refcount(BlockDriverState *bs,
int64_t l1_table_offset, int l1_size, int addend);
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res);
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
BdrvCheckMode fix);
/* qcow2-cluster.c functions */
int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册