74 lines
2.6 KiB
Diff
74 lines
2.6 KiB
Diff
|
From 16d78f7cd9e1455ebb0599706ba5badfa3ee4fdc Mon Sep 17 00:00:00 2001
|
||
|
From: Kevin Wolf <kwolf@redhat.com>
|
||
|
Date: Fri, 6 Sep 2013 12:32:26 +0200
|
||
|
Subject: [PATCH] qcow2: Discard VM state in active L1 after creating snapshot
|
||
|
|
||
|
During savevm, the VM state is written to the active L1 of the image and
|
||
|
then a snapshot is taken. After that, the VM state isn't needed any more
|
||
|
in the active L1 and should be discarded. This is implemented by this
|
||
|
patch.
|
||
|
|
||
|
The impact of not discarding the VM state is that a snapshot can never
|
||
|
become smaller than any previous snapshot (because it would be padded
|
||
|
with old VM state), and more importantly that future savevm operations
|
||
|
cause unnecessary COWs (with associated flushes), which makes subsequent
|
||
|
snapshots much slower.
|
||
|
|
||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||
|
---
|
||
|
block/qcow2-snapshot.c | 7 +++++++
|
||
|
block/qcow2.c | 5 -----
|
||
|
block/qcow2.h | 5 +++++
|
||
|
3 files changed, 12 insertions(+), 5 deletions(-)
|
||
|
|
||
|
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
|
||
|
index 0caac90..ae33b45 100644
|
||
|
--- a/block/qcow2-snapshot.c
|
||
|
+++ b/block/qcow2-snapshot.c
|
||
|
@@ -401,6 +401,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 16e45a0..f63c2cb 100644
|
||
|
--- a/block/qcow2.c
|
||
|
+++ b/block/qcow2.c
|
||
|
@@ -1666,11 +1666,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 52cf193..da61d18 100644
|
||
|
--- a/block/qcow2.h
|
||
|
+++ b/block/qcow2.h
|
||
|
@@ -324,6 +324,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) {
|