@@ -719,6 +719,9 @@ int qcow2_write_snapshots(BlockDriverState *bs);
int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
BdrvCheckResult *result,
BdrvCheckMode fix);
+int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs,
+ BdrvCheckResult *result,
+ BdrvCheckMode fix);
/* qcow2-cache.c functions */
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
@@ -380,6 +380,31 @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
return 0;
}
+int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs,
+ BdrvCheckResult *result,
+ BdrvCheckMode fix)
+{
+ BDRVQcow2State *s = bs->opaque;
+ int ret;
+
+ if (result->corruptions && (fix & BDRV_FIX_ERRORS)) {
+ qemu_co_mutex_unlock(&s->lock);
+ ret = qcow2_write_snapshots(bs);
+ qemu_co_mutex_lock(&s->lock);
+ if (ret < 0) {
+ result->check_errors++;
+ fprintf(stderr, "ERROR failed to update snapshot table: %s\n",
+ strerror(-ret));
+ return ret;
+ }
+
+ result->corruptions_fixed += result->corruptions;
+ result->corruptions = 0;
+ }
+
+ return 0;
+}
+
static void find_new_snapshot_id(BlockDriverState *bs,
char *id_str, int id_str_size)
{
@@ -597,13 +597,20 @@ static int coroutine_fn qcow2_co_check_locked(BlockDriverState *bs,
memset(result, 0, sizeof(*result));
ret = qcow2_check_read_snapshot_table(bs, &snapshot_res, fix);
- qcow2_add_check_result(result, &snapshot_res, false);
if (ret < 0) {
+ qcow2_add_check_result(result, &snapshot_res, false);
return ret;
}
ret = qcow2_check_refcounts(bs, &refcount_res, fix);
qcow2_add_check_result(result, &refcount_res, true);
+ if (ret < 0) {
+ qcow2_add_check_result(result, &snapshot_res, false);
+ return ret;
+ }
+
+ ret = qcow2_check_fix_snapshot_table(bs, &snapshot_res, fix);
+ qcow2_add_check_result(result, &snapshot_res, false);
if (ret < 0) {
return ret;
}