Skip to contentSkip to conversation

fix migration of zero pages

PATCH In review Peter Lieven 4 participants 12 messages Jun 10, 2013 – Jun 13, 2013

lore
Share & tools
lore
#0 lore raw

v2 cover fix migration of zero pages

There have been reports that migration is broken on pseries by Alexey Kardashevskiy. It turned out that migration will fail in general as soon as a page is zero on the source, but not on the destination. I thus reverted the skipping of zero pages in bulk transfer phase and added a patch that does not (over)write zero pages at the destination.

v2:
- keep skipped pages fields in monitoring and qmp intact to avoid compatiblity issues.

Peter Lieven (2):
Revert "migration: do not sent zero pages in bulk stage"
migration: do not overwrite zero pages

 arch_init.c |   27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH v2 1/2 Revert "migration: do not sent zero pages in bulk stage"

Not sending zero pages breaks migration if a page is zero at the source but not at the destination. This can e.g. happen if different BIOS versions are used at source and destination. It has also been reported that migration on pseries is completely broken with this patch.

This effectively reverts commit f1c72795af573b24a7da5eb52375c9aba8a37972.

Conflicts:

arch_init.c

---
 arch_init.c |   13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)
arch_init.c +4 -9
index 5d32ecf..08fccf6 100644
@@ -457,15 +457,10 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             bytes_sent = -1;
             if (is_zero_page(p)) {
                 acct_info.dup_pages++;
-                if (!ram_bulk_stage) {
-                    bytes_sent = save_block_hdr(f, block, offset, cont,
-                                                RAM_SAVE_FLAG_COMPRESS);
-                    qemu_put_byte(f, 0);
-                    bytes_sent++;
-                } else {
-                    acct_info.skipped_pages++;
-                    bytes_sent = 0;
-                }
+                bytes_sent = save_block_hdr(f, block, offset, cont,
+                                            RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_byte(f, 0);
+                bytes_sent++;
             } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
Signature · 1 line
1.7.9.5
Reviewed-by on v2 1/2
#2 lore raw

Re: [Qemu-devel] [PATCHv2 1/2] Revert "migration: do not sent zero pages in bulk stage"

Quoted 6 lines · Peter Lieven

Not sending zero pages breaks migration if a page is zero at the source but not at the destination. This can e.g. happen if different BIOS versions are used at source and destination. It has also been reported that migration on pseries is completely broken with this patch.

Quoted 7 lines

This effectively reverts commit f1c72795af573b24a7da5eb52375c9aba8a37972.

Conflicts:

arch_init.c

Also CC'ing qemu-stable

Quoted 32 lines
---
 arch_init.c |   13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)
arch_init.c +4 -9
index 5d32ecf..08fccf6 100644
@@ -457,15 +457,10 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             bytes_sent = -1;
             if (is_zero_page(p)) {
                 acct_info.dup_pages++;
-                if (!ram_bulk_stage) {
-                    bytes_sent = save_block_hdr(f, block, offset, cont,
-                                                RAM_SAVE_FLAG_COMPRESS);
-                    qemu_put_byte(f, 0);
-                    bytes_sent++;
-                } else {
-                    acct_info.skipped_pages++;
-                    bytes_sent = 0;
-                }
+                bytes_sent = save_block_hdr(f, block, offset, cont,
+                                            RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_byte(f, 0);
+                bytes_sent++;
             } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
Signature · 1 line
1.7.9.5
Reviewed-by on v2 1/2
#3 lore raw

Re: [Qemu-devel] [PATCHv2 1/2] Revert "migration: do not sent zero pages in bulk stage"

In reply to Peter Lieven
Quoted 32 lines · Peter Lieven

Not sending zero pages breaks migration if a page is zero at the source but not at the destination. This can e.g. happen if different BIOS versions are used at source and destination. It has also been reported that migration on pseries is completely broken with this patch.

This effectively reverts commit f1c72795af573b24a7da5eb52375c9aba8a37972.

Conflicts:

arch_init.c

---
 arch_init.c |   13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)
