aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuan Liu <yuan1.liu@intel.com>2024-04-01 23:41:10 +0800
committerPeter Xu <peterx@redhat.com>2024-04-23 18:36:01 -0400
commit5ef7e26bdb7eda10d6d5e1b77121be9945e5e550 (patch)
tree8823bbea099cf77e06a48b8d465ff2666c9adf6a
parentdd031677257d7d00a72f28f073befc22691a0ad6 (diff)
downloadqemu-5ef7e26bdb7eda10d6d5e1b77121be9945e5e550.zip
qemu-5ef7e26bdb7eda10d6d5e1b77121be9945e5e550.tar.gz
qemu-5ef7e26bdb7eda10d6d5e1b77121be9945e5e550.tar.bz2
migration/multifd: solve zero page causing multiple page faults
Implemented recvbitmap tracking of received pages in multifd. If the zero page appears for the first time in the recvbitmap, this page is not checked and set. If the zero page has already appeared in the recvbitmap, there is no need to check the data but directly set the data to 0, because it is unlikely that the zero page will be migrated multiple times. Signed-off-by: Yuan Liu <yuan1.liu@intel.com> Reviewed-by: Fabiano Rosas <farosas@suse.de> Link: https://lore.kernel.org/r/20240401154110.2028453-2-yuan1.liu@intel.com [peterx: touch up the comment, as the bitmap is used outside postcopy now] Signed-off-by: Peter Xu <peterx@redhat.com>
-rw-r--r--include/exec/ramblock.h2
-rw-r--r--migration/multifd-zero-page.c4
-rw-r--r--migration/multifd-zlib.c1
-rw-r--r--migration/multifd-zstd.c1
-rw-r--r--migration/multifd.c1
-rw-r--r--migration/ram.c4
-rw-r--r--migration/ram.h1
7 files changed, 12 insertions, 2 deletions
diff --git a/include/exec/ramblock.h b/include/exec/ramblock.h
index 848915e..7062da3 100644
--- a/include/exec/ramblock.h
+++ b/include/exec/ramblock.h
@@ -57,7 +57,7 @@ struct RAMBlock {
off_t bitmap_offset;
uint64_t pages_offset;
- /* bitmap of already received pages in postcopy */
+ /* Bitmap of already received pages. Only used on destination side. */
unsigned long *receivedmap;
/*
diff --git a/migration/multifd-zero-page.c b/migration/multifd-zero-page.c
index 1ba38be..e1b8370 100644
--- a/migration/multifd-zero-page.c
+++ b/migration/multifd-zero-page.c
@@ -80,8 +80,10 @@ void multifd_recv_zero_page_process(MultiFDRecvParams *p)
{
for (int i = 0; i < p->zero_num; i++) {
void *page = p->host + p->zero[i];
- if (!buffer_is_zero(page, p->page_size)) {
+ if (ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i])) {
memset(page, 0, p->page_size);
+ } else {
+ ramblock_recv_bitmap_set_offset(p->block, p->zero[i]);
}
}
}
diff --git a/migration/multifd-zlib.c b/migration/multifd-zlib.c
index 99821cd..737a964 100644
--- a/migration/multifd-zlib.c
+++ b/migration/multifd-zlib.c
@@ -284,6 +284,7 @@ static int zlib_recv(MultiFDRecvParams *p, Error **errp)
int flush = Z_NO_FLUSH;
unsigned long start = zs->total_out;
+ ramblock_recv_bitmap_set_offset(p->block, p->normal[i]);
if (i == p->normal_num - 1) {
flush = Z_SYNC_FLUSH;
}
diff --git a/migration/multifd-zstd.c b/migration/multifd-zstd.c
index 0211225..256858d 100644
--- a/migration/multifd-zstd.c
+++ b/migration/multifd-zstd.c
@@ -278,6 +278,7 @@ static int zstd_recv(MultiFDRecvParams *p, Error **errp)
z->in.pos = 0;
for (i = 0; i < p->normal_num; i++) {
+ ramblock_recv_bitmap_set_offset(p->block, p->normal[i]);
z->out.dst = p->host + p->normal[i];
z->out.size = p->page_size;
z->out.pos = 0;
diff --git a/migration/multifd.c b/migration/multifd.c
index 2802afe..f317bff 100644
--- a/migration/multifd.c
+++ b/migration/multifd.c
@@ -277,6 +277,7 @@ static int nocomp_recv(MultiFDRecvParams *p, Error **errp)
for (int i = 0; i < p->normal_num; i++) {
p->iov[i].iov_base = p->host + p->normal[i];
p->iov[i].iov_len = p->page_size;
+ ramblock_recv_bitmap_set_offset(p->block, p->normal[i]);
}
return qio_channel_readv_all(p->c, p->iov, p->normal_num, errp);
}
diff --git a/migration/ram.c b/migration/ram.c
index daffcd8..a975c5a 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -275,6 +275,10 @@ void ramblock_recv_bitmap_set_range(RAMBlock *rb, void *host_addr,
nr);
}
+void ramblock_recv_bitmap_set_offset(RAMBlock *rb, uint64_t byte_offset)
+{
+ set_bit_atomic(byte_offset >> TARGET_PAGE_BITS, rb->receivedmap);
+}
#define RAMBLOCK_RECV_BITMAP_ENDING (0x0123456789abcdefULL)
/*
diff --git a/migration/ram.h b/migration/ram.h
index 08feeca..bc0318b 100644
--- a/migration/ram.h
+++ b/migration/ram.h
@@ -69,6 +69,7 @@ int ramblock_recv_bitmap_test(RAMBlock *rb, void *host_addr);
bool ramblock_recv_bitmap_test_byte_offset(RAMBlock *rb, uint64_t byte_offset);
void ramblock_recv_bitmap_set(RAMBlock *rb, void *host_addr);
void ramblock_recv_bitmap_set_range(RAMBlock *rb, void *host_addr, size_t nr);
+void ramblock_recv_bitmap_set_offset(RAMBlock *rb, uint64_t byte_offset);
int64_t ramblock_recv_bitmap_send(QEMUFile *file,
const char *block_name);
bool ram_dirty_bitmap_reload(MigrationState *s, RAMBlock *rb, Error **errp);