summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/qcow2-snapshot.c7
-rw-r--r--block/qcow2.c5
-rw-r--r--block/qcow2.h5
3 files changed, 12 insertions, 5 deletions
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index e7e601301a..ffead08ca2 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -416,6 +416,13 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
g_free(old_snapshot_list);
+ /* The VM state isn't needed any more in the active L1 table; in fact, it
+ * hurts by causing expensive COW for the next snapshot. */
+ qcow2_discard_clusters(bs, qcow2_vm_state_offset(s),
+ align_offset(sn->vm_state_size, s->cluster_size)
+ >> BDRV_SECTOR_BITS,
+ QCOW2_DISCARD_NEVER);
+
#ifdef DEBUG_ALLOC
{
BdrvCheckResult result = {0};
diff --git a/block/qcow2.c b/block/qcow2.c
index 147822e8fd..c9e266e22e 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1757,11 +1757,6 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
return 0;
}
-static int64_t qcow2_vm_state_offset(BDRVQcowState *s)
-{
- return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
-}
-
static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVQcowState *s = bs->opaque;
diff --git a/block/qcow2.h b/block/qcow2.h
index 9c33b98457..49eed828c5 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -361,6 +361,11 @@ static inline int64_t align_offset(int64_t offset, int n)
return offset;
}
+static inline int64_t qcow2_vm_state_offset(BDRVQcowState *s)
+{
+ return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
+}
+
static inline int qcow2_get_cluster_type(uint64_t l2_entry)
{
if (l2_entry & QCOW_OFLAG_COMPRESSED) {