arch_init.c +0 -6
index 5d32ecf..08fccf6 100644
@@ -457,15 +457,10 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
             bytes_sent = -1;
             if (is_zero_page(p)) {
                 acct_info.dup_pages++;
-                if (!ram_bulk_stage) {
-                    bytes_sent = save_block_hdr(f, block, offset, cont,
-                                                RAM_SAVE_FLAG_COMPRESS);
-                    qemu_put_byte(f, 0);
-                    bytes_sent++;
-                } else {

arch_init.c static int ram_save_block(QEMUFile *f, bool last_stage) · line 466

Quoted 10 lines
arch_init.c +4 -3
-                    acct_info.skipped_pages++;
-                    bytes_sent = 0;
-                }
+                bytes_sent = save_block_hdr(f, block, offset, cont,
+                                            RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_byte(f, 0);
+                bytes_sent++;
             } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
                 current_addr = block->offset + offset;
                 bytes_sent = save_xbzrle_page(f, p, current_addr, block,
Reviewed-by on v2 1/2
#4 lore raw

Re: [Qemu-devel] [PATCHv2 1/2] Revert "migration: do not sent zero pages in bulk stage"

In reply to Peter Lieven

clear patch, I don't see any issue.

Quoted 42 lines

Not sending zero pages breaks migration if a page is zero at the source but not at the destination. This can e.g. happen if different BIOS versions are used at source and destination. It has also been reported that migration on pseries is completely broken with this patch.

This effectively reverts commit f1c72795af573b24a7da5eb52375c9aba8a37972.

Conflicts:

arch_init.c

---
  arch_init.c |   13 ++++---------
  1 file changed, 4 insertions(+), 9 deletions(-)
arch_init.c +4 -9
index 5d32ecf..08fccf6 100644
@@ -457,15 +457,10 @@ static int ram_save_block(QEMUFile *f, bool last_stage)
              bytes_sent = -1;
              if (is_zero_page(p)) {
                  acct_info.dup_pages++;
-                if (!ram_bulk_stage) {
-                    bytes_sent = save_block_hdr(f, block, offset, cont,
-                                                RAM_SAVE_FLAG_COMPRESS);
-                    qemu_put_byte(f, 0);
-                    bytes_sent++;
-                } else {
-                    acct_info.skipped_pages++;
-                    bytes_sent = 0;
-                }
+                bytes_sent = save_block_hdr(f, block, offset, cont,
+                                            RAM_SAVE_FLAG_COMPRESS);
+                qemu_put_byte(f, 0);
+                bytes_sent++;
              } else if (!ram_bulk_stage && migrate_use_xbzrle()) {
                  current_addr = block->offset + offset;
                  bytes_sent = save_xbzrle_page(f, p, current_addr, block,
Signature · 3 lines
Best Regards

Wenchao Xia
#5 lore raw

PATCH v2 2/2 migration: do not overwrite zero pages

In reply to Peter Lieven

on incoming migration do not memset pages to zero if they already read as zero. this will allocate a new zero page and consume memory unnecessarily. even if we madvise a MADV_DONTNEED later this will only deallocate the memory asynchronously.

---
 arch_init.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)
arch_init.c +8 -6
index 08fccf6..cf4e1d5 100644
@@ -832,14 +832,16 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
             }
 
             ch = qemu_get_byte(f);
-            memset(host, ch, TARGET_PAGE_SIZE);
+            if (ch != 0 || !is_zero_page(host)) {
+                memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32
-            if (ch == 0 &&
-                (!kvm_enabled() || kvm_has_sync_mmu()) &&
-                getpagesize() <= TARGET_PAGE_SIZE) {
-                qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
-            }
+                if (ch == 0 &&
+                    (!kvm_enabled() || kvm_has_sync_mmu()) &&
+                    getpagesize() <= TARGET_PAGE_SIZE) {
+                    qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
+                }
 #endif
+            }
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
             void *host;
 
Signature · 1 line
1.7.9.5
Reviewed-by on v2 2/2
#6 lore raw

Re: [Qemu-devel] [PATCHv2 2/2] migration: do not overwrite zero pages

Quoted 22 lines · Peter Lieven

on incoming migration do not memset pages to zero if they already read as zero. this will allocate a new zero page and consume memory unnecessarily. even if we madvise a MADV_DONTNEED later this will only deallocate the memory asynchronously.

---
 arch_init.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)
arch_init.c +2 -1
index 08fccf6..cf4e1d5 100644
@@ -832,14 +832,16 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
             }
 
             ch = qemu_get_byte(f);
