xref: /qemu/block/qcow2-snapshot.c (revision a39bae4e)
1c142442bSKevin Wolf /*
2c142442bSKevin Wolf  * Block driver for the QCOW version 2 format
3c142442bSKevin Wolf  *
4c142442bSKevin Wolf  * Copyright (c) 2004-2006 Fabrice Bellard
5c142442bSKevin Wolf  *
6c142442bSKevin Wolf  * Permission is hereby granted, free of charge, to any person obtaining a copy
7c142442bSKevin Wolf  * of this software and associated documentation files (the "Software"), to deal
8c142442bSKevin Wolf  * in the Software without restriction, including without limitation the rights
9c142442bSKevin Wolf  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10c142442bSKevin Wolf  * copies of the Software, and to permit persons to whom the Software is
11c142442bSKevin Wolf  * furnished to do so, subject to the following conditions:
12c142442bSKevin Wolf  *
13c142442bSKevin Wolf  * The above copyright notice and this permission notice shall be included in
14c142442bSKevin Wolf  * all copies or substantial portions of the Software.
15c142442bSKevin Wolf  *
16c142442bSKevin Wolf  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17c142442bSKevin Wolf  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18c142442bSKevin Wolf  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19c142442bSKevin Wolf  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20c142442bSKevin Wolf  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21c142442bSKevin Wolf  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22c142442bSKevin Wolf  * THE SOFTWARE.
23c142442bSKevin Wolf  */
24c142442bSKevin Wolf 
2580c71a24SPeter Maydell #include "qemu/osdep.h"
267fa140abSEric Blake #include "sysemu/block-backend.h"
27da34e65cSMarkus Armbruster #include "qapi/error.h"
280d8c41daSMichael S. Tsirkin #include "qcow2.h"
2958369e22SPaolo Bonzini #include "qemu/bswap.h"
30d49b6836SMarkus Armbruster #include "qemu/error-report.h"
31f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
325df022cfSPeter Maydell #include "qemu/memalign.h"
33c142442bSKevin Wolf 
qcow2_free_single_snapshot(BlockDriverState * bs,int i)34099febf3SMax Reitz static void qcow2_free_single_snapshot(BlockDriverState *bs, int i)
35099febf3SMax Reitz {
36099febf3SMax Reitz     BDRVQcow2State *s = bs->opaque;
37099febf3SMax Reitz 
38099febf3SMax Reitz     assert(i >= 0 && i < s->nb_snapshots);
39099febf3SMax Reitz     g_free(s->snapshots[i].name);
40099febf3SMax Reitz     g_free(s->snapshots[i].id_str);
41099febf3SMax Reitz     g_free(s->snapshots[i].unknown_extra_data);
42099febf3SMax Reitz     memset(&s->snapshots[i], 0, sizeof(s->snapshots[i]));
43099febf3SMax Reitz }
44099febf3SMax Reitz 
qcow2_free_snapshots(BlockDriverState * bs)45ed6ccf0fSKevin Wolf void qcow2_free_snapshots(BlockDriverState *bs)
46c142442bSKevin Wolf {
47ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
48c142442bSKevin Wolf     int i;
49c142442bSKevin Wolf 
50c142442bSKevin Wolf     for(i = 0; i < s->nb_snapshots; i++) {
51099febf3SMax Reitz         qcow2_free_single_snapshot(bs, i);
52c142442bSKevin Wolf     }
537267c094SAnthony Liguori     g_free(s->snapshots);
54c142442bSKevin Wolf     s->snapshots = NULL;
55c142442bSKevin Wolf     s->nb_snapshots = 0;
56c142442bSKevin Wolf }
57c142442bSKevin Wolf 
58f91f1f15SMax Reitz /*
59f91f1f15SMax Reitz  * If @repair is true, try to repair a broken snapshot table instead
60f91f1f15SMax Reitz  * of just returning an error:
61f91f1f15SMax Reitz  *
62099febf3SMax Reitz  * - If the snapshot table was too long, set *nb_clusters_reduced to
63099febf3SMax Reitz  *   the number of snapshots removed off the end.
64099febf3SMax Reitz  *   The caller will update the on-disk nb_snapshots accordingly;
65099febf3SMax Reitz  *   this leaks clusters, but is safe.
66099febf3SMax Reitz  *   (The on-disk information must be updated before
67099febf3SMax Reitz  *   qcow2_check_refcounts(), because that function relies on
68099febf3SMax Reitz  *   s->nb_snapshots to reflect the on-disk value.)
69099febf3SMax Reitz  *
70f91f1f15SMax Reitz  * - If there were snapshots with too much extra metadata, increment
71f91f1f15SMax Reitz  *   *extra_data_dropped for each.
72f91f1f15SMax Reitz  *   This requires the caller to eventually rewrite the whole snapshot
73f91f1f15SMax Reitz  *   table, which requires cluster allocation.  Therefore, this should
74f91f1f15SMax Reitz  *   be done only after qcow2_check_refcounts() made sure the refcount
75f91f1f15SMax Reitz  *   structures are valid.
76f91f1f15SMax Reitz  *   (In the meantime, the image is still valid because
77f91f1f15SMax Reitz  *   qcow2_check_refcounts() does not do anything with snapshots'
78f91f1f15SMax Reitz  *   extra data.)
79f91f1f15SMax Reitz  */
80a39bae4eSPaolo Bonzini static coroutine_fn GRAPH_RDLOCK
qcow2_do_read_snapshots(BlockDriverState * bs,bool repair,int * nb_clusters_reduced,int * extra_data_dropped,Error ** errp)81a39bae4eSPaolo Bonzini int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
82099febf3SMax Reitz                             int *nb_clusters_reduced,
83f91f1f15SMax Reitz                             int *extra_data_dropped,
84f91f1f15SMax Reitz                             Error **errp)
85c142442bSKevin Wolf {
86ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
87c142442bSKevin Wolf     QCowSnapshotHeader h;
88c2c9a466SKevin Wolf     QCowSnapshotExtraData extra;
89c142442bSKevin Wolf     QCowSnapshot *sn;
90c142442bSKevin Wolf     int i, id_str_size, name_size;
91099febf3SMax Reitz     int64_t offset, pre_sn_offset;
9262414335SMax Reitz     uint64_t table_length = 0;
9342deb29fSKevin Wolf     int ret;
94c142442bSKevin Wolf 
95c142442bSKevin Wolf     if (!s->nb_snapshots) {
96c142442bSKevin Wolf         s->snapshots = NULL;
97c142442bSKevin Wolf         s->snapshots_size = 0;
98c142442bSKevin Wolf         return 0;
99c142442bSKevin Wolf     }
100c142442bSKevin Wolf 
101c142442bSKevin Wolf     offset = s->snapshots_offset;
1025839e53bSMarkus Armbruster     s->snapshots = g_new0(QCowSnapshot, s->nb_snapshots);
10342deb29fSKevin Wolf 
104c142442bSKevin Wolf     for(i = 0; i < s->nb_snapshots; i++) {
105f91f1f15SMax Reitz         bool truncate_unknown_extra_data = false;
106f91f1f15SMax Reitz 
107099febf3SMax Reitz         pre_sn_offset = offset;
10862414335SMax Reitz         table_length = ROUND_UP(table_length, 8);
10962414335SMax Reitz 
11042deb29fSKevin Wolf         /* Read statically sized part of the snapshot header */
1119e029689SAlberto Garcia         offset = ROUND_UP(offset, 8);
112a39bae4eSPaolo Bonzini         ret = bdrv_co_pread(bs->file, offset, sizeof(h), &h, 0);
11342deb29fSKevin Wolf         if (ret < 0) {
114ecf6c7c0SMax Reitz             error_setg_errno(errp, -ret, "Failed to read snapshot table");
115c142442bSKevin Wolf             goto fail;
11642deb29fSKevin Wolf         }
11742deb29fSKevin Wolf 
118c142442bSKevin Wolf         offset += sizeof(h);
119c142442bSKevin Wolf         sn = s->snapshots + i;
120c142442bSKevin Wolf         sn->l1_table_offset = be64_to_cpu(h.l1_table_offset);
121c142442bSKevin Wolf         sn->l1_size = be32_to_cpu(h.l1_size);
122c142442bSKevin Wolf         sn->vm_state_size = be32_to_cpu(h.vm_state_size);
123c142442bSKevin Wolf         sn->date_sec = be32_to_cpu(h.date_sec);
124c142442bSKevin Wolf         sn->date_nsec = be32_to_cpu(h.date_nsec);
125c142442bSKevin Wolf         sn->vm_clock_nsec = be64_to_cpu(h.vm_clock_nsec);
126fcf9a6b7SMax Reitz         sn->extra_data_size = be32_to_cpu(h.extra_data_size);
127c142442bSKevin Wolf 
128c142442bSKevin Wolf         id_str_size = be16_to_cpu(h.id_str_size);
129c142442bSKevin Wolf         name_size = be16_to_cpu(h.name_size);
130c142442bSKevin Wolf 
131fcf9a6b7SMax Reitz         if (sn->extra_data_size > QCOW_MAX_SNAPSHOT_EXTRA_DATA) {
132f91f1f15SMax Reitz             if (!repair) {
133fcf9a6b7SMax Reitz                 ret = -EFBIG;
134fcf9a6b7SMax Reitz                 error_setg(errp, "Too much extra metadata in snapshot table "
135fcf9a6b7SMax Reitz                            "entry %i", i);
136f91f1f15SMax Reitz                 error_append_hint(errp, "You can force-remove this extra "
137f91f1f15SMax Reitz                                   "metadata with qemu-img check -r all\n");
138fcf9a6b7SMax Reitz                 goto fail;
139fcf9a6b7SMax Reitz             }
140fcf9a6b7SMax Reitz 
141f91f1f15SMax Reitz             fprintf(stderr, "Discarding too much extra metadata in snapshot "
142f91f1f15SMax Reitz                     "table entry %i (%" PRIu32 " > %u)\n",
143f91f1f15SMax Reitz                     i, sn->extra_data_size, QCOW_MAX_SNAPSHOT_EXTRA_DATA);
144f91f1f15SMax Reitz 
145f91f1f15SMax Reitz             (*extra_data_dropped)++;
146f91f1f15SMax Reitz             truncate_unknown_extra_data = true;
147f91f1f15SMax Reitz         }
148f91f1f15SMax Reitz 
149fcf9a6b7SMax Reitz         /* Read known extra data */
150a39bae4eSPaolo Bonzini         ret = bdrv_co_pread(bs->file, offset,
15132cc71deSAlberto Faria                             MIN(sizeof(extra), sn->extra_data_size), &extra, 0);
152c2c9a466SKevin Wolf         if (ret < 0) {
153ecf6c7c0SMax Reitz             error_setg_errno(errp, -ret, "Failed to read snapshot table");
154c2c9a466SKevin Wolf             goto fail;
155c2c9a466SKevin Wolf         }
156fcf9a6b7SMax Reitz         offset += MIN(sizeof(extra), sn->extra_data_size);
157c142442bSKevin Wolf 
158fcf9a6b7SMax Reitz         if (sn->extra_data_size >= endof(QCowSnapshotExtraData,
159d8fa8442SMax Reitz                                          vm_state_size_large)) {
160c2c9a466SKevin Wolf             sn->vm_state_size = be64_to_cpu(extra.vm_state_size_large);
161c2c9a466SKevin Wolf         }
162c2c9a466SKevin Wolf 
163fcf9a6b7SMax Reitz         if (sn->extra_data_size >= endof(QCowSnapshotExtraData, disk_size)) {
16490b27759SKevin Wolf             sn->disk_size = be64_to_cpu(extra.disk_size);
16590b27759SKevin Wolf         } else {
16690b27759SKevin Wolf             sn->disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
16790b27759SKevin Wolf         }
16890b27759SKevin Wolf 
169bbacffc5SPavel Dovgalyuk         if (sn->extra_data_size >= endof(QCowSnapshotExtraData, icount)) {
170bbacffc5SPavel Dovgalyuk             sn->icount = be64_to_cpu(extra.icount);
171bbacffc5SPavel Dovgalyuk         } else {
172bbacffc5SPavel Dovgalyuk             sn->icount = -1ULL;
173bbacffc5SPavel Dovgalyuk         }
174bbacffc5SPavel Dovgalyuk 
175fcf9a6b7SMax Reitz         if (sn->extra_data_size > sizeof(extra)) {
176f91f1f15SMax Reitz             uint64_t extra_data_end;
177f91f1f15SMax Reitz             size_t unknown_extra_data_size;
178fcf9a6b7SMax Reitz 
179f91f1f15SMax Reitz             extra_data_end = offset + sn->extra_data_size - sizeof(extra);
180f91f1f15SMax Reitz 
181f91f1f15SMax Reitz             if (truncate_unknown_extra_data) {
182f91f1f15SMax Reitz                 sn->extra_data_size = QCOW_MAX_SNAPSHOT_EXTRA_DATA;
183f91f1f15SMax Reitz             }
184f91f1f15SMax Reitz 
185f91f1f15SMax Reitz             /* Store unknown extra data */
186f91f1f15SMax Reitz             unknown_extra_data_size = sn->extra_data_size - sizeof(extra);
187fcf9a6b7SMax Reitz             sn->unknown_extra_data = g_malloc(unknown_extra_data_size);
188a39bae4eSPaolo Bonzini             ret = bdrv_co_pread(bs->file, offset, unknown_extra_data_size,
18932cc71deSAlberto Faria                                 sn->unknown_extra_data, 0);
190fcf9a6b7SMax Reitz             if (ret < 0) {
191f91f1f15SMax Reitz                 error_setg_errno(errp, -ret,
192f91f1f15SMax Reitz                                  "Failed to read snapshot table");
193fcf9a6b7SMax Reitz                 goto fail;
194fcf9a6b7SMax Reitz             }
195f91f1f15SMax Reitz             offset = extra_data_end;
196fcf9a6b7SMax Reitz         }
197fcf9a6b7SMax Reitz 
19842deb29fSKevin Wolf         /* Read snapshot ID */
1997267c094SAnthony Liguori         sn->id_str = g_malloc(id_str_size + 1);
200a39bae4eSPaolo Bonzini         ret = bdrv_co_pread(bs->file, offset, id_str_size, sn->id_str, 0);
20142deb29fSKevin Wolf         if (ret < 0) {
202ecf6c7c0SMax Reitz             error_setg_errno(errp, -ret, "Failed to read snapshot table");
203c142442bSKevin Wolf             goto fail;
20442deb29fSKevin Wolf         }
205c142442bSKevin Wolf         offset += id_str_size;
206c142442bSKevin Wolf         sn->id_str[id_str_size] = '\0';
207c142442bSKevin Wolf 
20842deb29fSKevin Wolf         /* Read snapshot name */
2097267c094SAnthony Liguori         sn->name = g_malloc(name_size + 1);
210a39bae4eSPaolo Bonzini         ret = bdrv_co_pread(bs->file, offset, name_size, sn->name, 0);
21142deb29fSKevin Wolf         if (ret < 0) {
212ecf6c7c0SMax Reitz             error_setg_errno(errp, -ret, "Failed to read snapshot table");
213c142442bSKevin Wolf             goto fail;
21442deb29fSKevin Wolf         }
215c142442bSKevin Wolf         offset += name_size;
216c142442bSKevin Wolf         sn->name[name_size] = '\0';
2175dae6e30SKevin Wolf 
21862414335SMax Reitz         /* Note that the extra data may have been truncated */
21962414335SMax Reitz         table_length += sizeof(h) + sn->extra_data_size + id_str_size +
22062414335SMax Reitz                         name_size;
22162414335SMax Reitz         if (!repair) {
22262414335SMax Reitz             assert(table_length == offset - s->snapshots_offset);
22362414335SMax Reitz         }
22462414335SMax Reitz 
22562414335SMax Reitz         if (table_length > QCOW_MAX_SNAPSHOTS_SIZE ||
22662414335SMax Reitz             offset - s->snapshots_offset > INT_MAX)
22762414335SMax Reitz         {
228099febf3SMax Reitz             if (!repair) {
2295dae6e30SKevin Wolf                 ret = -EFBIG;
230ecf6c7c0SMax Reitz                 error_setg(errp, "Snapshot table is too big");
231099febf3SMax Reitz                 error_append_hint(errp, "You can force-remove all %u "
232099febf3SMax Reitz                                   "overhanging snapshots with qemu-img check "
233099febf3SMax Reitz                                   "-r all\n", s->nb_snapshots - i);
2345dae6e30SKevin Wolf                 goto fail;
2355dae6e30SKevin Wolf             }
236099febf3SMax Reitz 
237099febf3SMax Reitz             fprintf(stderr, "Discarding %u overhanging snapshots (snapshot "
238099febf3SMax Reitz                     "table is too big)\n", s->nb_snapshots - i);
239099febf3SMax Reitz 
240099febf3SMax Reitz             *nb_clusters_reduced += (s->nb_snapshots - i);
241099febf3SMax Reitz 
242099febf3SMax Reitz             /* Discard current snapshot also */
243099febf3SMax Reitz             qcow2_free_single_snapshot(bs, i);
244099febf3SMax Reitz 
245099febf3SMax Reitz             /*
246099febf3SMax Reitz              * This leaks all the rest of the snapshot table and the
247099febf3SMax Reitz              * snapshots' clusters, but we run in check -r all mode,
248099febf3SMax Reitz              * so qcow2_check_refcounts() will take care of it.
249099febf3SMax Reitz              */
250099febf3SMax Reitz             s->nb_snapshots = i;
251099febf3SMax Reitz             offset = pre_sn_offset;
252099febf3SMax Reitz             break;
253099febf3SMax Reitz         }
254c142442bSKevin Wolf     }
25542deb29fSKevin Wolf 
2565dae6e30SKevin Wolf     assert(offset - s->snapshots_offset <= INT_MAX);
257c142442bSKevin Wolf     s->snapshots_size = offset - s->snapshots_offset;
258c142442bSKevin Wolf     return 0;
25942deb29fSKevin Wolf 
260c142442bSKevin Wolf fail:
261ed6ccf0fSKevin Wolf     qcow2_free_snapshots(bs);
26242deb29fSKevin Wolf     return ret;
263c142442bSKevin Wolf }
264c142442bSKevin Wolf 
qcow2_read_snapshots(BlockDriverState * bs,Error ** errp)265a39bae4eSPaolo Bonzini int coroutine_fn qcow2_read_snapshots(BlockDriverState *bs, Error **errp)
266f91f1f15SMax Reitz {
267099febf3SMax Reitz     return qcow2_do_read_snapshots(bs, false, NULL, NULL, errp);
268f91f1f15SMax Reitz }
269f91f1f15SMax Reitz 
270c142442bSKevin Wolf /* add at the end of the file a new list of snapshots */
qcow2_write_snapshots(BlockDriverState * bs)271e0314b56SMax Reitz int qcow2_write_snapshots(BlockDriverState *bs)
272c142442bSKevin Wolf {
273ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
274c142442bSKevin Wolf     QCowSnapshot *sn;
275c142442bSKevin Wolf     QCowSnapshotHeader h;
276c2c9a466SKevin Wolf     QCowSnapshotExtraData extra;
277c142442bSKevin Wolf     int i, name_size, id_str_size, snapshots_size;
278d69969c4SKevin Wolf     struct {
279d69969c4SKevin Wolf         uint32_t nb_snapshots;
280d69969c4SKevin Wolf         uint64_t snapshots_offset;
281d69969c4SKevin Wolf     } QEMU_PACKED header_data;
2825dae6e30SKevin Wolf     int64_t offset, snapshots_offset = 0;
28307fd8779SKevin Wolf     int ret;
284c142442bSKevin Wolf 
285c142442bSKevin Wolf     /* compute the size of the snapshots */
286c142442bSKevin Wolf     offset = 0;
287c142442bSKevin Wolf     for(i = 0; i < s->nb_snapshots; i++) {
288c142442bSKevin Wolf         sn = s->snapshots + i;
2899e029689SAlberto Garcia         offset = ROUND_UP(offset, 8);
290c142442bSKevin Wolf         offset += sizeof(h);
291fcf9a6b7SMax Reitz         offset += MAX(sizeof(extra), sn->extra_data_size);
292c142442bSKevin Wolf         offset += strlen(sn->id_str);
293c142442bSKevin Wolf         offset += strlen(sn->name);
2945dae6e30SKevin Wolf 
2955dae6e30SKevin Wolf         if (offset > QCOW_MAX_SNAPSHOTS_SIZE) {
2965dae6e30SKevin Wolf             ret = -EFBIG;
2975dae6e30SKevin Wolf             goto fail;
298c142442bSKevin Wolf         }
2995dae6e30SKevin Wolf     }
3005dae6e30SKevin Wolf 
3015dae6e30SKevin Wolf     assert(offset <= INT_MAX);
302c142442bSKevin Wolf     snapshots_size = offset;
303c142442bSKevin Wolf 
30407fd8779SKevin Wolf     /* Allocate space for the new snapshot list */
305ed6ccf0fSKevin Wolf     snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
306c142442bSKevin Wolf     offset = snapshots_offset;
3075d757b56SKevin Wolf     if (offset < 0) {
30837d41f0aSMax Reitz         ret = offset;
30937d41f0aSMax Reitz         goto fail;
3105d757b56SKevin Wolf     }
311f6977f15SStefan Hajnoczi     ret = bdrv_flush(bs);
312f6977f15SStefan Hajnoczi     if (ret < 0) {
31337d41f0aSMax Reitz         goto fail;
314f6977f15SStefan Hajnoczi     }
315c142442bSKevin Wolf 
316cf93980eSMax Reitz     /* The snapshot list position has not yet been updated, so these clusters
317cf93980eSMax Reitz      * must indeed be completely free */
318966b000fSKevin Wolf     ret = qcow2_pre_write_overlap_check(bs, 0, offset, snapshots_size, false);
319cf93980eSMax Reitz     if (ret < 0) {
32037d41f0aSMax Reitz         goto fail;
321cf93980eSMax Reitz     }
322cf93980eSMax Reitz 
323cf93980eSMax Reitz 
32407fd8779SKevin Wolf     /* Write all snapshots to the new list */
325c142442bSKevin Wolf     for(i = 0; i < s->nb_snapshots; i++) {
326c142442bSKevin Wolf         sn = s->snapshots + i;
327c142442bSKevin Wolf         memset(&h, 0, sizeof(h));
328c142442bSKevin Wolf         h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);
329c142442bSKevin Wolf         h.l1_size = cpu_to_be32(sn->l1_size);
330c2c9a466SKevin Wolf         /* If it doesn't fit in 32 bit, older implementations should treat it
331c2c9a466SKevin Wolf          * as a disk-only snapshot rather than truncate the VM state */
332c2c9a466SKevin Wolf         if (sn->vm_state_size <= 0xffffffff) {
333c142442bSKevin Wolf             h.vm_state_size = cpu_to_be32(sn->vm_state_size);
334c2c9a466SKevin Wolf         }
335c142442bSKevin Wolf         h.date_sec = cpu_to_be32(sn->date_sec);
336c142442bSKevin Wolf         h.date_nsec = cpu_to_be32(sn->date_nsec);
337c142442bSKevin Wolf         h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);
338fcf9a6b7SMax Reitz         h.extra_data_size = cpu_to_be32(MAX(sizeof(extra),
339fcf9a6b7SMax Reitz                                             sn->extra_data_size));
340c2c9a466SKevin Wolf 
341c2c9a466SKevin Wolf         memset(&extra, 0, sizeof(extra));
342c2c9a466SKevin Wolf         extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size);
34390b27759SKevin Wolf         extra.disk_size = cpu_to_be64(sn->disk_size);
344bbacffc5SPavel Dovgalyuk         extra.icount = cpu_to_be64(sn->icount);
345c142442bSKevin Wolf 
346c142442bSKevin Wolf         id_str_size = strlen(sn->id_str);
347c142442bSKevin Wolf         name_size = strlen(sn->name);
34888fb1535SMax Reitz         assert(id_str_size <= UINT16_MAX && name_size <= UINT16_MAX);
349c142442bSKevin Wolf         h.id_str_size = cpu_to_be16(id_str_size);
350c142442bSKevin Wolf         h.name_size = cpu_to_be16(name_size);
3519e029689SAlberto Garcia         offset = ROUND_UP(offset, 8);
35207fd8779SKevin Wolf 
35332cc71deSAlberto Faria         ret = bdrv_pwrite(bs->file, offset, sizeof(h), &h, 0);
35407fd8779SKevin Wolf         if (ret < 0) {
355c142442bSKevin Wolf             goto fail;
35607fd8779SKevin Wolf         }
357c142442bSKevin Wolf         offset += sizeof(h);
35807fd8779SKevin Wolf 
35932cc71deSAlberto Faria         ret = bdrv_pwrite(bs->file, offset, sizeof(extra), &extra, 0);
360c2c9a466SKevin Wolf         if (ret < 0) {
361c2c9a466SKevin Wolf             goto fail;
362c2c9a466SKevin Wolf         }
363c2c9a466SKevin Wolf         offset += sizeof(extra);
364c2c9a466SKevin Wolf 
365fcf9a6b7SMax Reitz         if (sn->extra_data_size > sizeof(extra)) {
366fcf9a6b7SMax Reitz             size_t unknown_extra_data_size =
367fcf9a6b7SMax Reitz                 sn->extra_data_size - sizeof(extra);
368fcf9a6b7SMax Reitz 
369fcf9a6b7SMax Reitz             /* qcow2_read_snapshots() ensures no unbounded allocation */
370fcf9a6b7SMax Reitz             assert(unknown_extra_data_size <= BDRV_REQUEST_MAX_BYTES);
371fcf9a6b7SMax Reitz             assert(sn->unknown_extra_data);
372fcf9a6b7SMax Reitz 
37332cc71deSAlberto Faria             ret = bdrv_pwrite(bs->file, offset, unknown_extra_data_size,
37432cc71deSAlberto Faria                               sn->unknown_extra_data, 0);
375fcf9a6b7SMax Reitz             if (ret < 0) {
376fcf9a6b7SMax Reitz                 goto fail;
377fcf9a6b7SMax Reitz             }
378fcf9a6b7SMax Reitz             offset += unknown_extra_data_size;
379fcf9a6b7SMax Reitz         }
380fcf9a6b7SMax Reitz 
38132cc71deSAlberto Faria         ret = bdrv_pwrite(bs->file, offset, id_str_size, sn->id_str, 0);
38207fd8779SKevin Wolf         if (ret < 0) {
383c142442bSKevin Wolf             goto fail;
38407fd8779SKevin Wolf         }
385c142442bSKevin Wolf         offset += id_str_size;
38607fd8779SKevin Wolf 
38732cc71deSAlberto Faria         ret = bdrv_pwrite(bs->file, offset, name_size, sn->name, 0);
38807fd8779SKevin Wolf         if (ret < 0) {
389c142442bSKevin Wolf             goto fail;
39007fd8779SKevin Wolf         }
391c142442bSKevin Wolf         offset += name_size;
392c142442bSKevin Wolf     }
393c142442bSKevin Wolf 
39407fd8779SKevin Wolf     /*
39507fd8779SKevin Wolf      * Update the header to point to the new snapshot table. This requires the
39607fd8779SKevin Wolf      * new table and its refcounts to be stable on disk.
39707fd8779SKevin Wolf      */
39807fd8779SKevin Wolf     ret = bdrv_flush(bs);
39907fd8779SKevin Wolf     if (ret < 0) {
40007fd8779SKevin Wolf         goto fail;
40107fd8779SKevin Wolf     }
40207fd8779SKevin Wolf 
403d69969c4SKevin Wolf     QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=
404d8fa8442SMax Reitz                       endof(QCowHeader, nb_snapshots));
40507fd8779SKevin Wolf 
406d69969c4SKevin Wolf     header_data.nb_snapshots        = cpu_to_be32(s->nb_snapshots);
407d69969c4SKevin Wolf     header_data.snapshots_offset    = cpu_to_be64(snapshots_offset);
408d69969c4SKevin Wolf 
409d9ca2ea2SKevin Wolf     ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
41032cc71deSAlberto Faria                            sizeof(header_data), &header_data, 0);
41107fd8779SKevin Wolf     if (ret < 0) {
412c142442bSKevin Wolf         goto fail;
41307fd8779SKevin Wolf     }
414c142442bSKevin Wolf 
415c142442bSKevin Wolf     /* free the old snapshot table */
4166cfcb9b8SKevin Wolf     qcow2_free_clusters(bs, s->snapshots_offset, s->snapshots_size,
4176cfcb9b8SKevin Wolf                         QCOW2_DISCARD_SNAPSHOT);
418c142442bSKevin Wolf     s->snapshots_offset = snapshots_offset;
419c142442bSKevin Wolf     s->snapshots_size = snapshots_size;
420c142442bSKevin Wolf     return 0;
42107fd8779SKevin Wolf 
422c142442bSKevin Wolf fail:
4239186ad96SMax Reitz     if (snapshots_offset > 0) {
4249186ad96SMax Reitz         qcow2_free_clusters(bs, snapshots_offset, snapshots_size,
4259186ad96SMax Reitz                             QCOW2_DISCARD_ALWAYS);
4269186ad96SMax Reitz     }
42707fd8779SKevin Wolf     return ret;
428c142442bSKevin Wolf }
429c142442bSKevin Wolf 
qcow2_check_read_snapshot_table(BlockDriverState * bs,BdrvCheckResult * result,BdrvCheckMode fix)4308bc584feSMax Reitz int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
4318bc584feSMax Reitz                                                  BdrvCheckResult *result,
4328bc584feSMax Reitz                                                  BdrvCheckMode fix)
4338bc584feSMax Reitz {
4348bc584feSMax Reitz     BDRVQcow2State *s = bs->opaque;
4358bc584feSMax Reitz     Error *local_err = NULL;
436099febf3SMax Reitz     int nb_clusters_reduced = 0;
437f91f1f15SMax Reitz     int extra_data_dropped = 0;
4388bc584feSMax Reitz     int ret;
4398bc584feSMax Reitz     struct {
4408bc584feSMax Reitz         uint32_t nb_snapshots;
4418bc584feSMax Reitz         uint64_t snapshots_offset;
4428bc584feSMax Reitz     } QEMU_PACKED snapshot_table_pointer;
4438bc584feSMax Reitz 
4448bc584feSMax Reitz     /* qcow2_do_open() discards this information in check mode */
44538505e2aSAlberto Faria     ret = bdrv_co_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
44632cc71deSAlberto Faria                         sizeof(snapshot_table_pointer), &snapshot_table_pointer,
44753fb7844SAlberto Faria                         0);
4488bc584feSMax Reitz     if (ret < 0) {
4498bc584feSMax Reitz         result->check_errors++;
4508bc584feSMax Reitz         fprintf(stderr, "ERROR failed to read the snapshot table pointer from "
4518bc584feSMax Reitz                 "the image header: %s\n", strerror(-ret));
4528bc584feSMax Reitz         return ret;
4538bc584feSMax Reitz     }
4548bc584feSMax Reitz 
4558bc584feSMax Reitz     s->snapshots_offset = be64_to_cpu(snapshot_table_pointer.snapshots_offset);
4568bc584feSMax Reitz     s->nb_snapshots = be32_to_cpu(snapshot_table_pointer.nb_snapshots);
4578bc584feSMax Reitz 
458d2b1d1ecSMax Reitz     if (s->nb_snapshots > QCOW_MAX_SNAPSHOTS && (fix & BDRV_FIX_ERRORS)) {
459d2b1d1ecSMax Reitz         fprintf(stderr, "Discarding %u overhanging snapshots\n",
460d2b1d1ecSMax Reitz                 s->nb_snapshots - QCOW_MAX_SNAPSHOTS);
461d2b1d1ecSMax Reitz 
462d2b1d1ecSMax Reitz         nb_clusters_reduced += s->nb_snapshots - QCOW_MAX_SNAPSHOTS;
463d2b1d1ecSMax Reitz         s->nb_snapshots = QCOW_MAX_SNAPSHOTS;
464d2b1d1ecSMax Reitz     }
465d2b1d1ecSMax Reitz 
4668bc584feSMax Reitz     ret = qcow2_validate_table(bs, s->snapshots_offset, s->nb_snapshots,
4678bc584feSMax Reitz                                sizeof(QCowSnapshotHeader),
4688bc584feSMax Reitz                                sizeof(QCowSnapshotHeader) * QCOW_MAX_SNAPSHOTS,
4698bc584feSMax Reitz                                "snapshot table", &local_err);
4708bc584feSMax Reitz     if (ret < 0) {
4718bc584feSMax Reitz         result->check_errors++;
4728bc584feSMax Reitz         error_reportf_err(local_err, "ERROR ");
4738bc584feSMax Reitz 
474d2b1d1ecSMax Reitz         if (s->nb_snapshots > QCOW_MAX_SNAPSHOTS) {
475d2b1d1ecSMax Reitz             fprintf(stderr, "You can force-remove all %u overhanging snapshots "
476d2b1d1ecSMax Reitz                     "with qemu-img check -r all\n",
477d2b1d1ecSMax Reitz                     s->nb_snapshots - QCOW_MAX_SNAPSHOTS);
478d2b1d1ecSMax Reitz         }
479d2b1d1ecSMax Reitz 
4808bc584feSMax Reitz         /* We did not read the snapshot table, so invalidate this information */
4818bc584feSMax Reitz         s->snapshots_offset = 0;
4828bc584feSMax Reitz         s->nb_snapshots = 0;
4838bc584feSMax Reitz 
4848bc584feSMax Reitz         return ret;
4858bc584feSMax Reitz     }
4868bc584feSMax Reitz 
4878bc584feSMax Reitz     qemu_co_mutex_unlock(&s->lock);
488f91f1f15SMax Reitz     ret = qcow2_do_read_snapshots(bs, fix & BDRV_FIX_ERRORS,
489099febf3SMax Reitz                                   &nb_clusters_reduced, &extra_data_dropped,
490099febf3SMax Reitz                                   &local_err);
4918bc584feSMax Reitz     qemu_co_mutex_lock(&s->lock);
4928bc584feSMax Reitz     if (ret < 0) {
4938bc584feSMax Reitz         result->check_errors++;
4948bc584feSMax Reitz         error_reportf_err(local_err,
4958bc584feSMax Reitz                           "ERROR failed to read the snapshot table: ");
4968bc584feSMax Reitz 
4978bc584feSMax Reitz         /* We did not read the snapshot table, so invalidate this information */
4988bc584feSMax Reitz         s->snapshots_offset = 0;
4998bc584feSMax Reitz         s->nb_snapshots = 0;
5008bc584feSMax Reitz 
5018bc584feSMax Reitz         return ret;
5028bc584feSMax Reitz     }
503099febf3SMax Reitz     result->corruptions += nb_clusters_reduced + extra_data_dropped;
504099febf3SMax Reitz 
505099febf3SMax Reitz     if (nb_clusters_reduced) {
506099febf3SMax Reitz         /*
507099febf3SMax Reitz          * Update image header now, because:
508099febf3SMax Reitz          * (1) qcow2_check_refcounts() relies on s->nb_snapshots to be
509099febf3SMax Reitz          *     the same as what the image header says,
510099febf3SMax Reitz          * (2) this leaks clusters, but qcow2_check_refcounts() will
511099febf3SMax Reitz          *     fix that.
512099febf3SMax Reitz          */
513099febf3SMax Reitz         assert(fix & BDRV_FIX_ERRORS);
514099febf3SMax Reitz 
515099febf3SMax Reitz         snapshot_table_pointer.nb_snapshots = cpu_to_be32(s->nb_snapshots);
516a8f0e83cSAlberto Faria         ret = bdrv_co_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
51732cc71deSAlberto Faria                                   sizeof(snapshot_table_pointer.nb_snapshots),
51832cc71deSAlberto Faria                                   &snapshot_table_pointer.nb_snapshots, 0);
519099febf3SMax Reitz         if (ret < 0) {
520099febf3SMax Reitz             result->check_errors++;
521099febf3SMax Reitz             fprintf(stderr, "ERROR failed to update the snapshot count in the "
522099febf3SMax Reitz                     "image header: %s\n", strerror(-ret));
523099febf3SMax Reitz             return ret;
524099febf3SMax Reitz         }
525099febf3SMax Reitz 
526099febf3SMax Reitz         result->corruptions_fixed += nb_clusters_reduced;
527099febf3SMax Reitz         result->corruptions -= nb_clusters_reduced;
528099febf3SMax Reitz     }
5298bc584feSMax Reitz 
530e40e6e88SMax Reitz     /*
531e40e6e88SMax Reitz      * All of v3 images' snapshot table entries need to have at least
532e40e6e88SMax Reitz      * 16 bytes of extra data.
533e40e6e88SMax Reitz      */
534e40e6e88SMax Reitz     if (s->qcow_version >= 3) {
535e40e6e88SMax Reitz         int i;
536e40e6e88SMax Reitz         for (i = 0; i < s->nb_snapshots; i++) {
537e40e6e88SMax Reitz             if (s->snapshots[i].extra_data_size <
538e40e6e88SMax Reitz                 sizeof_field(QCowSnapshotExtraData, vm_state_size_large) +
539e40e6e88SMax Reitz                 sizeof_field(QCowSnapshotExtraData, disk_size))
540e40e6e88SMax Reitz             {
541e40e6e88SMax Reitz                 result->corruptions++;
542e40e6e88SMax Reitz                 fprintf(stderr, "%s snapshot table entry %i is incomplete\n",
543e40e6e88SMax Reitz                         fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR", i);
544e40e6e88SMax Reitz             }
545e40e6e88SMax Reitz         }
546e40e6e88SMax Reitz     }
547e40e6e88SMax Reitz 
5488bc584feSMax Reitz     return 0;
5498bc584feSMax Reitz }
5508bc584feSMax Reitz 
qcow2_check_fix_snapshot_table(BlockDriverState * bs,BdrvCheckResult * result,BdrvCheckMode fix)551fe446b5dSMax Reitz int coroutine_fn qcow2_check_fix_snapshot_table(BlockDriverState *bs,
552fe446b5dSMax Reitz                                                 BdrvCheckResult *result,
553fe446b5dSMax Reitz                                                 BdrvCheckMode fix)
554fe446b5dSMax Reitz {
555fe446b5dSMax Reitz     BDRVQcow2State *s = bs->opaque;
556fe446b5dSMax Reitz     int ret;
557fe446b5dSMax Reitz 
558fe446b5dSMax Reitz     if (result->corruptions && (fix & BDRV_FIX_ERRORS)) {
559fe446b5dSMax Reitz         qemu_co_mutex_unlock(&s->lock);
560fe446b5dSMax Reitz         ret = qcow2_write_snapshots(bs);
561fe446b5dSMax Reitz         qemu_co_mutex_lock(&s->lock);
562fe446b5dSMax Reitz         if (ret < 0) {
563fe446b5dSMax Reitz             result->check_errors++;
564fe446b5dSMax Reitz             fprintf(stderr, "ERROR failed to update snapshot table: %s\n",
565fe446b5dSMax Reitz                     strerror(-ret));
566fe446b5dSMax Reitz             return ret;
567fe446b5dSMax Reitz         }
568fe446b5dSMax Reitz 
569fe446b5dSMax Reitz         result->corruptions_fixed += result->corruptions;
570fe446b5dSMax Reitz         result->corruptions = 0;
571fe446b5dSMax Reitz     }
572fe446b5dSMax Reitz 
573fe446b5dSMax Reitz     return 0;
574fe446b5dSMax Reitz }
575fe446b5dSMax Reitz 
find_new_snapshot_id(BlockDriverState * bs,char * id_str,int id_str_size)576c142442bSKevin Wolf static void find_new_snapshot_id(BlockDriverState *bs,
577c142442bSKevin Wolf                                  char *id_str, int id_str_size)
578c142442bSKevin Wolf {
579ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
580c142442bSKevin Wolf     QCowSnapshot *sn;
58100c49b21SMax Reitz     int i;
58200c49b21SMax Reitz     unsigned long id, id_max = 0;
583c142442bSKevin Wolf 
584c142442bSKevin Wolf     for(i = 0; i < s->nb_snapshots; i++) {
585c142442bSKevin Wolf         sn = s->snapshots + i;
586c142442bSKevin Wolf         id = strtoul(sn->id_str, NULL, 10);
587c142442bSKevin Wolf         if (id > id_max)
588c142442bSKevin Wolf             id_max = id;
589c142442bSKevin Wolf     }
59000c49b21SMax Reitz     snprintf(id_str, id_str_size, "%lu", id_max + 1);
591c142442bSKevin Wolf }
592c142442bSKevin Wolf 
find_snapshot_by_id_and_name(BlockDriverState * bs,const char * id,const char * name)593a89d89d3SWenchao Xia static int find_snapshot_by_id_and_name(BlockDriverState *bs,
594a89d89d3SWenchao Xia                                         const char *id,
595a89d89d3SWenchao Xia                                         const char *name)
596c142442bSKevin Wolf {
597ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
598c142442bSKevin Wolf     int i;
599c142442bSKevin Wolf 
600a89d89d3SWenchao Xia     if (id && name) {
601c142442bSKevin Wolf         for (i = 0; i < s->nb_snapshots; i++) {
602a89d89d3SWenchao Xia             if (!strcmp(s->snapshots[i].id_str, id) &&
603a89d89d3SWenchao Xia                 !strcmp(s->snapshots[i].name, name)) {
604c142442bSKevin Wolf                 return i;
605c142442bSKevin Wolf             }
606a89d89d3SWenchao Xia         }
607a89d89d3SWenchao Xia     } else if (id) {
608a89d89d3SWenchao Xia         for (i = 0; i < s->nb_snapshots; i++) {
609a89d89d3SWenchao Xia             if (!strcmp(s->snapshots[i].id_str, id)) {
610a89d89d3SWenchao Xia                 return i;
611a89d89d3SWenchao Xia             }
612a89d89d3SWenchao Xia         }
613a89d89d3SWenchao Xia     } else if (name) {
614a89d89d3SWenchao Xia         for (i = 0; i < s->nb_snapshots; i++) {
615a89d89d3SWenchao Xia             if (!strcmp(s->snapshots[i].name, name)) {
616a89d89d3SWenchao Xia                 return i;
617a89d89d3SWenchao Xia             }
618a89d89d3SWenchao Xia         }
619a89d89d3SWenchao Xia     }
620a89d89d3SWenchao Xia 
621c142442bSKevin Wolf     return -1;
622c142442bSKevin Wolf }
623c142442bSKevin Wolf 
find_snapshot_by_id_or_name(BlockDriverState * bs,const char * id_or_name)624a89d89d3SWenchao Xia static int find_snapshot_by_id_or_name(BlockDriverState *bs,
625a89d89d3SWenchao Xia                                        const char *id_or_name)
626c142442bSKevin Wolf {
627a89d89d3SWenchao Xia     int ret;
628c142442bSKevin Wolf 
629a89d89d3SWenchao Xia     ret = find_snapshot_by_id_and_name(bs, id_or_name, NULL);
630a89d89d3SWenchao Xia     if (ret >= 0) {
631c142442bSKevin Wolf         return ret;
632c142442bSKevin Wolf     }
633a89d89d3SWenchao Xia     return find_snapshot_by_id_and_name(bs, NULL, id_or_name);
634c142442bSKevin Wolf }
635c142442bSKevin Wolf 
636c142442bSKevin Wolf /* if no id is provided, a new one is constructed */
qcow2_snapshot_create(BlockDriverState * bs,QEMUSnapshotInfo * sn_info)637ed6ccf0fSKevin Wolf int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
638c142442bSKevin Wolf {
639ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
640d1ea98d5SKevin Wolf     QCowSnapshot *new_snapshot_list = NULL;
641d1ea98d5SKevin Wolf     QCowSnapshot *old_snapshot_list = NULL;
642d1ea98d5SKevin Wolf     QCowSnapshot sn1, *sn = &sn1;
643c142442bSKevin Wolf     int i, ret;
644c142442bSKevin Wolf     uint64_t *l1_table = NULL;
6455d757b56SKevin Wolf     int64_t l1_table_offset;
646c142442bSKevin Wolf 
647ce48f2f4SKevin Wolf     if (s->nb_snapshots >= QCOW_MAX_SNAPSHOTS) {
648ce48f2f4SKevin Wolf         return -EFBIG;
649ce48f2f4SKevin Wolf     }
650ce48f2f4SKevin Wolf 
651aa8b34c1SKevin Wolf     if (has_data_file(bs)) {
652aa8b34c1SKevin Wolf         return -ENOTSUP;
653aa8b34c1SKevin Wolf     }
654aa8b34c1SKevin Wolf 
655c142442bSKevin Wolf     memset(sn, 0, sizeof(*sn));
656c142442bSKevin Wolf 
657407bc150SYi Wang     /* Generate an ID */
658c142442bSKevin Wolf     find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
659c142442bSKevin Wolf 
66003343166SKevin Wolf     /* Populate sn with passed data */
6617267c094SAnthony Liguori     sn->id_str = g_strdup(sn_info->id_str);
6627267c094SAnthony Liguori     sn->name = g_strdup(sn_info->name);
66303343166SKevin Wolf 
66490b27759SKevin Wolf     sn->disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
665c142442bSKevin Wolf     sn->vm_state_size = sn_info->vm_state_size;
666c142442bSKevin Wolf     sn->date_sec = sn_info->date_sec;
667c142442bSKevin Wolf     sn->date_nsec = sn_info->date_nsec;
668c142442bSKevin Wolf     sn->vm_clock_nsec = sn_info->vm_clock_nsec;
669b39847a5SPavel Dovgalyuk     sn->icount = sn_info->icount;
670fcf9a6b7SMax Reitz     sn->extra_data_size = sizeof(QCowSnapshotExtraData);
671c142442bSKevin Wolf 
67203343166SKevin Wolf     /* Allocate the L1 table of the snapshot and copy the current one there. */
67302b1ecfaSAlberto Garcia     l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * L1E_SIZE);
6745d757b56SKevin Wolf     if (l1_table_offset < 0) {
675d1ea98d5SKevin Wolf         ret = l1_table_offset;
6765d757b56SKevin Wolf         goto fail;
6775d757b56SKevin Wolf     }
6785d757b56SKevin Wolf 
6795d757b56SKevin Wolf     sn->l1_table_offset = l1_table_offset;
680c142442bSKevin Wolf     sn->l1_size = s->l1_size;
681c142442bSKevin Wolf 
6825839e53bSMarkus Armbruster     l1_table = g_try_new(uint64_t, s->l1_size);
683de82815dSKevin Wolf     if (s->l1_size && l1_table == NULL) {
684de82815dSKevin Wolf         ret = -ENOMEM;
685de82815dSKevin Wolf         goto fail;
686de82815dSKevin Wolf     }
687de82815dSKevin Wolf 
688c142442bSKevin Wolf     for(i = 0; i < s->l1_size; i++) {
689c142442bSKevin Wolf         l1_table[i] = cpu_to_be64(s->l1_table[i]);
690c142442bSKevin Wolf     }
691d1ea98d5SKevin Wolf 
692231bb267SMax Reitz     ret = qcow2_pre_write_overlap_check(bs, 0, sn->l1_table_offset,
69302b1ecfaSAlberto Garcia                                         s->l1_size * L1E_SIZE, false);
694cf93980eSMax Reitz     if (ret < 0) {
695cf93980eSMax Reitz         goto fail;
696cf93980eSMax Reitz     }
697cf93980eSMax Reitz 
69832cc71deSAlberto Faria     ret = bdrv_pwrite(bs->file, sn->l1_table_offset, s->l1_size * L1E_SIZE,
69932cc71deSAlberto Faria                       l1_table, 0);
700d1ea98d5SKevin Wolf     if (ret < 0) {
701c142442bSKevin Wolf         goto fail;
702d1ea98d5SKevin Wolf     }
703d1ea98d5SKevin Wolf 
7047267c094SAnthony Liguori     g_free(l1_table);
705c142442bSKevin Wolf     l1_table = NULL;
706c142442bSKevin Wolf 
707d1ea98d5SKevin Wolf     /*
708d1ea98d5SKevin Wolf      * Increase the refcounts of all clusters and make sure everything is
709d1ea98d5SKevin Wolf      * stable on disk before updating the snapshot table to contain a pointer
710d1ea98d5SKevin Wolf      * to the new L1 table.
711d1ea98d5SKevin Wolf      */
712d1ea98d5SKevin Wolf     ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1);
713d1ea98d5SKevin Wolf     if (ret < 0) {
714d1ea98d5SKevin Wolf         goto fail;
715c142442bSKevin Wolf     }
716d1ea98d5SKevin Wolf 
717d1ea98d5SKevin Wolf     /* Append the new snapshot to the snapshot list */
7185839e53bSMarkus Armbruster     new_snapshot_list = g_new(QCowSnapshot, s->nb_snapshots + 1);
719d1ea98d5SKevin Wolf     if (s->snapshots) {
720d1ea98d5SKevin Wolf         memcpy(new_snapshot_list, s->snapshots,
721d1ea98d5SKevin Wolf                s->nb_snapshots * sizeof(QCowSnapshot));
722d1ea98d5SKevin Wolf         old_snapshot_list = s->snapshots;
723d1ea98d5SKevin Wolf     }
724d1ea98d5SKevin Wolf     s->snapshots = new_snapshot_list;
725c142442bSKevin Wolf     s->snapshots[s->nb_snapshots++] = *sn;
726c142442bSKevin Wolf 
727d1ea98d5SKevin Wolf     ret = qcow2_write_snapshots(bs);
728d1ea98d5SKevin Wolf     if (ret < 0) {
729d1ea98d5SKevin Wolf         g_free(s->snapshots);
730d1ea98d5SKevin Wolf         s->snapshots = old_snapshot_list;
73184757f7eSMax Reitz         s->nb_snapshots--;
732c142442bSKevin Wolf         goto fail;
733d1ea98d5SKevin Wolf     }
734d1ea98d5SKevin Wolf 
735d1ea98d5SKevin Wolf     g_free(old_snapshot_list);
736d1ea98d5SKevin Wolf 
7371ebf561cSKevin Wolf     /* The VM state isn't needed any more in the active L1 table; in fact, it
7381ebf561cSKevin Wolf      * hurts by causing expensive COW for the next snapshot. */
739d2cb36afSEric Blake     qcow2_cluster_discard(bs, qcow2_vm_state_offset(s),
7409e029689SAlberto Garcia                           ROUND_UP(sn->vm_state_size, s->cluster_size),
741808c4b6fSMax Reitz                           QCOW2_DISCARD_NEVER, false);
7421ebf561cSKevin Wolf 
743c142442bSKevin Wolf #ifdef DEBUG_ALLOC
7446cbc3031SPhilipp Hahn     {
7456cbc3031SPhilipp Hahn       BdrvCheckResult result = {0};
746b35278f7SStefan Hajnoczi       qcow2_check_refcounts(bs, &result, 0);
7476cbc3031SPhilipp Hahn     }
748c142442bSKevin Wolf #endif
749c142442bSKevin Wolf     return 0;
75003343166SKevin Wolf 
751c142442bSKevin Wolf fail:
75203343166SKevin Wolf     g_free(sn->id_str);
7537267c094SAnthony Liguori     g_free(sn->name);
7547267c094SAnthony Liguori     g_free(l1_table);
755d1ea98d5SKevin Wolf 
756d1ea98d5SKevin Wolf     return ret;
757c142442bSKevin Wolf }
758c142442bSKevin Wolf 
759c142442bSKevin Wolf /* copy the snapshot 'snapshot_name' into the current disk image */
qcow2_snapshot_goto(BlockDriverState * bs,const char * snapshot_id)760ed6ccf0fSKevin Wolf int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
761c142442bSKevin Wolf {
762ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
763c142442bSKevin Wolf     QCowSnapshot *sn;
764a8475d75SAlberto Garcia     Error *local_err = NULL;
76535d7ace7SKevin Wolf     int i, snapshot_index;
76635d7ace7SKevin Wolf     int cur_l1_bytes, sn_l1_bytes;
767589f284bSKevin Wolf     int ret;
76843a0cac4SKevin Wolf     uint64_t *sn_l1_table = NULL;
769c142442bSKevin Wolf 
770aa8b34c1SKevin Wolf     if (has_data_file(bs)) {
771aa8b34c1SKevin Wolf         return -ENOTSUP;
772aa8b34c1SKevin Wolf     }
773aa8b34c1SKevin Wolf 
774589f284bSKevin Wolf     /* Search the snapshot */
775c142442bSKevin Wolf     snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
776589f284bSKevin Wolf     if (snapshot_index < 0) {
777c142442bSKevin Wolf         return -ENOENT;
778589f284bSKevin Wolf     }
779c142442bSKevin Wolf     sn = &s->snapshots[snapshot_index];
780c142442bSKevin Wolf 
781a8475d75SAlberto Garcia     ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size,
78202b1ecfaSAlberto Garcia                                L1E_SIZE, QCOW_MAX_L1_SIZE,
783a8475d75SAlberto Garcia                                "Snapshot L1 table", &local_err);
784a8475d75SAlberto Garcia     if (ret < 0) {
785a8475d75SAlberto Garcia         error_report_err(local_err);
786a8475d75SAlberto Garcia         goto fail;
787a8475d75SAlberto Garcia     }
788a8475d75SAlberto Garcia 
78990b27759SKevin Wolf     if (sn->disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) {
7907fa140abSEric Blake         BlockBackend *blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL,
7917fa140abSEric Blake                                             &local_err);
7927fa140abSEric Blake         if (!blk) {
7937fa140abSEric Blake             error_report_err(local_err);
79490b27759SKevin Wolf             ret = -ENOTSUP;
79590b27759SKevin Wolf             goto fail;
79690b27759SKevin Wolf         }
79790b27759SKevin Wolf 
7987fa140abSEric Blake         ret = blk_truncate(blk, sn->disk_size, true, PREALLOC_MODE_OFF, 0,
7997fa140abSEric Blake                            &local_err);
8007fa140abSEric Blake         blk_unref(blk);
8017fa140abSEric Blake         if (ret < 0) {
8027fa140abSEric Blake             error_report_err(local_err);
8037fa140abSEric Blake             goto fail;
8047fa140abSEric Blake         }
8057fa140abSEric Blake     }
8067fa140abSEric Blake 
807589f284bSKevin Wolf     /*
808589f284bSKevin Wolf      * Make sure that the current L1 table is big enough to contain the whole
809589f284bSKevin Wolf      * L1 table of the snapshot. If the snapshot L1 table is smaller, the
810589f284bSKevin Wolf      * current one must be padded with zeros.
811589f284bSKevin Wolf      */
812589f284bSKevin Wolf     ret = qcow2_grow_l1_table(bs, sn->l1_size, true);
813589f284bSKevin Wolf     if (ret < 0) {
814c142442bSKevin Wolf         goto fail;
815589f284bSKevin Wolf     }
816c142442bSKevin Wolf 
81702b1ecfaSAlberto Garcia     cur_l1_bytes = s->l1_size * L1E_SIZE;
81802b1ecfaSAlberto Garcia     sn_l1_bytes = sn->l1_size * L1E_SIZE;
81935d7ace7SKevin Wolf 
820589f284bSKevin Wolf     /*
821589f284bSKevin Wolf      * Copy the snapshot L1 table to the current L1 table.
822589f284bSKevin Wolf      *
823589f284bSKevin Wolf      * Before overwriting the old current L1 table on disk, make sure to
824589f284bSKevin Wolf      * increase all refcounts for the clusters referenced by the new one.
82543a0cac4SKevin Wolf      * Decrease the refcount referenced by the old one only when the L1
82643a0cac4SKevin Wolf      * table is overwritten.
827589f284bSKevin Wolf      */
828de82815dSKevin Wolf     sn_l1_table = g_try_malloc0(cur_l1_bytes);
829de82815dSKevin Wolf     if (cur_l1_bytes && sn_l1_table == NULL) {
830de82815dSKevin Wolf         ret = -ENOMEM;
831de82815dSKevin Wolf         goto fail;
832de82815dSKevin Wolf     }
83343a0cac4SKevin Wolf 
83432cc71deSAlberto Faria     ret = bdrv_pread(bs->file, sn->l1_table_offset, sn_l1_bytes, sn_l1_table,
83553fb7844SAlberto Faria                      0);
836589f284bSKevin Wolf     if (ret < 0) {
837c142442bSKevin Wolf         goto fail;
838589f284bSKevin Wolf     }
839589f284bSKevin Wolf 
84043a0cac4SKevin Wolf     ret = qcow2_update_snapshot_refcount(bs, sn->l1_table_offset,
84143a0cac4SKevin Wolf                                          sn->l1_size, 1);
84243a0cac4SKevin Wolf     if (ret < 0) {
84343a0cac4SKevin Wolf         goto fail;
84443a0cac4SKevin Wolf     }
84543a0cac4SKevin Wolf 
846231bb267SMax Reitz     ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1,
847966b000fSKevin Wolf                                         s->l1_table_offset, cur_l1_bytes,
848966b000fSKevin Wolf                                         false);
849cf93980eSMax Reitz     if (ret < 0) {
850cf93980eSMax Reitz         goto fail;
851cf93980eSMax Reitz     }
852cf93980eSMax Reitz 
85332cc71deSAlberto Faria     ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, cur_l1_bytes,
85432cc71deSAlberto Faria                            sn_l1_table, 0);
855589f284bSKevin Wolf     if (ret < 0) {
856c142442bSKevin Wolf         goto fail;
857589f284bSKevin Wolf     }
858589f284bSKevin Wolf 
85943a0cac4SKevin Wolf     /*
86043a0cac4SKevin Wolf      * Decrease refcount of clusters of current L1 table.
86143a0cac4SKevin Wolf      *
86243a0cac4SKevin Wolf      * At this point, the in-memory s->l1_table points to the old L1 table,
86343a0cac4SKevin Wolf      * whereas on disk we already have the new one.
86443a0cac4SKevin Wolf      *
86543a0cac4SKevin Wolf      * qcow2_update_snapshot_refcount special cases the current L1 table to use
86643a0cac4SKevin Wolf      * the in-memory data instead of really using the offset to load a new one,
86743a0cac4SKevin Wolf      * which is why this works.
86843a0cac4SKevin Wolf      */
86943a0cac4SKevin Wolf     ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset,
87043a0cac4SKevin Wolf                                          s->l1_size, -1);
87143a0cac4SKevin Wolf 
87243a0cac4SKevin Wolf     /*
87343a0cac4SKevin Wolf      * Now update the in-memory L1 table to be in sync with the on-disk one. We
87443a0cac4SKevin Wolf      * need to do this even if updating refcounts failed.
87543a0cac4SKevin Wolf      */
876c142442bSKevin Wolf     for(i = 0;i < s->l1_size; i++) {
87743a0cac4SKevin Wolf         s->l1_table[i] = be64_to_cpu(sn_l1_table[i]);
878c142442bSKevin Wolf     }
879c142442bSKevin Wolf 
88043a0cac4SKevin Wolf     if (ret < 0) {
88143a0cac4SKevin Wolf         goto fail;
88243a0cac4SKevin Wolf     }
88343a0cac4SKevin Wolf 
88443a0cac4SKevin Wolf     g_free(sn_l1_table);
88543a0cac4SKevin Wolf     sn_l1_table = NULL;
88643a0cac4SKevin Wolf 
88743a0cac4SKevin Wolf     /*
88843a0cac4SKevin Wolf      * Update QCOW_OFLAG_COPIED in the active L1 table (it may have changed
88943a0cac4SKevin Wolf      * when we decreased the refcount of the old snapshot.
89043a0cac4SKevin Wolf      */
89143a0cac4SKevin Wolf     ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
892589f284bSKevin Wolf     if (ret < 0) {
893c142442bSKevin Wolf         goto fail;
894589f284bSKevin Wolf     }
895c142442bSKevin Wolf 
896c142442bSKevin Wolf #ifdef DEBUG_ALLOC
8976cbc3031SPhilipp Hahn     {
8986cbc3031SPhilipp Hahn         BdrvCheckResult result = {0};
899b35278f7SStefan Hajnoczi         qcow2_check_refcounts(bs, &result, 0);
9006cbc3031SPhilipp Hahn     }
901c142442bSKevin Wolf #endif
902c142442bSKevin Wolf     return 0;
903589f284bSKevin Wolf 
904c142442bSKevin Wolf fail:
90543a0cac4SKevin Wolf     g_free(sn_l1_table);
906589f284bSKevin Wolf     return ret;
907c142442bSKevin Wolf }
908c142442bSKevin Wolf 
qcow2_snapshot_delete(BlockDriverState * bs,const char * snapshot_id,const char * name,Error ** errp)909a89d89d3SWenchao Xia int qcow2_snapshot_delete(BlockDriverState *bs,
910a89d89d3SWenchao Xia                           const char *snapshot_id,
911a89d89d3SWenchao Xia                           const char *name,
912a89d89d3SWenchao Xia                           Error **errp)
913c142442bSKevin Wolf {
914ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
9159a476780SKevin Wolf     QCowSnapshot sn;
916c142442bSKevin Wolf     int snapshot_index, ret;
917c142442bSKevin Wolf 
918aa8b34c1SKevin Wolf     if (has_data_file(bs)) {
919aa8b34c1SKevin Wolf         return -ENOTSUP;
920aa8b34c1SKevin Wolf     }
921aa8b34c1SKevin Wolf 
9229a476780SKevin Wolf     /* Search the snapshot */
923a89d89d3SWenchao Xia     snapshot_index = find_snapshot_by_id_and_name(bs, snapshot_id, name);
9249a476780SKevin Wolf     if (snapshot_index < 0) {
925a89d89d3SWenchao Xia         error_setg(errp, "Can't find the snapshot");
926c142442bSKevin Wolf         return -ENOENT;
9279a476780SKevin Wolf     }
9289a476780SKevin Wolf     sn = s->snapshots[snapshot_index];
929c142442bSKevin Wolf 
930db5794f1SAlberto Garcia     ret = qcow2_validate_table(bs, sn.l1_table_offset, sn.l1_size,
93102b1ecfaSAlberto Garcia                                L1E_SIZE, QCOW_MAX_L1_SIZE,
932db5794f1SAlberto Garcia                                "Snapshot L1 table", errp);
933db5794f1SAlberto Garcia     if (ret < 0) {
934db5794f1SAlberto Garcia         return ret;
935db5794f1SAlberto Garcia     }
936db5794f1SAlberto Garcia 
9379a476780SKevin Wolf     /* Remove it from the snapshot list */
9389a476780SKevin Wolf     memmove(s->snapshots + snapshot_index,
9399a476780SKevin Wolf             s->snapshots + snapshot_index + 1,
9409a476780SKevin Wolf             (s->nb_snapshots - snapshot_index - 1) * sizeof(sn));
941c142442bSKevin Wolf     s->nb_snapshots--;
9427c80ab3fSJes Sorensen     ret = qcow2_write_snapshots(bs);
943c142442bSKevin Wolf     if (ret < 0) {
94439a611a3SJeff Cody         error_setg_errno(errp, -ret,
94539a611a3SJeff Cody                          "Failed to remove snapshot from snapshot list");
946c142442bSKevin Wolf         return ret;
947c142442bSKevin Wolf     }
9489a476780SKevin Wolf 
9499a476780SKevin Wolf     /*
9509a476780SKevin Wolf      * The snapshot is now unused, clean up. If we fail after this point, we
9519a476780SKevin Wolf      * won't recover but just leak clusters.
9529a476780SKevin Wolf      */
953fcf9a6b7SMax Reitz     g_free(sn.unknown_extra_data);
9549a476780SKevin Wolf     g_free(sn.id_str);
9559a476780SKevin Wolf     g_free(sn.name);
9569a476780SKevin Wolf 
9579a476780SKevin Wolf     /*
9589a476780SKevin Wolf      * Now decrease the refcounts of clusters referenced by the snapshot and
9599a476780SKevin Wolf      * free the L1 table.
9609a476780SKevin Wolf      */
9619a476780SKevin Wolf     ret = qcow2_update_snapshot_refcount(bs, sn.l1_table_offset,
9629a476780SKevin Wolf                                          sn.l1_size, -1);
9639a476780SKevin Wolf     if (ret < 0) {
96439a611a3SJeff Cody         error_setg_errno(errp, -ret, "Failed to free the cluster and L1 table");
9659a476780SKevin Wolf         return ret;
9669a476780SKevin Wolf     }
96702b1ecfaSAlberto Garcia     qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * L1E_SIZE,
9686cfcb9b8SKevin Wolf                         QCOW2_DISCARD_SNAPSHOT);
9699a476780SKevin Wolf 
9709a476780SKevin Wolf     /* must update the copied flag on the current cluster offsets */
9719a476780SKevin Wolf     ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
9729a476780SKevin Wolf     if (ret < 0) {
97339a611a3SJeff Cody         error_setg_errno(errp, -ret,
97439a611a3SJeff Cody                          "Failed to update snapshot status in disk");
9759a476780SKevin Wolf         return ret;
9769a476780SKevin Wolf     }
9779a476780SKevin Wolf 
978c142442bSKevin Wolf #ifdef DEBUG_ALLOC
9796cbc3031SPhilipp Hahn     {
9806cbc3031SPhilipp Hahn         BdrvCheckResult result = {0};
981b35278f7SStefan Hajnoczi         qcow2_check_refcounts(bs, &result, 0);
9826cbc3031SPhilipp Hahn     }
983c142442bSKevin Wolf #endif
984c142442bSKevin Wolf     return 0;
985c142442bSKevin Wolf }
986c142442bSKevin Wolf 
qcow2_snapshot_list(BlockDriverState * bs,QEMUSnapshotInfo ** psn_tab)987ed6ccf0fSKevin Wolf int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
988c142442bSKevin Wolf {
989ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
990c142442bSKevin Wolf     QEMUSnapshotInfo *sn_tab, *sn_info;
991c142442bSKevin Wolf     QCowSnapshot *sn;
992c142442bSKevin Wolf     int i;
993c142442bSKevin Wolf 
994aa8b34c1SKevin Wolf     if (has_data_file(bs)) {
995aa8b34c1SKevin Wolf         return -ENOTSUP;
996aa8b34c1SKevin Wolf     }
997c142442bSKevin Wolf     if (!s->nb_snapshots) {
998c142442bSKevin Wolf         *psn_tab = NULL;
999c142442bSKevin Wolf         return s->nb_snapshots;
1000c142442bSKevin Wolf     }
1001c142442bSKevin Wolf 
10025839e53bSMarkus Armbruster     sn_tab = g_new0(QEMUSnapshotInfo, s->nb_snapshots);
1003c142442bSKevin Wolf     for(i = 0; i < s->nb_snapshots; i++) {
1004c142442bSKevin Wolf         sn_info = sn_tab + i;
1005c142442bSKevin Wolf         sn = s->snapshots + i;
1006c142442bSKevin Wolf         pstrcpy(sn_info->id_str, sizeof(sn_info->id_str),
1007c142442bSKevin Wolf                 sn->id_str);
1008c142442bSKevin Wolf         pstrcpy(sn_info->name, sizeof(sn_info->name),
1009c142442bSKevin Wolf                 sn->name);
1010c142442bSKevin Wolf         sn_info->vm_state_size = sn->vm_state_size;
1011c142442bSKevin Wolf         sn_info->date_sec = sn->date_sec;
1012c142442bSKevin Wolf         sn_info->date_nsec = sn->date_nsec;
1013c142442bSKevin Wolf         sn_info->vm_clock_nsec = sn->vm_clock_nsec;
1014b39847a5SPavel Dovgalyuk         sn_info->icount = sn->icount;
1015c142442bSKevin Wolf     }
1016c142442bSKevin Wolf     *psn_tab = sn_tab;
1017c142442bSKevin Wolf     return s->nb_snapshots;
1018c142442bSKevin Wolf }
1019c142442bSKevin Wolf 
qcow2_snapshot_load_tmp(BlockDriverState * bs,const char * snapshot_id,const char * name,Error ** errp)10207b4c4781SWenchao Xia int qcow2_snapshot_load_tmp(BlockDriverState *bs,
10217b4c4781SWenchao Xia                             const char *snapshot_id,
10227b4c4781SWenchao Xia                             const char *name,
10237b4c4781SWenchao Xia                             Error **errp)
102451ef6727Sedison {
1025e3f652b3SKevin Wolf     int i, snapshot_index;
1026ff99129aSKevin Wolf     BDRVQcow2State *s = bs->opaque;
102751ef6727Sedison     QCowSnapshot *sn;
1028e3f652b3SKevin Wolf     uint64_t *new_l1_table;
1029e3f652b3SKevin Wolf     int new_l1_bytes;
1030e3f652b3SKevin Wolf     int ret;
103151ef6727Sedison 
1032307261b2SVladimir Sementsov-Ogievskiy     assert(bdrv_is_read_only(bs));
1033e3f652b3SKevin Wolf 
1034e3f652b3SKevin Wolf     /* Search the snapshot */
10357b4c4781SWenchao Xia     snapshot_index = find_snapshot_by_id_and_name(bs, snapshot_id, name);
103651ef6727Sedison     if (snapshot_index < 0) {
10377b4c4781SWenchao Xia         error_setg(errp,
10387b4c4781SWenchao Xia                    "Can't find snapshot");
103951ef6727Sedison         return -ENOENT;
104051ef6727Sedison     }
104151ef6727Sedison     sn = &s->snapshots[snapshot_index];
1042e3f652b3SKevin Wolf 
1043e3f652b3SKevin Wolf     /* Allocate and read in the snapshot's L1 table */
1044314e8d39SAlberto Garcia     ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size,
104502b1ecfaSAlberto Garcia                                L1E_SIZE, QCOW_MAX_L1_SIZE,
1046314e8d39SAlberto Garcia                                "Snapshot L1 table", errp);
1047314e8d39SAlberto Garcia     if (ret < 0) {
1048314e8d39SAlberto Garcia         return ret;
10496a83f8b5SKevin Wolf     }
105002b1ecfaSAlberto Garcia     new_l1_bytes = sn->l1_size * L1E_SIZE;
1051ef97d608SAlberto Garcia     new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_bytes);
1052de82815dSKevin Wolf     if (new_l1_table == NULL) {
1053de82815dSKevin Wolf         return -ENOMEM;
1054de82815dSKevin Wolf     }
1055e3f652b3SKevin Wolf 
105632cc71deSAlberto Faria     ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_bytes,
105732cc71deSAlberto Faria                      new_l1_table, 0);
1058e3f652b3SKevin Wolf     if (ret < 0) {
10597b4c4781SWenchao Xia         error_setg(errp, "Failed to read l1 table for snapshot");
1060de82815dSKevin Wolf         qemu_vfree(new_l1_table);
1061e3f652b3SKevin Wolf         return ret;
1062e3f652b3SKevin Wolf     }
1063e3f652b3SKevin Wolf 
1064e3f652b3SKevin Wolf     /* Switch the L1 table */
1065de82815dSKevin Wolf     qemu_vfree(s->l1_table);
106651ef6727Sedison 
1067e3f652b3SKevin Wolf     s->l1_size = sn->l1_size;
106851ef6727Sedison     s->l1_table_offset = sn->l1_table_offset;
1069e3f652b3SKevin Wolf     s->l1_table = new_l1_table;
107051ef6727Sedison 
107151ef6727Sedison     for(i = 0;i < s->l1_size; i++) {
107251ef6727Sedison         be64_to_cpus(&s->l1_table[i]);
107351ef6727Sedison     }
1074e3f652b3SKevin Wolf 
107551ef6727Sedison     return 0;
107651ef6727Sedison }
1077