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