-            memset(host, ch, TARGET_PAGE_SIZE);
+            if (ch != 0 || !is_zero_page(host)) {
+                memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32

arch_init.c static int ram_load(QEMUFile *f, void *opaque, int version_id) · line 842

Quoted 10 lines
arch_init.c +5 -5
-            if (ch == 0 &&
-                (!kvm_enabled() || kvm_has_sync_mmu()) &&
-                getpagesize() <= TARGET_PAGE_SIZE) {
-                qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
-            }
+                if (ch == 0 &&
+                    (!kvm_enabled() || kvm_has_sync_mmu()) &&
+                    getpagesize() <= TARGET_PAGE_SIZE) {
+                    qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
+                }

Also CC'ing qemu-stable, but from what I gather this just mitigates the performance impact of 1/2 and isn't strictly necessary to fix migration? i.e. we can still do outgoing migration to 1.5.0 guests?

Quoted 9 lines
arch_init.c +1 -0
 #endif
+            }
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
             void *host;
 
Signature · 1 line
1.7.9.5
#7 lore raw

Re: [Qemu-devel] [PATCHv2 2/2] migration: do not overwrite zero pages

Quoted 36 lines · mdroth
Quoted 22 lines · Peter Lieven

on incoming migration do not memset pages to zero if they already read as zero. this will allocate a new zero page and consume memory unnecessarily. even if we madvise a MADV_DONTNEED later this will only deallocate the memory asynchronously.

---
 arch_init.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)
arch_init.c +2 -1
index 08fccf6..cf4e1d5 100644
@@ -832,14 +832,16 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
             }
 
             ch = qemu_get_byte(f);
-            memset(host, ch, TARGET_PAGE_SIZE);
+            if (ch != 0 || !is_zero_page(host)) {
+                memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32

arch_init.c static int ram_load(QEMUFile *f, void *opaque, int version_id) · line 842

Quoted 10 lines
arch_init.c +5 -5
-            if (ch == 0 &&
-                (!kvm_enabled() || kvm_has_sync_mmu()) &&
-                getpagesize() <= TARGET_PAGE_SIZE) {
-                qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
-            }
+                if (ch == 0 &&
+                    (!kvm_enabled() || kvm_has_sync_mmu()) &&
+                    getpagesize() <= TARGET_PAGE_SIZE) {
+                    qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
+                }
Quoted 1 line

Also CC'ing qemu-stable, but from what I gather this just mitigates the

*actually* CC'ing qemu-stable this time :)

#8 lore raw

Re: [Qemu-devel] [PATCHv2 2/2] migration: do not overwrite zero pages

In reply to mdroth

Am 10.06.2013 um 18:10 schrieb mdroth <[email protected]>:

Quoted 36 lines · Peter Lieven
Quoted 22 lines

on incoming migration do not memset pages to zero if they already read as zero. this will allocate a new zero page and consume memory unnecessarily. even if we madvise a MADV_DONTNEED later this will only deallocate the memory asynchronously.

---
arch_init.c | 14 ++++++++------

1 file changed, 8 insertions(+), 6 deletions(-)
arch_init.c +2 -1
index 08fccf6..cf4e1d5 100644
@@ -832,14 +832,16 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
            }
 
            ch = qemu_get_byte(f);
-            memset(host, ch, TARGET_PAGE_SIZE);
+            if (ch != 0 || !is_zero_page(host)) {
+                memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32

arch_init.c static int ram_load(QEMUFile *f, void *opaque, int version_id) · line 842

Quoted 10 lines
arch_init.c +5 -5
-            if (ch == 0 &&
-                (!kvm_enabled() || kvm_has_sync_mmu()) &&
-                getpagesize() <= TARGET_PAGE_SIZE) {
-                qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
-            }
+                if (ch == 0 &&
+                    (!kvm_enabled() || kvm_has_sync_mmu()) &&
+                    getpagesize() <= TARGET_PAGE_SIZE) {
+                    qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
+                }
Quoted 3 lines

Also CC'ing qemu-stable, but from what I gather this just mitigates the performance impact of 1/2 and isn't strictly necessary to fix migration? i.e. we can still do outgoing migration to 1.5.0 guests?

correct. the regression was introduced by the patch that was reverted in 1/2. This patch is just a nice to have to avoid unnecessary allocation of zero pages.

Peter

Reviewed-by on v2 2/2
#9 lore raw

Re: [Qemu-devel] [PATCHv2 2/2] migration: do not overwrite zero pages

In reply to Peter Lieven
Quoted 28 lines · Peter Lieven

on incoming migration do not memset pages to zero if they already read as zero. this will allocate a new zero page and consume memory unnecessarily. even if we madvise a MADV_DONTNEED later this will only deallocate the memory asynchronously.

---
 arch_init.c |   14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)
