aboutsummaryrefslogtreecommitdiff
path: root/block/qcow2-snapshot.c
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2019-10-11 17:28:06 +0200
committerMax Reitz <mreitz@redhat.com>2019-10-28 11:54:00 +0100
commit8bc584fe035d98b8aca4fcc818617c91df0ed925 (patch)
treef88aa3e4d673fce26ed685a6a9eca498527928e7 /block/qcow2-snapshot.c
parent0a85af351d90e1ae9e06b3bb5290ddf2d5d8b950 (diff)
qcow2: Separate qcow2_check_read_snapshot_table()
Reading the snapshot table can fail. That is a problem when we want to repair the image. Therefore, stop reading the snapshot table in qcow2_do_open() in check mode. Instead, add a new function qcow2_check_read_snapshot_table() that reads the snapshot table at a later point. In the future, we want to handle errors here and fix them. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 20191011152814.14791-9-mreitz@redhat.com Signed-off-by: Max Reitz <mreitz@redhat.com>
Diffstat (limited to 'block/qcow2-snapshot.c')
-rw-r--r--block/qcow2-snapshot.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index e3bf4c9776..d667bfd935 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -322,6 +322,64 @@ fail:
return ret;
}
+int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
+ BdrvCheckResult *result,
+ BdrvCheckMode fix)
+{
+ BDRVQcow2State *s = bs->opaque;
+ Error *local_err = NULL;
+ int ret;
+ struct {
+ uint32_t nb_snapshots;
+ uint64_t snapshots_offset;
+ } QEMU_PACKED snapshot_table_pointer;
+
+ /* qcow2_do_open() discards this information in check mode */
+ ret = bdrv_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
+ &snapshot_table_pointer, sizeof(snapshot_table_pointer));
+ if (ret < 0) {
+ result->check_errors++;
+ fprintf(stderr, "ERROR failed to read the snapshot table pointer from "
+ "the image header: %s\n", strerror(-ret));
+ return ret;
+ }
+
+ s->snapshots_offset = be64_to_cpu(snapshot_table_pointer.snapshots_offset);
+ s->nb_snapshots = be32_to_cpu(snapshot_table_pointer.nb_snapshots);
+
+ ret = qcow2_validate_table(bs, s->snapshots_offset, s->nb_snapshots,
+ sizeof(QCowSnapshotHeader),
+ sizeof(QCowSnapshotHeader) * QCOW_MAX_SNAPSHOTS,
+ "snapshot table", &local_err);
+ if (ret < 0) {
+ result->check_errors++;
+ error_reportf_err(local_err, "ERROR ");
+
+ /* We did not read the snapshot table, so invalidate this information */
+ s->snapshots_offset = 0;
+ s->nb_snapshots = 0;
+
+ return ret;
+ }
+
+ qemu_co_mutex_unlock(&s->lock);
+ ret = qcow2_read_snapshots(bs, &local_err);
+ qemu_co_mutex_lock(&s->lock);
+ if (ret < 0) {
+ result->check_errors++;
+ error_reportf_err(local_err,
+ "ERROR failed to read the snapshot table: ");
+
+ /* We did not read the snapshot table, so invalidate this information */
+ s->snapshots_offset = 0;
+ s->nb_snapshots = 0;
+
+ return ret;
+ }
+
+ return 0;
+}
+
static void find_new_snapshot_id(BlockDriverState *bs,
char *id_str, int id_str_size)
{