qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v9 0/3] Eliminate multifd flush
@ 2023-04-26 18:18 Juan Quintela
  2023-04-26 18:18 ` [PATCH v9 1/3] multifd: Create property multifd-flush-after-each-section Juan Quintela
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Juan Quintela @ 2023-04-26 18:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: Philippe Mathieu-Daudé, Marcel Apfelbaum, Peter Xu,
	Juan Quintela, Leonardo Bras, Yanan Wang, Eduardo Habkost

Hi

Changes in v9:
- rebase over migration-pull-20230424
  this means that we need to change things for options.c creation.
- make the property be set for 8.0 not 7.0 (thanks peter)
- the check that disabled the property was lost on some rebase, put it back.

Please, review.

[v8]
- rebase over latests

[v7]
- Rebased to last upstream
- Rename the capability to a property.  So we move all the problems
  that we have on last review dissaper because it is not a capability.

So now, it is works as expected.  Enabled for old machine types,
disabled for new machine types.  Users will only found it if they go through the migration properties.

[v6]
- Rename multifd-sync-after-each-section to
         multifd-flush-after-each-section
- Redo comments (thanks Markus)
- Redo how to comment capabilities that are enabled/disabled during
  development. (thanks Markus)

[v5]
- Remove RAM Flags documentation (already on PULL request)
- rebase on top of PULL request.

[v4]
- Rebased on top of migration-20230209 PULL request
- Integrate two patches in that pull request
- Rebase
- Address Eric reviews.

[v3]
- update to latest upstream.
- fix checkpatch errors.

[v2]
- update to latest upstream
- change 0, 1, 2 values to defines
- Add documentation for SAVE_VM_FLAGS
- Add missing qemu_fflush(), it made random hangs for migration test
  (only for tls, no clue why).

[v1]
Upstream multifd code synchronize all threads after each RAM section.  This is suboptimal.
Change it to only flush after we go trough all ram.

Preserve all semantics for old machine types.

Juan Quintela (3):
  multifd: Create property multifd-flush-after-each-section
  multifd: Protect multifd_send_sync_main() calls
  multifd: Only flush once each full round of memory

 hw/core/machine.c     |  4 +++-
 migration/migration.c |  2 ++
 migration/migration.h | 11 +++++++++++
 migration/options.c   |  7 +++++++
 migration/options.h   |  1 +
 migration/ram.c       | 44 +++++++++++++++++++++++++++++++++++++------
 6 files changed, 62 insertions(+), 7 deletions(-)

-- 
2.40.0



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v9 1/3] multifd: Create property multifd-flush-after-each-section
  2023-04-26 18:18 [PATCH v9 0/3] Eliminate multifd flush Juan Quintela
@ 2023-04-26 18:18 ` Juan Quintela
  2023-04-26 18:19 ` [PATCH v9 2/3] multifd: Protect multifd_send_sync_main() calls Juan Quintela
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Juan Quintela @ 2023-04-26 18:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: Philippe Mathieu-Daudé, Marcel Apfelbaum, Peter Xu,
	Juan Quintela, Leonardo Bras, Yanan Wang, Eduardo Habkost,
	Dr . David Alan Gilbert

We used to flush all channels at the end of each RAM section
sent.  That is not needed, so preparing to only flush after a full
iteration through all the RAM.

Default value of the property is false.  But we return "true" in
migrate_multifd_flush_after_each_section() until we implement the code
in following patches.

Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

---

Rename each-iteration to after-each-section
Rename multifd-sync-after-each-section to
       multifd-flush-after-each-section
Move to machine-8.0 (peter)
---
 hw/core/machine.c     |  4 +++-
 migration/migration.c |  2 ++
 migration/migration.h | 12 ++++++++++++
 migration/options.c   | 11 +++++++++++
 migration/options.h   |  1 +
 5 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 2ce97a5d3b..47a34841a5 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -39,7 +39,9 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-pci.h"
 
-GlobalProperty hw_compat_8_0[] = {};
+GlobalProperty hw_compat_8_0[] = {
+    { "migration", "multifd-flush-after-each-section", "on"},
+};
 const size_t hw_compat_8_0_len = G_N_ELEMENTS(hw_compat_8_0);
 
 GlobalProperty hw_compat_7_2[] = {
diff --git a/migration/migration.c b/migration/migration.c
index 22e8586623..e82aa69842 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -3344,6 +3344,8 @@ static Property migration_properties[] = {
                      send_section_footer, true),
     DEFINE_PROP_BOOL("decompress-error-check", MigrationState,
                       decompress_error_check, true),
+    DEFINE_PROP_BOOL("multifd-flush-after-each-section", MigrationState,
+                      multifd_flush_after_each_section, true),
     DEFINE_PROP_UINT8("x-clear-bitmap-shift", MigrationState,
                       clear_bitmap_shift, CLEAR_BITMAP_SHIFT_DEFAULT),
     DEFINE_PROP_BOOL("x-preempt-pre-7-2", MigrationState,
diff --git a/migration/migration.h b/migration/migration.h
index 2b71df8617..e2247d708f 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -404,6 +404,18 @@ struct MigrationState {
      */
     bool preempt_pre_7_2;
 
+    /*
+     * flush every channel after each section sent.
+     *
+     * This assures that we can't mix pages from one iteration through
+     * ram pages with pages for the following iteration.  We really
+     * only need to do this flush after we have go through all the
+     * dirty pages.  For historical reasons, we do that after each
+     * section.  This is suboptimal (we flush too many times).
+     * Default value is false.  Setting this property has no effect
+     * until the patch that removes this comment.  (since 8.1)
+     */
+    bool multifd_flush_after_each_section;
     /*
      * This decides the size of guest memory chunk that will be used
      * to track dirty bitmap clearing.  The size of memory chunk will
diff --git a/migration/options.c b/migration/options.c
index c6030587cf..b9d54b4ef7 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -217,6 +217,17 @@ bool migrate_zero_copy_send(void)
 
 /* pseudo capabilities */
 
+bool migrate_multifd_flush_after_each_section(void)
+{
+    MigrationState *s = migrate_get_current();
+
+    /*
+     * Until the patch that remove this comment, we always return that
+     * the property is enabled.
+     */
+    return true || s->multifd_flush_after_each_section;
+}
+
 bool migrate_postcopy(void)
 {
     return migrate_postcopy_ram() || migrate_dirty_bitmaps();
diff --git a/migration/options.h b/migration/options.h
index 89067e59a0..9b9ea0cde8 100644
--- a/migration/options.h
+++ b/migration/options.h
@@ -52,6 +52,7 @@ bool migrate_zero_copy_send(void);
  * check, but they are not a capability.
  */
 
+bool migrate_multifd_flush_after_each_section(void);
 bool migrate_postcopy(void);
 bool migrate_tls(void);
 
-- 
2.40.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v9 2/3] multifd: Protect multifd_send_sync_main() calls
  2023-04-26 18:18 [PATCH v9 0/3] Eliminate multifd flush Juan Quintela
  2023-04-26 18:18 ` [PATCH v9 1/3] multifd: Create property multifd-flush-after-each-section Juan Quintela
