From: Juan Quintela <quintela@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Paolo Bonzini" <pbonzini@redhat.com>,
"David Hildenbrand" <david@redhat.com>,
"Laurent Vivier" <laurent@vivier.eu>,
"Stefan Hajnoczi" <stefanha@redhat.com>,
"Fam Zheng" <fam@euphon.net>,
qemu-block@nongnu.org,
"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
"Thomas Huth" <thuth@redhat.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
qemu-trivial@nongnu.org, "Michael Tokarev" <mjt@tls.msk.ru>,
"Daniel P. Berrangé" <berrange@redhat.com>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>,
"Peter Xu" <peterx@redhat.com>,
"Juan Quintela" <quintela@redhat.com>
Subject: [PATCH 23/30] migration: Introduce pss_channel
Date: Tue, 15 Nov 2022 13:12:19 +0100 [thread overview]
Message-ID: <20221115121226.26609-24-quintela@redhat.com> (raw)
In-Reply-To: <20221115121226.26609-1-quintela@redhat.com>
From: Peter Xu <peterx@redhat.com>
Introduce pss_channel for PageSearchStatus, define it as "the migration
channel to be used to transfer this host page".
We used to have rs->f, which is a mirror to MigrationState.to_dst_file.
After postcopy preempt initial version, rs->f can be dynamically changed
depending on which channel we want to use.
But that later work still doesn't grant full concurrency of sending pages
in e.g. different threads, because rs->f can either be the PRECOPY channel
or POSTCOPY channel. This needs to be per-thread too.
PageSearchStatus is actually a good piece of struct which we can leverage
if we want to have multiple threads sending pages. Sending a single guest
page may not make sense, so we make the granule to be "host page", and in
the PSS structure we allow specify a QEMUFile* to migrate a specific host
page. Then we open the possibility to specify different channels in
different threads with different PSS structures.
The PSS prefix can be slightly misleading here because e.g. for the
upcoming usage of postcopy channel/thread it's not "searching" (or,
scanning) at all but sending the explicit page that was requested. However
since PSS existed for some years keep it as-is until someone complains.
This patch mostly (simply) replace rs->f with pss->pss_channel only. No
functional change intended for this patch yet. But it does prepare to
finally drop rs->f, and make ram_save_guest_page() thread safe.
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
migration/ram.c | 70 +++++++++++++++++++++++++++----------------------
1 file changed, 38 insertions(+), 32 deletions(-)
diff --git a/migration/ram.c b/migration/ram.c
index b71edf1f26..fedd61b3da 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -481,6 +481,8 @@ void dirty_sync_missed_zero_copy(void)
/* used by the search for pages to send */
struct PageSearchStatus {
+ /* The migration channel used for a specific host page */
+ QEMUFile *pss_channel;
/* Current block being searched */
RAMBlock *block;
/* Current page to search from */
@@ -803,9 +805,9 @@ static void xbzrle_cache_zero_page(RAMState *rs, ram_addr_t current_addr)
* @block: block that contains the page we want to send
* @offset: offset inside the block for the page
*/
-static int save_xbzrle_page(RAMState *rs, uint8_t **current_data,
- ram_addr_t current_addr, RAMBlock *block,
- ram_addr_t offset)
+static int save_xbzrle_page(RAMState *rs, QEMUFile *file,
+ uint8_t **current_data, ram_addr_t current_addr,
+ RAMBlock *block, ram_addr_t offset)
{
int encoded_len = 0, bytes_xbzrle;
uint8_t *prev_cached_page;
@@ -873,11 +875,11 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data,
}
/* Send XBZRLE based compressed page */
- bytes_xbzrle = save_page_header(rs, rs->f, block,
+ bytes_xbzrle = save_page_header(rs, file, block,
offset | RAM_SAVE_FLAG_XBZRLE);
- qemu_put_byte(rs->f, ENCODING_FLAG_XBZRLE);
- qemu_put_be16(rs->f, encoded_len);
- qemu_put_buffer(rs->f, XBZRLE.encoded_buf, encoded_len);
+ qemu_put_byte(file, ENCODING_FLAG_XBZRLE);
+ qemu_put_be16(file, encoded_len);
+ qemu_put_buffer(file, XBZRLE.encoded_buf, encoded_len);
bytes_xbzrle += encoded_len + 1 + 2;
/*
* Like compressed_size (please see update_compress_thread_counts),
@@ -1333,9 +1335,10 @@ static int save_zero_page_to_file(RAMState *rs, QEMUFile *file,
* @block: block that contains the page we want to send
* @offset: offset inside the block for the page
*/
-static int save_zero_page(RAMState *rs, RAMBlock *block, ram_addr_t offset)
+static int save_zero_page(RAMState *rs, QEMUFile *file, RAMBlock *block,
+ ram_addr_t offset)
{
- int len = save_zero_page_to_file(rs, rs->f, block, offset);
+ int len = save_zero_page_to_file(rs, file, block, offset);
if (len) {
stat64_add(&ram_atomic_counters.duplicate, 1);
@@ -1352,15 +1355,15 @@ static int save_zero_page(RAMState *rs, RAMBlock *block, ram_addr_t offset)
*
* Return true if the pages has been saved, otherwise false is returned.
*/
-static bool control_save_page(RAMState *rs, RAMBlock *block, ram_addr_t offset,
- int *pages)
+static bool control_save_page(PageSearchStatus *pss, RAMBlock *block,
+ ram_addr_t offset, int *pages)
{
uint64_t bytes_xmit = 0;
int ret;
*pages = -1;
- ret = ram_control_save_page(rs->f, block->offset, offset, TARGET_PAGE_SIZE,
- &bytes_xmit);
+ ret = ram_control_save_page(pss->pss_channel, block->offset, offset,
+ TARGET_PAGE_SIZE, &bytes_xmit);
if (ret == RAM_SAVE_CONTROL_NOT_SUPP) {
return false;
}
@@ -1394,17 +1397,17 @@ static bool control_save_page(RAMState *rs, RAMBlock *block, ram_addr_t offset,
* @buf: the page to be sent
* @async: send to page asyncly
*/
-static int save_normal_page(RAMState *rs, RAMBlock *block, ram_addr_t offset,
- uint8_t *buf, bool async)
+static int save_normal_page(RAMState *rs, QEMUFile *file, RAMBlock *block,
+ ram_addr_t offset, uint8_t *buf, bool async)
{
- ram_transferred_add(save_page_header(rs, rs->f, block,
+ ram_transferred_add(save_page_header(rs, file, block,
offset | RAM_SAVE_FLAG_PAGE));
if (async) {
- qemu_put_buffer_async(rs->f, buf, TARGET_PAGE_SIZE,
+ qemu_put_buffer_async(file, buf, TARGET_PAGE_SIZE,
migrate_release_ram() &&
migration_in_postcopy());
} else {
- qemu_put_buffer(rs->f, buf, TARGET_PAGE_SIZE);
+ qemu_put_buffer(file, buf, TARGET_PAGE_SIZE);
}
ram_transferred_add(TARGET_PAGE_SIZE);
stat64_add(&ram_atomic_counters.normal, 1);
@@ -1437,8 +1440,8 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss)
XBZRLE_cache_lock();
if (rs->xbzrle_enabled && !migration_in_postcopy()) {
- pages = save_xbzrle_page(rs, &p, current_addr, block,
- offset);
+ pages = save_xbzrle_page(rs, pss->pss_channel, &p, current_addr,
+ block, offset);
if (!rs->last_stage) {
/* Can't send this cached data async, since the cache page
* might get updated before it gets to the wire
@@ -1449,7 +1452,8 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss)
/* XBZRLE overflow or normal page */
if (pages == -1) {
- pages = save_normal_page(rs, block, offset, p, send_async);
+ pages = save_normal_page(rs, pss->pss_channel, block, offset,
+ p, send_async);
}
XBZRLE_cache_unlock();
@@ -1457,10 +1461,10 @@ static int ram_save_page(RAMState *rs, PageSearchStatus *pss)
return pages;
}
-static int ram_save_multifd_page(RAMState *rs, RAMBlock *block,
+static int ram_save_multifd_page(QEMUFile *file, RAMBlock *block,
ram_addr_t offset)
{
- if (multifd_queue_page(rs->f, block, offset) < 0) {
+ if (multifd_queue_page(file, block, offset) < 0) {
return -1;
}
stat64_add(&ram_atomic_counters.normal, 1);
@@ -1755,7 +1759,7 @@ static int ram_save_release_protection(RAMState *rs, PageSearchStatus *pss,
uint64_t run_length = (pss->page - start_page) << TARGET_PAGE_BITS;
/* Flush async buffers before un-protect. */
- qemu_fflush(rs->f);
+ qemu_fflush(pss->pss_channel);
/* Un-protect memory range. */
res = uffd_change_protection(rs->uffdio_fd, page_address, run_length,
false, false);
@@ -2342,7 +2346,7 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss)
ram_addr_t offset = ((ram_addr_t)pss->page) << TARGET_PAGE_BITS;
int res;
- if (control_save_page(rs, block, offset, &res)) {
+ if (control_save_page(pss, block, offset, &res)) {
return res;
}
@@ -2350,7 +2354,7 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss)
return 1;
}
- res = save_zero_page(rs, block, offset);
+ res = save_zero_page(rs, pss->pss_channel, block, offset);
if (res > 0) {
/* Must let xbzrle know, otherwise a previous (now 0'd) cached
* page would be stale
@@ -2370,7 +2374,7 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss)
* still see partially copied pages which is data corruption.
*/
if (migrate_use_multifd() && !migration_in_postcopy()) {
- return ram_save_multifd_page(rs, block, offset);
+ return ram_save_multifd_page(pss->pss_channel, block, offset);
}
return ram_save_page(rs, pss);
@@ -2572,10 +2576,6 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss)
return 0;
}
- if (postcopy_preempt_active()) {
- postcopy_preempt_choose_channel(rs, pss);
- }
-
/* Update host page boundary information */
pss_host_page_prepare(pss);
@@ -2635,7 +2635,7 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss)
* explicit flush or it won't flush until the buffer is full.
*/
if (migrate_postcopy_preempt() && pss->postcopy_requested) {
- qemu_fflush(rs->f);
+ qemu_fflush(pss->pss_channel);
}
res = ram_save_release_protection(rs, pss, start_page);
@@ -2701,6 +2701,12 @@ static int ram_find_and_save_block(RAMState *rs)
}
if (found) {
+ /* Update rs->f with correct channel */
+ if (postcopy_preempt_active()) {
+ postcopy_preempt_choose_channel(rs, &pss);
+ }
+ /* Cache rs->f in pss_channel (TODO: remove rs->f) */
+ pss.pss_channel = rs->f;
pages = ram_save_host_page(rs, &pss);
}
} while (!pages && again);
--
2.38.1
next prev parent reply other threads:[~2022-11-15 12:22 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-15 12:11 [PATCH 00/30] Migration PULL request Juan Quintela
2022-11-15 12:11 ` [PATCH 01/30] migration/channel-block: fix return value for qio_channel_block_{readv, writev} Juan Quintela
2022-11-15 12:11 ` [PATCH 02/30] migration/multifd/zero-copy: Create helper function for flushing Juan Quintela
2022-11-15 12:11 ` [PATCH 03/30] migration: check magic value for deciding the mapping of channels Juan Quintela
2022-11-15 12:12 ` [PATCH 04/30] multifd: Create page_size fields into both MultiFD{Recv, Send}Params Juan Quintela
2022-11-15 12:12 ` [PATCH 05/30] multifd: Create page_count " Juan Quintela
2022-11-15 12:12 ` [PATCH 06/30] migration: Export ram_transferred_ram() Juan Quintela
2022-11-15 12:12 ` [PATCH 07/30] migration: Export ram_release_page() Juan Quintela
2022-11-15 12:12 ` [PATCH 08/30] Update AVX512 support for xbzrle_encode_buffer Juan Quintela
2022-11-15 12:12 ` [PATCH 09/30] Unit test code and benchmark code Juan Quintela
2022-11-15 12:12 ` [PATCH 10/30] migration: Fix possible infinite loop of ram save process Juan Quintela
2022-11-15 12:12 ` [PATCH 11/30] migration: Fix race on qemu_file_shutdown() Juan Quintela
2022-11-15 12:12 ` [PATCH 12/30] migration: Disallow postcopy preempt to be used with compress Juan Quintela
2022-11-15 12:12 ` [PATCH 13/30] migration: Use non-atomic ops for clear log bitmap Juan Quintela
2022-11-15 12:12 ` [PATCH 14/30] migration: Disable multifd explicitly with compression Juan Quintela
2022-11-15 12:12 ` [PATCH 15/30] migration: Take bitmap mutex when completing ram migration Juan Quintela
2022-11-15 12:12 ` [PATCH 16/30] migration: Add postcopy_preempt_active() Juan Quintela
2022-11-15 12:12 ` [PATCH 17/30] migration: Cleanup xbzrle zero page cache update logic Juan Quintela
2022-11-15 12:12 ` [PATCH 18/30] migration: Trivial cleanup save_page_header() on same block check Juan Quintela
2022-11-15 12:12 ` [PATCH 19/30] migration: Remove RAMState.f references in compression code Juan Quintela
2022-11-15 12:12 ` [PATCH 20/30] migration: Yield bitmap_mutex properly when sending/sleeping Juan Quintela
2022-11-15 12:12 ` [PATCH 21/30] migration: Use atomic ops properly for page accountings Juan Quintela
2022-11-15 12:12 ` [PATCH 22/30] migration: Teach PSS about host page Juan Quintela
2022-11-15 12:12 ` Juan Quintela [this message]
2022-11-15 12:12 ` [PATCH 24/30] migration: Add pss_init() Juan Quintela
2022-11-15 12:12 ` [PATCH 25/30] migration: Make PageSearchStatus part of RAMState Juan Quintela
2022-11-15 12:12 ` [PATCH 26/30] migration: Move last_sent_block into PageSearchStatus Juan Quintela
2022-11-15 12:12 ` [PATCH 27/30] migration: Send requested page directly in rp-return thread Juan Quintela
2022-11-15 12:12 ` [PATCH 28/30] migration: Remove old preempt code around state maintainance Juan Quintela
2022-11-15 12:12 ` [PATCH 29/30] migration: Drop rs->f Juan Quintela
2022-11-15 12:12 ` [PATCH 30/30] migration: Block migration comment or code is wrong Juan Quintela
2022-11-15 14:55 ` [PATCH 00/30] Migration PULL request Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221115121226.26609-24-quintela@redhat.com \
--to=quintela@redhat.com \
--cc=berrange@redhat.com \
--cc=david@redhat.com \
--cc=dgilbert@redhat.com \
--cc=fam@euphon.net \
--cc=laurent@vivier.eu \
--cc=marcandre.lureau@redhat.com \
--cc=mjt@tls.msk.ru \
--cc=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=philmd@linaro.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-trivial@nongnu.org \
--cc=stefanha@redhat.com \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).