xref: /openbmc/qemu/block/qcow2-snapshot.c (revision 2038f8c8)
1 /*
2  * Block driver for the QCOW version 2 format
3  *
4  * Copyright (c) 2004-2006 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "qapi/error.h"
27 #include "qcow2.h"
28 #include "qemu/bswap.h"
29 #include "qemu/error-report.h"
30 #include "qemu/cutils.h"
31 
32 void qcow2_free_snapshots(BlockDriverState *bs)
33 {
34     BDRVQcow2State *s = bs->opaque;
35     int i;
36 
37     for(i = 0; i < s->nb_snapshots; i++) {
38         g_free(s->snapshots[i].name);
39         g_free(s->snapshots[i].id_str);
40     }
41     g_free(s->snapshots);
42     s->snapshots = NULL;
43     s->nb_snapshots = 0;
44 }
45 
46 int qcow2_read_snapshots(BlockDriverState *bs)
47 {
48     BDRVQcow2State *s = bs->opaque;
49     QCowSnapshotHeader h;
50     QCowSnapshotExtraData extra;
51     QCowSnapshot *sn;
52     int i, id_str_size, name_size;
53     int64_t offset;
54     uint32_t extra_data_size;
55     int ret;
56 
57     if (!s->nb_snapshots) {
58         s->snapshots = NULL;
59         s->snapshots_size = 0;
60         return 0;
61     }
62 
63     offset = s->snapshots_offset;
64     s->snapshots = g_new0(QCowSnapshot, s->nb_snapshots);
65 
66     for(i = 0; i < s->nb_snapshots; i++) {
67         /* Read statically sized part of the snapshot header */
68         offset = ROUND_UP(offset, 8);
69         ret = bdrv_pread(bs->file, offset, &h, sizeof(h));
70         if (ret < 0) {
71             goto fail;
72         }
73 
74         offset += sizeof(h);
75         sn = s->snapshots + i;
76         sn->l1_table_offset = be64_to_cpu(h.l1_table_offset);
77         sn->l1_size = be32_to_cpu(h.l1_size);
78         sn->vm_state_size = be32_to_cpu(h.vm_state_size);
79         sn->date_sec = be32_to_cpu(h.date_sec);
80         sn->date_nsec = be32_to_cpu(h.date_nsec);
81         sn->vm_clock_nsec = be64_to_cpu(h.vm_clock_nsec);
82         extra_data_size = be32_to_cpu(h.extra_data_size);
83 
84         id_str_size = be16_to_cpu(h.id_str_size);
85         name_size = be16_to_cpu(h.name_size);
86 
87         /* Read extra data */
88         ret = bdrv_pread(bs->file, offset, &extra,
89                          MIN(sizeof(extra), extra_data_size));
90         if (ret < 0) {
91             goto fail;
92         }
93         offset += extra_data_size;
94 
95         if (extra_data_size >= 8) {
96             sn->vm_state_size = be64_to_cpu(extra.vm_state_size_large);
97         }
98 
99         if (extra_data_size >= 16) {
100             sn->disk_size = be64_to_cpu(extra.disk_size);
101         } else {
102             sn->disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
103         }
104 
105         /* Read snapshot ID */
106         sn->id_str = g_malloc(id_str_size + 1);
107         ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size);
108         if (ret < 0) {
109             goto fail;
110         }
111         offset += id_str_size;
112         sn->id_str[id_str_size] = '\0';
113 
114         /* Read snapshot name */
115         sn->name = g_malloc(name_size + 1);
116         ret = bdrv_pread(bs->file, offset, sn->name, name_size);
117         if (ret < 0) {
118             goto fail;
119         }
120         offset += name_size;
121         sn->name[name_size] = '\0';
122 
123         if (offset - s->snapshots_offset > QCOW_MAX_SNAPSHOTS_SIZE) {
124             ret = -EFBIG;
125             goto fail;
126         }
127     }
128 
129     assert(offset - s->snapshots_offset <= INT_MAX);
130     s->snapshots_size = offset - s->snapshots_offset;
131     return 0;
132 
133 fail:
134     qcow2_free_snapshots(bs);
135     return ret;
136 }
137 
138 /* add at the end of the file a new list of snapshots */
139 static int qcow2_write_snapshots(BlockDriverState *bs)
140 {
141     BDRVQcow2State *s = bs->opaque;
142     QCowSnapshot *sn;
143     QCowSnapshotHeader h;
144     QCowSnapshotExtraData extra;
145     int i, name_size, id_str_size, snapshots_size;
146     struct {
147         uint32_t nb_snapshots;
148         uint64_t snapshots_offset;
149     } QEMU_PACKED header_data;
150     int64_t offset, snapshots_offset = 0;
151     int ret;
152 
153     /* compute the size of the snapshots */
154     offset = 0;
155     for(i = 0; i < s->nb_snapshots; i++) {
156         sn = s->snapshots + i;
157         offset = ROUND_UP(offset, 8);
158         offset += sizeof(h);
159         offset += sizeof(extra);
160         offset += strlen(sn->id_str);
161         offset += strlen(sn->name);
162 
163         if (offset > QCOW_MAX_SNAPSHOTS_SIZE) {
164             ret = -EFBIG;
165             goto fail;
166         }
167     }
168 
169     assert(offset <= INT_MAX);
170     snapshots_size = offset;
171 
172     /* Allocate space for the new snapshot list */
173     snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);
174     offset = snapshots_offset;
175     if (offset < 0) {
176         ret = offset;
177         goto fail;
178     }
179     ret = bdrv_flush(bs);
180     if (ret < 0) {
181         goto fail;
182     }
183 
184     /* The snapshot list position has not yet been updated, so these clusters
185      * must indeed be completely free */
186     ret = qcow2_pre_write_overlap_check(bs, 0, offset, snapshots_size, false);
187     if (ret < 0) {
188         goto fail;
189     }
190 
191 
192     /* Write all snapshots to the new list */
193     for(i = 0; i < s->nb_snapshots; i++) {
194         sn = s->snapshots + i;
195         memset(&h, 0, sizeof(h));
196         h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);
197         h.l1_size = cpu_to_be32(sn->l1_size);
198         /* If it doesn't fit in 32 bit, older implementations should treat it
199          * as a disk-only snapshot rather than truncate the VM state */
200         if (sn->vm_state_size <= 0xffffffff) {
201             h.vm_state_size = cpu_to_be32(sn->vm_state_size);
202         }
203         h.date_sec = cpu_to_be32(sn->date_sec);
204         h.date_nsec = cpu_to_be32(sn->date_nsec);
205         h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);
206         h.extra_data_size = cpu_to_be32(sizeof(extra));
207 
208         memset(&extra, 0, sizeof(extra));
209         extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size);
210         extra.disk_size = cpu_to_be64(sn->disk_size);
211 
212         id_str_size = strlen(sn->id_str);
213         name_size = strlen(sn->name);
214         assert(id_str_size <= UINT16_MAX && name_size <= UINT16_MAX);
215         h.id_str_size = cpu_to_be16(id_str_size);
216         h.name_size = cpu_to_be16(name_size);
217         offset = ROUND_UP(offset, 8);
218 
219         ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h));
220         if (ret < 0) {
221             goto fail;
222         }
223         offset += sizeof(h);
224 
225         ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra));
226         if (ret < 0) {
227             goto fail;
228         }
229         offset += sizeof(extra);
230 
231         ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size);
232         if (ret < 0) {
233             goto fail;
234         }
235         offset += id_str_size;
236 
237         ret = bdrv_pwrite(bs->file, offset, sn->name, name_size);
238         if (ret < 0) {
239             goto fail;
240         }
241         offset += name_size;
242     }
243 
244     /*
245      * Update the header to point to the new snapshot table. This requires the
246      * new table and its refcounts to be stable on disk.
247      */
248     ret = bdrv_flush(bs);
249     if (ret < 0) {
250         goto fail;
251     }
252 
253     QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=
254         offsetof(QCowHeader, nb_snapshots) + sizeof(header_data.nb_snapshots));
255 
256     header_data.nb_snapshots        = cpu_to_be32(s->nb_snapshots);
257     header_data.snapshots_offset    = cpu_to_be64(snapshots_offset);
258 
259     ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
260                            &header_data, sizeof(header_data));
261     if (ret < 0) {
262         goto fail;
263     }
264 
265     /* free the old snapshot table */
266     qcow2_free_clusters(bs, s->snapshots_offset, s->snapshots_size,
267                         QCOW2_DISCARD_SNAPSHOT);
268     s->snapshots_offset = snapshots_offset;
269     s->snapshots_size = snapshots_size;
270     return 0;
271 
272 fail:
273     if (snapshots_offset > 0) {
274         qcow2_free_clusters(bs, snapshots_offset, snapshots_size,
275                             QCOW2_DISCARD_ALWAYS);
276     }
277     return ret;
278 }
279 
280 static void find_new_snapshot_id(BlockDriverState *bs,
281                                  char *id_str, int id_str_size)
282 {
283     BDRVQcow2State *s = bs->opaque;
284     QCowSnapshot *sn;
285     int i;
286     unsigned long id, id_max = 0;
287 
288     for(i = 0; i < s->nb_snapshots; i++) {
289         sn = s->snapshots + i;
290         id = strtoul(sn->id_str, NULL, 10);
291         if (id > id_max)
292             id_max = id;
293     }
294     snprintf(id_str, id_str_size, "%lu", id_max + 1);
295 }
296 
297 static int find_snapshot_by_id_and_name(BlockDriverState *bs,
298                                         const char *id,
299                                         const char *name)
300 {
301     BDRVQcow2State *s = bs->opaque;
302     int i;
303 
304     if (id && name) {
305         for (i = 0; i < s->nb_snapshots; i++) {
306             if (!strcmp(s->snapshots[i].id_str, id) &&
307                 !strcmp(s->snapshots[i].name, name)) {
308                 return i;
309             }
310         }
311     } else if (id) {
312         for (i = 0; i < s->nb_snapshots; i++) {
313             if (!strcmp(s->snapshots[i].id_str, id)) {
314                 return i;
315             }
316         }
317     } else if (name) {
318         for (i = 0; i < s->nb_snapshots; i++) {
319             if (!strcmp(s->snapshots[i].name, name)) {
320                 return i;
321             }
322         }
323     }
324 
325     return -1;
326 }
327 
328 static int find_snapshot_by_id_or_name(BlockDriverState *bs,
329                                        const char *id_or_name)
330 {
331     int ret;
332 
333     ret = find_snapshot_by_id_and_name(bs, id_or_name, NULL);
334     if (ret >= 0) {
335         return ret;
336     }
337     return find_snapshot_by_id_and_name(bs, NULL, id_or_name);
338 }
339 
340 /* if no id is provided, a new one is constructed */
341 int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
342 {
343     BDRVQcow2State *s = bs->opaque;
344     QCowSnapshot *new_snapshot_list = NULL;
345     QCowSnapshot *old_snapshot_list = NULL;
346     QCowSnapshot sn1, *sn = &sn1;
347     int i, ret;
348     uint64_t *l1_table = NULL;
349     int64_t l1_table_offset;
350 
351     if (s->nb_snapshots >= QCOW_MAX_SNAPSHOTS) {
352         return -EFBIG;
353     }
354 
355     if (has_data_file(bs)) {
356         return -ENOTSUP;
357     }
358 
359     memset(sn, 0, sizeof(*sn));
360 
361     /* Generate an ID */
362     find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
363 
364     /* Populate sn with passed data */
365     sn->id_str = g_strdup(sn_info->id_str);
366     sn->name = g_strdup(sn_info->name);
367 
368     sn->disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
369     sn->vm_state_size = sn_info->vm_state_size;
370     sn->date_sec = sn_info->date_sec;
371     sn->date_nsec = sn_info->date_nsec;
372     sn->vm_clock_nsec = sn_info->vm_clock_nsec;
373 
374     /* Allocate the L1 table of the snapshot and copy the current one there. */
375     l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
376     if (l1_table_offset < 0) {
377         ret = l1_table_offset;
378         goto fail;
379     }
380 
381     sn->l1_table_offset = l1_table_offset;
382     sn->l1_size = s->l1_size;
383 
384     l1_table = g_try_new(uint64_t, s->l1_size);
385     if (s->l1_size && l1_table == NULL) {
386         ret = -ENOMEM;
387         goto fail;
388     }
389 
390     for(i = 0; i < s->l1_size; i++) {
391         l1_table[i] = cpu_to_be64(s->l1_table[i]);
392     }
393 
394     ret = qcow2_pre_write_overlap_check(bs, 0, sn->l1_table_offset,
395                                         s->l1_size * sizeof(uint64_t), false);
396     if (ret < 0) {
397         goto fail;
398     }
399 
400     ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table,
401                       s->l1_size * sizeof(uint64_t));
402     if (ret < 0) {
403         goto fail;
404     }
405 
406     g_free(l1_table);
407     l1_table = NULL;
408 
409     /*
410      * Increase the refcounts of all clusters and make sure everything is
411      * stable on disk before updating the snapshot table to contain a pointer
412      * to the new L1 table.
413      */
414     ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1);
415     if (ret < 0) {
416         goto fail;
417     }
418 
419     /* Append the new snapshot to the snapshot list */
420     new_snapshot_list = g_new(QCowSnapshot, s->nb_snapshots + 1);
421     if (s->snapshots) {
422         memcpy(new_snapshot_list, s->snapshots,
423                s->nb_snapshots * sizeof(QCowSnapshot));
424         old_snapshot_list = s->snapshots;
425     }
426     s->snapshots = new_snapshot_list;
427     s->snapshots[s->nb_snapshots++] = *sn;
428 
429     ret = qcow2_write_snapshots(bs);
430     if (ret < 0) {
431         g_free(s->snapshots);
432         s->snapshots = old_snapshot_list;
433         s->nb_snapshots--;
434         goto fail;
435     }
436 
437     g_free(old_snapshot_list);
438 
439     /* The VM state isn't needed any more in the active L1 table; in fact, it
440      * hurts by causing expensive COW for the next snapshot. */
441     qcow2_cluster_discard(bs, qcow2_vm_state_offset(s),
442                           ROUND_UP(sn->vm_state_size, s->cluster_size),
443                           QCOW2_DISCARD_NEVER, false);
444 
445 #ifdef DEBUG_ALLOC
446     {
447       BdrvCheckResult result = {0};
448       qcow2_check_refcounts(bs, &result, 0);
449     }
450 #endif
451     return 0;
452 
453 fail:
454     g_free(sn->id_str);
455     g_free(sn->name);
456     g_free(l1_table);
457 
458     return ret;
459 }
460 
461 /* copy the snapshot 'snapshot_name' into the current disk image */
462 int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
463 {
464     BDRVQcow2State *s = bs->opaque;
465     QCowSnapshot *sn;
466     Error *local_err = NULL;
467     int i, snapshot_index;
468     int cur_l1_bytes, sn_l1_bytes;
469     int ret;
470     uint64_t *sn_l1_table = NULL;
471 
472     if (has_data_file(bs)) {
473         return -ENOTSUP;
474     }
475 
476     /* Search the snapshot */
477     snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
478     if (snapshot_index < 0) {
479         return -ENOENT;
480     }
481     sn = &s->snapshots[snapshot_index];
482 
483     ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size,
484                                sizeof(uint64_t), QCOW_MAX_L1_SIZE,
485                                "Snapshot L1 table", &local_err);
486     if (ret < 0) {
487         error_report_err(local_err);
488         goto fail;
489     }
490 
491     if (sn->disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) {
492         error_report("qcow2: Loading snapshots with different disk "
493             "size is not implemented");
494         ret = -ENOTSUP;
495         goto fail;
496     }
497 
498     /*
499      * Make sure that the current L1 table is big enough to contain the whole
500      * L1 table of the snapshot. If the snapshot L1 table is smaller, the
501      * current one must be padded with zeros.
502      */
503     ret = qcow2_grow_l1_table(bs, sn->l1_size, true);
504     if (ret < 0) {
505         goto fail;
506     }
507 
508     cur_l1_bytes = s->l1_size * sizeof(uint64_t);
509     sn_l1_bytes = sn->l1_size * sizeof(uint64_t);
510 
511     /*
512      * Copy the snapshot L1 table to the current L1 table.
513      *
514      * Before overwriting the old current L1 table on disk, make sure to
515      * increase all refcounts for the clusters referenced by the new one.
516      * Decrease the refcount referenced by the old one only when the L1
517      * table is overwritten.
518      */
519     sn_l1_table = g_try_malloc0(cur_l1_bytes);
520     if (cur_l1_bytes && sn_l1_table == NULL) {
521         ret = -ENOMEM;
522         goto fail;
523     }
524 
525     ret = bdrv_pread(bs->file, sn->l1_table_offset,
526                      sn_l1_table, sn_l1_bytes);
527     if (ret < 0) {
528         goto fail;
529     }
530 
531     ret = qcow2_update_snapshot_refcount(bs, sn->l1_table_offset,
532                                          sn->l1_size, 1);
533     if (ret < 0) {
534         goto fail;
535     }
536 
537     ret = qcow2_pre_write_overlap_check(bs, QCOW2_OL_ACTIVE_L1,
538                                         s->l1_table_offset, cur_l1_bytes,
539                                         false);
540     if (ret < 0) {
541         goto fail;
542     }
543 
544     ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, sn_l1_table,
545                            cur_l1_bytes);
546     if (ret < 0) {
547         goto fail;
548     }
549 
550     /*
551      * Decrease refcount of clusters of current L1 table.
552      *
553      * At this point, the in-memory s->l1_table points to the old L1 table,
554      * whereas on disk we already have the new one.
555      *
556      * qcow2_update_snapshot_refcount special cases the current L1 table to use
557      * the in-memory data instead of really using the offset to load a new one,
558      * which is why this works.
559      */
560     ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset,
561                                          s->l1_size, -1);
562 
563     /*
564      * Now update the in-memory L1 table to be in sync with the on-disk one. We
565      * need to do this even if updating refcounts failed.
566      */
567     for(i = 0;i < s->l1_size; i++) {
568         s->l1_table[i] = be64_to_cpu(sn_l1_table[i]);
569     }
570 
571     if (ret < 0) {
572         goto fail;
573     }
574 
575     g_free(sn_l1_table);
576     sn_l1_table = NULL;
577 
578     /*
579      * Update QCOW_OFLAG_COPIED in the active L1 table (it may have changed
580      * when we decreased the refcount of the old snapshot.
581      */
582     ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
583     if (ret < 0) {
584         goto fail;
585     }
586 
587 #ifdef DEBUG_ALLOC
588     {
589         BdrvCheckResult result = {0};
590         qcow2_check_refcounts(bs, &result, 0);
591     }
592 #endif
593     return 0;
594 
595 fail:
596     g_free(sn_l1_table);
597     return ret;
598 }
599 
600 int qcow2_snapshot_delete(BlockDriverState *bs,
601                           const char *snapshot_id,
602                           const char *name,
603                           Error **errp)
604 {
605     BDRVQcow2State *s = bs->opaque;
606     QCowSnapshot sn;
607     int snapshot_index, ret;
608 
609     if (has_data_file(bs)) {
610         return -ENOTSUP;
611     }
612 
613     /* Search the snapshot */
614     snapshot_index = find_snapshot_by_id_and_name(bs, snapshot_id, name);
615     if (snapshot_index < 0) {
616         error_setg(errp, "Can't find the snapshot");
617         return -ENOENT;
618     }
619     sn = s->snapshots[snapshot_index];
620 
621     ret = qcow2_validate_table(bs, sn.l1_table_offset, sn.l1_size,
622                                sizeof(uint64_t), QCOW_MAX_L1_SIZE,
623                                "Snapshot L1 table", errp);
624     if (ret < 0) {
625         return ret;
626     }
627 
628     /* Remove it from the snapshot list */
629     memmove(s->snapshots + snapshot_index,
630             s->snapshots + snapshot_index + 1,
631             (s->nb_snapshots - snapshot_index - 1) * sizeof(sn));
632     s->nb_snapshots--;
633     ret = qcow2_write_snapshots(bs);
634     if (ret < 0) {
635         error_setg_errno(errp, -ret,
636                          "Failed to remove snapshot from snapshot list");
637         return ret;
638     }
639 
640     /*
641      * The snapshot is now unused, clean up. If we fail after this point, we
642      * won't recover but just leak clusters.
643      */
644     g_free(sn.id_str);
645     g_free(sn.name);
646 
647     /*
648      * Now decrease the refcounts of clusters referenced by the snapshot and
649      * free the L1 table.
650      */
651     ret = qcow2_update_snapshot_refcount(bs, sn.l1_table_offset,
652                                          sn.l1_size, -1);
653     if (ret < 0) {
654         error_setg_errno(errp, -ret, "Failed to free the cluster and L1 table");
655         return ret;
656     }
657     qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t),
658                         QCOW2_DISCARD_SNAPSHOT);
659 
660     /* must update the copied flag on the current cluster offsets */
661     ret = qcow2_update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
662     if (ret < 0) {
663         error_setg_errno(errp, -ret,
664                          "Failed to update snapshot status in disk");
665         return ret;
666     }
667 
668 #ifdef DEBUG_ALLOC
669     {
670         BdrvCheckResult result = {0};
671         qcow2_check_refcounts(bs, &result, 0);
672     }
673 #endif
674     return 0;
675 }
676 
677 int qcow2_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
678 {
679     BDRVQcow2State *s = bs->opaque;
680     QEMUSnapshotInfo *sn_tab, *sn_info;
681     QCowSnapshot *sn;
682     int i;
683 
684     if (has_data_file(bs)) {
685         return -ENOTSUP;
686     }
687     if (!s->nb_snapshots) {
688         *psn_tab = NULL;
689         return s->nb_snapshots;
690     }
691 
692     sn_tab = g_new0(QEMUSnapshotInfo, s->nb_snapshots);
693     for(i = 0; i < s->nb_snapshots; i++) {
694         sn_info = sn_tab + i;
695         sn = s->snapshots + i;
696         pstrcpy(sn_info->id_str, sizeof(sn_info->id_str),
697                 sn->id_str);
698         pstrcpy(sn_info->name, sizeof(sn_info->name),
699                 sn->name);
700         sn_info->vm_state_size = sn->vm_state_size;
701         sn_info->date_sec = sn->date_sec;
702         sn_info->date_nsec = sn->date_nsec;
703         sn_info->vm_clock_nsec = sn->vm_clock_nsec;
704     }
705     *psn_tab = sn_tab;
706     return s->nb_snapshots;
707 }
708 
709 int qcow2_snapshot_load_tmp(BlockDriverState *bs,
710                             const char *snapshot_id,
711                             const char *name,
712                             Error **errp)
713 {
714     int i, snapshot_index;
715     BDRVQcow2State *s = bs->opaque;
716     QCowSnapshot *sn;
717     uint64_t *new_l1_table;
718     int new_l1_bytes;
719     int ret;
720 
721     assert(bs->read_only);
722 
723     /* Search the snapshot */
724     snapshot_index = find_snapshot_by_id_and_name(bs, snapshot_id, name);
725     if (snapshot_index < 0) {
726         error_setg(errp,
727                    "Can't find snapshot");
728         return -ENOENT;
729     }
730     sn = &s->snapshots[snapshot_index];
731 
732     /* Allocate and read in the snapshot's L1 table */
733     ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size,
734                                sizeof(uint64_t), QCOW_MAX_L1_SIZE,
735                                "Snapshot L1 table", errp);
736     if (ret < 0) {
737         return ret;
738     }
739     new_l1_bytes = sn->l1_size * sizeof(uint64_t);
740     new_l1_table = qemu_try_blockalign(bs->file->bs,
741                                        ROUND_UP(new_l1_bytes, 512));
742     if (new_l1_table == NULL) {
743         return -ENOMEM;
744     }
745 
746     ret = bdrv_pread(bs->file, sn->l1_table_offset,
747                      new_l1_table, new_l1_bytes);
748     if (ret < 0) {
749         error_setg(errp, "Failed to read l1 table for snapshot");
750         qemu_vfree(new_l1_table);
751         return ret;
752     }
753 
754     /* Switch the L1 table */
755     qemu_vfree(s->l1_table);
756 
757     s->l1_size = sn->l1_size;
758     s->l1_table_offset = sn->l1_table_offset;
759     s->l1_table = new_l1_table;
760 
761     for(i = 0;i < s->l1_size; i++) {
762         be64_to_cpus(&s->l1_table[i]);
763     }
764 
765     return 0;
766 }
767