@ 2023-04-26 18:19 ` Juan Quintela
  2023-04-26 18:19 ` [PATCH v9 3/3] multifd: Only flush once each full round of memory Juan Quintela
  2023-04-26 19:49 ` [PATCH v9 0/3] Eliminate multifd flush Peter Xu
  3 siblings, 0 replies; 5+ messages in thread
From: Juan Quintela @ 2023-04-26 18:19 UTC (permalink / raw)
  To: qemu-devel
  Cc: Philippe Mathieu-Daudé, Marcel Apfelbaum, Peter Xu,
	Juan Quintela, Leonardo Bras, Yanan Wang, Eduardo Habkost,
	Dr . David Alan Gilbert

We only need to do that on the ram_save_iterate() call on sending and
on destination when we get a RAM_SAVE_FLAG_EOS.

In setup() and complete() we need to synch in both new and old cases,
so don't add a check there.

Signed-off-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Acked-by: Peter Xu <peterx@redhat.com>

---

Remove the wrappers that we take out on patch 5.
---
 migration/ram.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/migration/ram.c b/migration/ram.c
index 01356f60a4..1e2414d681 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -3394,9 +3394,11 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
 out:
     if (ret >= 0
         && migration_is_setup_or_active(migrate_get_current()->state)) {
-        ret = multifd_send_sync_main(rs->pss[RAM_CHANNEL_PRECOPY].pss_channel);
-        if (ret < 0) {
-            return ret;
+        if (migrate_multifd_flush_after_each_section()) {
+            ret = multifd_send_sync_main(rs->pss[RAM_CHANNEL_PRECOPY].pss_channel);
+            if (ret < 0) {
+                return ret;
+            }
         }
 
         qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
@@ -4153,7 +4155,9 @@ int ram_load_postcopy(QEMUFile *f, int channel)
 
         case RAM_SAVE_FLAG_EOS:
             /* normal exit */
-            multifd_recv_sync_main();
+            if (migrate_multifd_flush_after_each_section()) {
+                multifd_recv_sync_main();
+            }
             break;
         default:
             error_report("Unknown combination of migration flags: 0x%x"
@@ -4424,7 +4428,9 @@ static int ram_load_precopy(QEMUFile *f)
             break;
         case RAM_SAVE_FLAG_EOS:
             /* normal exit */
-            multifd_recv_sync_main();
+            if (migrate_multifd_flush_after_each_section()) {
+                multifd_recv_sync_main();
+            }
             break;
         default:
             if (flags & RAM_SAVE_FLAG_HOOK) {
-- 
2.40.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v9 3/3] multifd: Only flush once each full round of memory
  2023-04-26 18:18 [PATCH v9 0/3] Eliminate multifd flush Juan Quintela
  2023-04-26 18:18 ` [PATCH v9 1/3] multifd: Create property multifd-flush-after-each-section Juan Quintela
  2023-04-26 18:19 ` [PATCH v9 2/3] multifd: Protect multifd_send_sync_main() calls Juan Quintela
@ 2023-04-26 18:19 ` Juan Quintela
  2023-04-26 19:49 ` [PATCH v9 0/3] Eliminate multifd flush Peter Xu
  3 siblings, 0 replies; 5+ messages in thread
From: Juan Quintela @ 2023-04-26 18:19 UTC (permalink / raw)
  To: qemu-devel
  Cc: Philippe Mathieu-Daudé, Marcel Apfelbaum, Peter Xu,
	Juan Quintela, Leonardo Bras, Yanan Wang, Eduardo Habkost

We need to add a new flag to mean to flush at that point.
Notice that we still flush at the end of setup and at the end of
complete stages.

Signed-off-by: Juan Quintela <quintela@redhat.com>

---

Add missing qemu_fflush(), now it passes all tests always.
In the previous version, the check that changes the default value to
false got lost in some rebase.  Get it back.
---
 migration/migration.c |  2 +-
 migration/migration.h |  3 +--
 migration/options.c   |  6 +-----
 migration/ram.c       | 28 +++++++++++++++++++++++++++-
 4 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/migration/migration.c b/migration/migration.c
index e82aa69842..e504f30c2e 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -3345,7 +3345,7 @@ static Property migration_properties[] = {
     DEFINE_PROP_BOOL("decompress-error-check", MigrationState,
                       decompress_error_check, true),
     DEFINE_PROP_BOOL("multifd-flush-after-each-section", MigrationState,
-                      multifd_flush_after_each_section, true),
+                      multifd_flush_after_each_section, false),
     DEFINE_PROP_UINT8("x-clear-bitmap-shift", MigrationState,
                       clear_bitmap_shift, CLEAR_BITMAP_SHIFT_DEFAULT),
     DEFINE_PROP_BOOL("x-preempt-pre-7-2", MigrationState,
diff --git a/migration/migration.h b/migration/migration.h
index e2247d708f..3a918514e7 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -412,8 +412,7 @@ struct MigrationState {
      * only need to do this flush after we have go through all the
      * dirty pages.  For historical reasons, we do that after each
      * section.  This is suboptimal (we flush too many times).
-     * Default value is false.  Setting this property has no effect
-     * until the patch that removes this comment.  (since 8.1)
+     * Default value is false. (since 8.1)
      */
     bool multifd_flush_after_each_section;
     /*
diff --git a/migration/options.c b/migration/options.c
index b9d54b4ef7..78bfcc8ec0 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -221,11 +221,7 @@ bool migrate_multifd_flush_after_each_section(void)
 {
     MigrationState *s = migrate_get_current();
 
-    /*
-     * Until the patch that remove this comment, we always return that
-     * the property is enabled.
-     */
-    return true || s->multifd_flush_after_each_section;
+    return s->multifd_flush_after_each_section;
 }
 
 bool migrate_postcopy(void)
diff --git a/migration/ram.c b/migration/ram.c
index 1e2414d681..e9dcda8b9d 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -86,6 +86,7 @@
 #define RAM_SAVE_FLAG_XBZRLE   0x40
 /* 0x80 is reserved in qemu-file.h for RAM_SAVE_FLAG_HOOK */
 #define RAM_SAVE_FLAG_COMPRESS_PAGE    0x100
+#define RAM_SAVE_FLAG_MULTIFD_FLUSH    0x200
 /* We can't use any flag that is bigger than 0x200 */
 
 int (*xbzrle_encode_buffer_func)(uint8_t *, uint8_t *, int,
@@ -1581,6 +1582,7 @@ retry:
  * associated with the search process.
  *
  * Returns:
+ *         <0: An error happened
  *         PAGE_ALL_CLEAN: no dirty page found, give up
  *         PAGE_TRY_AGAIN: no dirty page found, retry for next block
  *         PAGE_DIRTY_FOUND: dirty page found
@@ -1608,6 +1610,15 @@ static int find_dirty_block(RAMState *rs, PageSearchStatus *pss)
         pss->page = 0;
         pss->block = QLIST_NEXT_RCU(pss->block, next);
         if (!pss->block) {
+            if (!migrate_multifd_flush_after_each_section()) {
+                QEMUFile *f = rs->pss[RAM_CHANNEL_PRECOPY].pss_channel;
+                int ret = multifd_send_sync_main(f);
+                if (ret < 0) {
+                    return ret;
+                }
+                qemu_put_be64(f, RAM_SAVE_FLAG_MULTIFD_FLUSH);
+                qemu_fflush(f);
+            }
             /*
              * If memory migration starts over, we will meet a dirtied page
              * which may still exists in compression threads's ring, so we
@@ -2600,6 +2611,9 @@ static int ram_find_and_save_block(RAMState *rs)
                     break;
                 } else if (res == PAGE_TRY_AGAIN) {
                     continue;
+                } else if (res < 0) {
+                    pages = res;
+                    break;
                 }
             }
         }
@@ -3286,6 +3300,10 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
         return ret;
     }
 
+    if (!migrate_multifd_flush_after_each_section()) {
+        qemu_put_be64(f, RAM_SAVE_FLAG_MULTIFD_FLUSH);
+    }
+
     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
     qemu_fflush(f);
 
@@ -3471,6 +3489,9 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
         return ret;
     }
 
+    if (!migrate_multifd_flush_after_each_section()) {
+        qemu_put_be64(f, RAM_SAVE_FLAG_MULTIFD_FLUSH);
+    }
     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
     qemu_fflush(f);
 
@@ -4152,7 +4173,9 @@ int ram_load_postcopy(QEMUFile *f, int channel)
             }
             decompress_data_with_multi_threads(f, page_buffer, len);
             break;
-
+        case RAM_SAVE_FLAG_MULTIFD_FLUSH:
+            multifd_recv_sync_main();
+            break;
         case RAM_SAVE_FLAG_EOS:
             /* normal exit */
             if (migrate_multifd_flush_after_each_section()) {
@@ -4426,6 +4449,9 @@ static int ram_load_precopy(QEMUFile *f)
                 break;
             }
             break;
+        case RAM_SAVE_FLAG_MULTIFD_FLUSH:
+            multifd_recv_sync_main();
+            break;
         case RAM_SAVE_FLAG_EOS:
             /* normal exit */
             if (migrate_multifd_flush_after_each_section()) {
-- 
2.40.0



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v9 0/3] Eliminate multifd flush
  2023-04-26 18:18 [PATCH v9 0/3] Eliminate multifd flush Juan Quintela
                   ` (2 preceding siblings ...)
  2023-04-26 18:19 ` [PATCH v9 3/3] multifd: Only flush once each full round of memory Juan Quintela
@ 2023-04-26 19:49 ` Peter Xu
  3 siblings, 0 replies; 5+ messages in thread
From: Peter Xu @ 2023-04-26 19:49 UTC (permalink / raw)
  To: Juan Quintela
  Cc: qemu-devel, Philippe Mathieu-Daudé, Marcel Apfelbaum,
	Leonardo Bras, Yanan Wang, Eduardo Habkost

On Wed, Apr 26, 2023 at 08:18:58PM +0200, Juan Quintela wrote:
> Juan Quintela (3):
>   multifd: Create property multifd-flush-after-each-section
>   multifd: Protect multifd_send_sync_main() calls
>   multifd: Only flush once each full round of memory

Acked-by: Peter Xu <peterx@redhat.com>

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-04-26 19:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-26 18:18 [PATCH v9 0/3] Eliminate multifd flush Juan Quintela
2023-04-26 18:18 ` [PATCH v9 1/3] multifd: Create property multifd-flush-after-each-section Juan Quintela
2023-04-26 18:19 ` [PATCH v9 2/3] multifd: Protect multifd_send_sync_main() calls Juan Quintela
2023-04-26 18:19 ` [PATCH v9 3/3] multifd: Only flush once each full round of memory Juan Quintela
2023-04-26 19:49 ` [PATCH v9 0/3] Eliminate multifd flush Peter Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).