arch_init.c +2 -6
index 08fccf6..cf4e1d5 100644
@@ -832,14 +832,16 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
             }
 
             ch = qemu_get_byte(f);
-            memset(host, ch, TARGET_PAGE_SIZE);
+            if (ch != 0 || !is_zero_page(host)) {
+                memset(host, ch, TARGET_PAGE_SIZE);
 #ifndef _WIN32
-            if (ch == 0 &&
-                (!kvm_enabled() || kvm_has_sync_mmu()) &&
-                getpagesize() <= TARGET_PAGE_SIZE) {
-                qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
-            }

arch_init.c static int ram_load(QEMUFile *f, void *opaque, int version_id) · line 847

Quoted 10 lines
arch_init.c +6 -0
+                if (ch == 0 &&
+                    (!kvm_enabled() || kvm_has_sync_mmu()) &&
+                    getpagesize() <= TARGET_PAGE_SIZE) {
+                    qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
+                }
 #endif
+            }
         } else if (flags & RAM_SAVE_FLAG_PAGE) {
             void *host;
 
Reviewed-by on v2 2/2
#10 lore raw

Re: [Qemu-devel] [PATCHv2 2/2] migration: do not overwrite zero pages

In reply to Peter Lieven
Quoted 15 lines · Peter Lieven

on incoming migration do not memset pages to zero if they already read as zero. this will allocate a new zero page and consume memory unnecessarily. even if we madvise a MADV_DONTNEED later this will only deallocate the memory asynchronously.

---
  arch_init.c |   14 ++++++++------
  1 file changed, 8 insertions(+), 6 deletions(-)
arch_init.c +0 -0
index 08fccf6..cf4e1d5 100644

arch_init.c static int ram_load(QEMUFile *f, void *opaque, int version_id) · line 835

Quoted 5 lines
arch_init.c +1 -1
@@ -832,14 +832,16 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
              }
 
              ch = qemu_get_byte(f);
-            memset(host, ch, TARGET_PAGE_SIZE);
+            if (ch != 0 || !is_zero_page(host)) {

If incoming page is not zero, always memset. If incoming page is
zero, then if on destination it is not zero, memset. Logic is OK. Only question is if the read operation in is_zero_page() consumes memory, as there are doubt in the discuss before.
Any way this patch will not break migration in my opinion.

Quoted 17 lines
arch_init.c +7 -5
+                memset(host, ch, TARGET_PAGE_SIZE);
  #ifndef _WIN32
-            if (ch == 0 &&
-                (!kvm_enabled() || kvm_has_sync_mmu()) &&
-                getpagesize() <= TARGET_PAGE_SIZE) {
-                qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
-            }
+                if (ch == 0 &&
+                    (!kvm_enabled() || kvm_has_sync_mmu()) &&
+                    getpagesize() <= TARGET_PAGE_SIZE) {
+                    qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED);
+                }
  #endif
+            }
          } else if (flags & RAM_SAVE_FLAG_PAGE) {
              void *host;
 
Signature · 3 lines
Best Regards

Wenchao Xia
#11 lore raw

Re: [Qemu-devel] [PATCHv2 2/2] migration: do not overwrite zero pages

Quoted 18 lines · Wenchao Xia
Quoted 17 lines · Peter Lieven

on incoming migration do not memset pages to zero if they already read as zero. this will allocate a new zero page and consume memory unnecessarily. even if we madvise a MADV_DONTNEED later this will only deallocate the memory asynchronously.

---
  arch_init.c |   14 ++++++++------
  1 file changed, 8 insertions(+), 6 deletions(-)
arch_init.c +0 -0
index 08fccf6..cf4e1d5 100644
@@ -832,14 +832,16 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id)
              }
 
Quoted 7 lines

arch_init.c static int ram_load(QEMUFile *f, void *opaque, int version_id) · line 835

Quoted 3 lines
arch_init.c +1 -1
              ch = qemu_get_byte(f);
-            memset(host, ch, TARGET_PAGE_SIZE);
+            if (ch != 0 || !is_zero_page(host)) {

If incoming page is not zero, always memset. If incoming page is
zero, then if on destination it is not zero, memset. Logic is OK. Only question is if the read operation in is_zero_page() consumes memory, as there are doubt in the discuss before.

It does not consume memory for normal pages and for thp since 3.8.

BR,
Peter