]> git.proxmox.com Git - mirror_qemu.git/blobdiff - block/qcow2-snapshot.c
block/export: Add blk_exp_close_all(_type)
[mirror_qemu.git] / block / qcow2-snapshot.c
index 5ab64da1ec36163ddfdca182bed17a40904f1aad..9b68690f5618659c1028208aa6771e1da0f091be 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "sysemu/block-backend.h"
 #include "qapi/error.h"
 #include "qcow2.h"
 #include "qemu/bswap.h"
@@ -658,7 +659,7 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     sn->extra_data_size = sizeof(QCowSnapshotExtraData);
 
     /* Allocate the L1 table of the snapshot and copy the current one there. */
-    l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
+    l1_table_offset = qcow2_alloc_clusters(bs, s->l1_size * L1E_SIZE);
     if (l1_table_offset < 0) {
         ret = l1_table_offset;
         goto fail;
@@ -678,13 +679,13 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
     }
 
     ret = qcow2_pre_write_overlap_check(bs, 0, sn->l1_table_offset,
-                                        s->l1_size * sizeof(uint64_t), false);
+                                        s->l1_size * L1E_SIZE, false);
     if (ret < 0) {
         goto fail;
     }
 
     ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table,
-                      s->l1_size * sizeof(uint64_t));
+                      s->l1_size * L1E_SIZE);
     if (ret < 0) {
         goto fail;
     }
@@ -767,7 +768,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     sn = &s->snapshots[snapshot_index];
 
     ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size,
-                               sizeof(uint64_t), QCOW_MAX_L1_SIZE,
+                               L1E_SIZE, QCOW_MAX_L1_SIZE,
                                "Snapshot L1 table", &local_err);
     if (ret < 0) {
         error_report_err(local_err);
@@ -775,10 +776,21 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
     }
 
     if (sn->disk_size != bs->total_sectors * BDRV_SECTOR_SIZE) {
-        error_report("qcow2: Loading snapshots with different disk "
-            "size is not implemented");
-        ret = -ENOTSUP;
-        goto fail;
+        BlockBackend *blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL,
+                                            &local_err);
+        if (!blk) {
+            error_report_err(local_err);
+            ret = -ENOTSUP;
+            goto fail;
+        }
+
+        ret = blk_truncate(blk, sn->disk_size, true, PREALLOC_MODE_OFF, 0,
+                           &local_err);
+        blk_unref(blk);
+        if (ret < 0) {
+            error_report_err(local_err);
+            goto fail;
+        }
     }
 
     /*
@@ -791,8 +803,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
         goto fail;
     }
 
-    cur_l1_bytes = s->l1_size * sizeof(uint64_t);
-    sn_l1_bytes = sn->l1_size * sizeof(uint64_t);
+    cur_l1_bytes = s->l1_size * L1E_SIZE;
+    sn_l1_bytes = sn->l1_size * L1E_SIZE;
 
     /*
      * Copy the snapshot L1 table to the current L1 table.
@@ -905,7 +917,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs,
     sn = s->snapshots[snapshot_index];
 
     ret = qcow2_validate_table(bs, sn.l1_table_offset, sn.l1_size,
-                               sizeof(uint64_t), QCOW_MAX_L1_SIZE,
+                               L1E_SIZE, QCOW_MAX_L1_SIZE,
                                "Snapshot L1 table", errp);
     if (ret < 0) {
         return ret;
@@ -941,7 +953,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs,
         error_setg_errno(errp, -ret, "Failed to free the cluster and L1 table");
         return ret;
     }
-    qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * sizeof(uint64_t),
+    qcow2_free_clusters(bs, sn.l1_table_offset, sn.l1_size * L1E_SIZE,
                         QCOW2_DISCARD_SNAPSHOT);
 
     /* must update the copied flag on the current cluster offsets */
@@ -1018,14 +1030,13 @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
 
     /* Allocate and read in the snapshot's L1 table */
     ret = qcow2_validate_table(bs, sn->l1_table_offset, sn->l1_size,
-                               sizeof(uint64_t), QCOW_MAX_L1_SIZE,
+                               L1E_SIZE, QCOW_MAX_L1_SIZE,
                                "Snapshot L1 table", errp);
     if (ret < 0) {
         return ret;
     }
-    new_l1_bytes = sn->l1_size * sizeof(uint64_t);
-    new_l1_table = qemu_try_blockalign(bs->file->bs,
-                                       ROUND_UP(new_l1_bytes, 512));
+    new_l1_bytes = sn->l1_size * L1E_SIZE;
+    new_l1_table = qemu_try_blockalign(bs->file->bs, new_l1_bytes);
     if (new_l1_table == NULL) {
         return -ENOMEM;
     }