From 8d3031fa1bfcdc623934ec7b15889a3f49248552 Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Wed, 18 Sep 2024 12:18:53 +0530 Subject: [PATCH 01/12] memory: notify hypervisor of all eventfds during listener (de)registration When a new listener for an address space is registered, the hypervisor must be informed of all existing eventfds for that address space by calling eventfd_add() for that listener. Similarly, when a listener is de-registered from an address space, the hypervisor must be informed of all existing eventfds for that address space with a call to eventfd_del(). Same is also true for coalesced io. Send coalesced io add/del listener notifications if any flatrage for the address space registered with the listener intersects with any coalesced io range. Suggested-by: Paolo Bonzini Signed-off-by: Ani Sinha Link: https://lore.kernel.org/r/20240918064853.30678-1-anisinha@redhat.com Signed-off-by: Peter Xu --- system/memory.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/system/memory.c b/system/memory.c index f6f6fee6d8..85f6834cb3 100644 --- a/system/memory.c +++ b/system/memory.c @@ -941,6 +941,38 @@ static void flat_range_coalesced_io_add(FlatRange *fr, AddressSpace *as) } } +static void +flat_range_coalesced_io_notify_listener_add_del(FlatRange *fr, + MemoryRegionSection *mrs, + MemoryListener *listener, + AddressSpace *as, bool add) +{ + CoalescedMemoryRange *cmr; + MemoryRegion *mr = fr->mr; + AddrRange tmp; + + QTAILQ_FOREACH(cmr, &mr->coalesced, link) { + tmp = addrrange_shift(cmr->addr, + int128_sub(fr->addr.start, + int128_make64(fr->offset_in_region))); + + if (!addrrange_intersects(tmp, fr->addr)) { + return; + } + tmp = addrrange_intersection(tmp, fr->addr); + + if (add && listener->coalesced_io_add) { + listener->coalesced_io_add(listener, mrs, + int128_get64(tmp.start), + int128_get64(tmp.size)); + } else if (!add && listener->coalesced_io_del) { + listener->coalesced_io_del(listener, mrs, + int128_get64(tmp.start), + int128_get64(tmp.size)); + } + } +} + static void address_space_update_topology_pass(AddressSpace *as, const FlatView *old_view, const FlatView *new_view, @@ -3015,8 +3047,10 @@ void memory_global_dirty_log_stop(unsigned int flags) static void listener_add_address_space(MemoryListener *listener, AddressSpace *as) { + unsigned i; FlatView *view; FlatRange *fr; + MemoryRegionIoeventfd *fd; if (listener->begin) { listener->begin(listener); @@ -3041,10 +3075,34 @@ static void listener_add_address_space(MemoryListener *listener, if (listener->region_add) { listener->region_add(listener, §ion); } + + /* send coalesced io add notifications */ + flat_range_coalesced_io_notify_listener_add_del(fr, §ion, + listener, as, true); + if (fr->dirty_log_mask && listener->log_start) { listener->log_start(listener, §ion, 0, fr->dirty_log_mask); } } + + /* + * register all eventfds for this address space for the newly registered + * listener. + */ + for (i = 0; i < as->ioeventfd_nb; i++) { + fd = &as->ioeventfds[i]; + MemoryRegionSection section = (MemoryRegionSection) { + .fv = view, + .offset_within_address_space = int128_get64(fd->addr.start), + .size = fd->addr.size, + }; + + if (listener->eventfd_add) { + listener->eventfd_add(listener, §ion, + fd->match_data, fd->data, fd->e); + } + } + if (listener->commit) { listener->commit(listener); } @@ -3054,8 +3112,10 @@ static void listener_add_address_space(MemoryListener *listener, static void listener_del_address_space(MemoryListener *listener, AddressSpace *as) { + unsigned i; FlatView *view; FlatRange *fr; + MemoryRegionIoeventfd *fd; if (listener->begin) { listener->begin(listener); @@ -3067,10 +3127,33 @@ static void listener_del_address_space(MemoryListener *listener, if (fr->dirty_log_mask && listener->log_stop) { listener->log_stop(listener, §ion, fr->dirty_log_mask, 0); } + + /* send coalesced io del notifications */ + flat_range_coalesced_io_notify_listener_add_del(fr, §ion, + listener, as, false); if (listener->region_del) { listener->region_del(listener, §ion); } } + + /* + * de-register all eventfds for this address space for the current + * listener. + */ + for (i = 0; i < as->ioeventfd_nb; i++) { + fd = &as->ioeventfds[i]; + MemoryRegionSection section = (MemoryRegionSection) { + .fv = view, + .offset_within_address_space = int128_get64(fd->addr.start), + .size = fd->addr.size, + }; + + if (listener->eventfd_del) { + listener->eventfd_del(listener, §ion, + fd->match_data, fd->data, fd->e); + } + } + if (listener->commit) { listener->commit(listener); } From 68e0fca625912c7c63a8bfbc784f53d4fefa1a13 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Thu, 19 Sep 2024 12:06:11 -0300 Subject: [PATCH 02/12] migration/multifd: Ensure packet->ramblock is null-terminated Coverity points out that the current usage of strncpy to write the ramblock name allows the field to not have an ending '\0' in case idstr is already not null-terminated (e.g. if it's larger than 256 bytes). This is currently harmless because the packet->ramblock field is never touched again on the source side. The destination side reads only up to the field's size from the stream and forces the last byte to be 0. We're still open to a programming error in the future in case this field is ever passed into a function that expects a null-terminated string. Change from strncpy to QEMU's pstrcpy, which puts a '\0' at the end of the string and doesn't fill the extra space with zeros. (there's no spillage between iterations of fill_packet because after commit 87bb9e953e ("migration/multifd: Isolate ram pages packet data") the packet is always zeroed before filling) Resolves: Coverity CID 1560071 Reported-by: Peter Maydell Signed-off-by: Fabiano Rosas Link: https://lore.kernel.org/r/20240919150611.17074-1-farosas@suse.de Signed-off-by: Peter Xu --- migration/multifd-nocomp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/migration/multifd-nocomp.c b/migration/multifd-nocomp.c index 07c63f4a72..55191152f9 100644 --- a/migration/multifd-nocomp.c +++ b/migration/multifd-nocomp.c @@ -17,6 +17,7 @@ #include "multifd.h" #include "options.h" #include "qapi/error.h" +#include "qemu/cutils.h" #include "qemu/error-report.h" #include "trace.h" @@ -201,7 +202,8 @@ void multifd_ram_fill_packet(MultiFDSendParams *p) packet->zero_pages = cpu_to_be32(zero_num); if (pages->block) { - strncpy(packet->ramblock, pages->block->idstr, 256); + pstrcpy(packet->ramblock, sizeof(packet->ramblock), + pages->block->idstr); } for (int i = 0; i < pages->num; i++) { From a5d8d1384224252b122cb23e3bc141dcd29d41c2 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 19 Sep 2024 14:46:20 +0100 Subject: [PATCH 03/12] migration: Remove migrate_cap_set migrate_cap_set has been unused since 18d154f575 ("migration: Remove 'blk/-b' option from migrate commands") Remove it. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Fabiano Rosas Link: https://lore.kernel.org/r/20240919134626.166183-2-dave@treblig.org Signed-off-by: Peter Xu --- migration/options.c | 20 -------------------- migration/options.h | 1 - 2 files changed, 21 deletions(-) diff --git a/migration/options.c b/migration/options.c index 147cd2b8fd..9460c5dee9 100644 --- a/migration/options.c +++ b/migration/options.c @@ -605,26 +605,6 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp) return true; } -bool migrate_cap_set(int cap, bool value, Error **errp) -{ - MigrationState *s = migrate_get_current(); - bool new_caps[MIGRATION_CAPABILITY__MAX]; - - if (migration_is_running()) { - error_setg(errp, "There's a migration process in progress"); - return false; - } - - memcpy(new_caps, s->capabilities, sizeof(new_caps)); - new_caps[cap] = value; - - if (!migrate_caps_check(s->capabilities, new_caps, errp)) { - return false; - } - s->capabilities[cap] = value; - return true; -} - MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) { MigrationCapabilityStatusList *head = NULL, **tail = &head; diff --git a/migration/options.h b/migration/options.h index a0bd6edc06..36e7b3723f 100644 --- a/migration/options.h +++ b/migration/options.h @@ -58,7 +58,6 @@ bool migrate_tls(void); /* capabilities helpers */ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp); -bool migrate_cap_set(int cap, bool value, Error **errp); /* parameters */ From 21ed5ff6063422c874fbb0e389d5b4cfd18b6fff Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 19 Sep 2024 14:46:21 +0100 Subject: [PATCH 04/12] migration: Remove unused migrate_zero_blocks migrate_zero_blocks is unused since eef0bae3a7 ("migration: Remove block migration") Remove it. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Peter Xu Link: https://lore.kernel.org/r/20240919134626.166183-3-dave@treblig.org Signed-off-by: Peter Xu --- migration/options.c | 7 ------- migration/options.h | 1 - 2 files changed, 8 deletions(-) diff --git a/migration/options.c b/migration/options.c index 9460c5dee9..6f549984cb 100644 --- a/migration/options.c +++ b/migration/options.c @@ -339,13 +339,6 @@ bool migrate_xbzrle(void) return s->capabilities[MIGRATION_CAPABILITY_XBZRLE]; } -bool migrate_zero_blocks(void) -{ - MigrationState *s = migrate_get_current(); - - return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS]; -} - bool migrate_zero_copy_send(void) { MigrationState *s = migrate_get_current(); diff --git a/migration/options.h b/migration/options.h index 36e7b3723f..79084eed0d 100644 --- a/migration/options.h +++ b/migration/options.h @@ -40,7 +40,6 @@ bool migrate_release_ram(void); bool migrate_return_path(void); bool migrate_validate_uuid(void); bool migrate_xbzrle(void); -bool migrate_zero_blocks(void); bool migrate_zero_copy_send(void); /* From 73581a041e683fe7899e6af799c42becf60ee400 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Thu, 19 Sep 2024 14:46:22 +0100 Subject: [PATCH 05/12] migration: Deprecate zero-blocks capability The zero-blocks capability was meant to be used along with the block migration, which has been removed already in commit eef0bae3a7 ("migration: Remove block migration"). Setting zero-blocks is currently a noop, but the outright removal of the capability would cause and error in case some users are still setting it. Put the capability through the deprecation process. Signed-off-by: Fabiano Rosas Reviewed-by: Peter Xu Link: https://lore.kernel.org/r/20240919134626.166183-4-dave@treblig.org Signed-off-by: Peter Xu --- docs/about/deprecated.rst | 6 ++++++ migration/options.c | 4 ++++ qapi/migration.json | 5 ++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index c02bbb66f7..33ce4f9536 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -467,3 +467,9 @@ usage of providing a file descriptor to a plain file has been deprecated in favor of explicitly using the ``file:`` URI with the file descriptor being passed as an ``fdset``. Refer to the ``add-fd`` command documentation for details on the ``fdset`` usage. + +``zero-blocks`` capability (since 9.2) +'''''''''''''''''''''''''''''''''''''' + +The ``zero-blocks`` capability was part of the block migration which +doesn't exist anymore since it was removed in QEMU v9.1. diff --git a/migration/options.c b/migration/options.c index 6f549984cb..ad8d6989a8 100644 --- a/migration/options.c +++ b/migration/options.c @@ -450,6 +450,10 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp) ERRP_GUARD(); MigrationIncomingState *mis = migration_incoming_get_current(); + if (new_caps[MIGRATION_CAPABILITY_ZERO_BLOCKS]) { + warn_report("zero-blocks capability is deprecated"); + } + #ifndef CONFIG_REPLICATION if (new_caps[MIGRATION_CAPABILITY_X_COLO]) { error_setg(errp, "QEMU compiled without replication module" diff --git a/qapi/migration.json b/qapi/migration.json index b66cccf107..3af6aa1740 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -479,11 +479,14 @@ # Features: # # @unstable: Members @x-colo and @x-ignore-shared are experimental. +# @deprecated: Member @zero-blocks is deprecated as being part of +# block migration which was already removed. # # Since: 1.2 ## { 'enum': 'MigrationCapability', - 'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', 'zero-blocks', + 'data': ['xbzrle', 'rdma-pin-all', 'auto-converge', + { 'name': 'zero-blocks', 'features': [ 'deprecated' ] }, 'events', 'postcopy-ram', { 'name': 'x-colo', 'features': [ 'unstable' ] }, 'release-ram', From 6242b36102ff7c8279015bb8b41f9d95fbb1f533 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 19 Sep 2024 14:46:23 +0100 Subject: [PATCH 06/12] migration: Remove unused socket_send_channel_create_sync socket_send_channel_create_sync only use was removed by d0edb8a173 ("migration: Create the postcopy preempt channel asynchronously") Remove it. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Fabiano Rosas Link: https://lore.kernel.org/r/20240919134626.166183-5-dave@treblig.org Signed-off-by: Peter Xu --- migration/socket.c | 18 ------------------ migration/socket.h | 1 - 2 files changed, 19 deletions(-) diff --git a/migration/socket.c b/migration/socket.c index 9ab89b1e08..5ec65b8c03 100644 --- a/migration/socket.c +++ b/migration/socket.c @@ -42,24 +42,6 @@ void socket_send_channel_create(QIOTaskFunc f, void *data) f, data, NULL, NULL); } -QIOChannel *socket_send_channel_create_sync(Error **errp) -{ - QIOChannelSocket *sioc = qio_channel_socket_new(); - - if (!outgoing_args.saddr) { - object_unref(OBJECT(sioc)); - error_setg(errp, "Initial sock address not set!"); - return NULL; - } - - if (qio_channel_socket_connect_sync(sioc, outgoing_args.saddr, errp) < 0) { - object_unref(OBJECT(sioc)); - return NULL; - } - - return QIO_CHANNEL(sioc); -} - struct SocketConnectData { MigrationState *s; char *hostname; diff --git a/migration/socket.h b/migration/socket.h index 46c233ecd2..04ebbe95a1 100644 --- a/migration/socket.h +++ b/migration/socket.h @@ -22,7 +22,6 @@ #include "qemu/sockets.h" void socket_send_channel_create(QIOTaskFunc f, void *data); -QIOChannel *socket_send_channel_create_sync(Error **errp); void socket_start_incoming_migration(SocketAddress *saddr, Error **errp); From 6f81bd1a3ec3b8c06ec614f09eac688c6053f412 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 19 Sep 2024 14:46:24 +0100 Subject: [PATCH 07/12] util/userfaultfd: Return -errno on error Convert (the currently unused) uffd_wakeup, uffd_copy_page and uffd_zero_page to return -errno on error rather than -1. That will make it easier to reuse in postcopy. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Peter Xu Link: https://lore.kernel.org/r/20240919134626.166183-6-dave@treblig.org Signed-off-by: Peter Xu --- util/userfaultfd.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/util/userfaultfd.c b/util/userfaultfd.c index 1b2fa949d4..518d5c3586 100644 --- a/util/userfaultfd.c +++ b/util/userfaultfd.c @@ -240,7 +240,7 @@ int uffd_change_protection(int uffd_fd, void *addr, uint64_t length, * Copy range of source pages to the destination to resolve * missing page fault somewhere in the destination range. * - * Returns 0 on success, negative value in case of an error + * Returns 0 on success, -errno in case of an error * * @uffd_fd: UFFD file descriptor * @dst_addr: destination base address @@ -259,10 +259,11 @@ int uffd_copy_page(int uffd_fd, void *dst_addr, void *src_addr, uffd_copy.mode = dont_wake ? UFFDIO_COPY_MODE_DONTWAKE : 0; if (ioctl(uffd_fd, UFFDIO_COPY, &uffd_copy)) { + int e = errno; error_report("uffd_copy_page() failed: dst_addr=%p src_addr=%p length=%" PRIu64 " mode=%" PRIx64 " errno=%i", dst_addr, src_addr, - length, (uint64_t) uffd_copy.mode, errno); - return -1; + length, (uint64_t) uffd_copy.mode, e); + return -e; } return 0; @@ -273,7 +274,7 @@ int uffd_copy_page(int uffd_fd, void *dst_addr, void *src_addr, * * Fill range pages with zeroes to resolve missing page fault within the range. * - * Returns 0 on success, negative value in case of an error + * Returns 0 on success, -errno in case of an error * * @uffd_fd: UFFD file descriptor * @addr: base address @@ -289,10 +290,11 @@ int uffd_zero_page(int uffd_fd, void *addr, uint64_t length, bool dont_wake) uffd_zeropage.mode = dont_wake ? UFFDIO_ZEROPAGE_MODE_DONTWAKE : 0; if (ioctl(uffd_fd, UFFDIO_ZEROPAGE, &uffd_zeropage)) { + int e = errno; error_report("uffd_zero_page() failed: addr=%p length=%" PRIu64 " mode=%" PRIx64 " errno=%i", addr, length, - (uint64_t) uffd_zeropage.mode, errno); - return -1; + (uint64_t) uffd_zeropage.mode, e); + return -e; } return 0; @@ -306,7 +308,7 @@ int uffd_zero_page(int uffd_fd, void *addr, uint64_t length, bool dont_wake) * via UFFD-IO IOCTLs with MODE_DONTWAKE flag set, then after that all waits * for the whole memory range are satisfied in a single call to uffd_wakeup(). * - * Returns 0 on success, negative value in case of an error + * Returns 0 on success, -errno in case of an error * * @uffd_fd: UFFD file descriptor * @addr: base address @@ -320,9 +322,10 @@ int uffd_wakeup(int uffd_fd, void *addr, uint64_t length) uffd_range.len = length; if (ioctl(uffd_fd, UFFDIO_WAKE, &uffd_range)) { + int e = errno; error_report("uffd_wakeup() failed: addr=%p length=%" PRIu64 " errno=%i", - addr, length, errno); - return -1; + addr, length, e); + return -e; } return 0; From 3ba55a33e82c9902c211d6325bc550afcca7ddf9 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 19 Sep 2024 14:46:25 +0100 Subject: [PATCH 08/12] migration/postcopy: Use uffd helpers Use the uffd_copy_page, uffd_zero_page and uffd_wakeup helpers rather than calling ioctl ourselves. They return -errno on error, and print an error_report themselves. I think this actually makes postcopy_place_page actually more consistent in it's callers. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Peter Xu Link: https://lore.kernel.org/r/20240919134626.166183-7-dave@treblig.org [peterx: fix i386 build] Signed-off-by: Peter Xu --- migration/postcopy-ram.c | 48 ++++++++++++---------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 0fe9d83d44..83f6160a36 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -746,18 +746,10 @@ int postcopy_wake_shared(struct PostCopyFD *pcfd, RAMBlock *rb) { size_t pagesize = qemu_ram_pagesize(rb); - struct uffdio_range range; - int ret; trace_postcopy_wake_shared(client_addr, qemu_ram_get_idstr(rb)); - range.start = ROUND_DOWN(client_addr, pagesize); - range.len = pagesize; - ret = ioctl(pcfd->fd, UFFDIO_WAKE, &range); - if (ret) { - error_report("%s: Failed to wake: %zx in %s (%s)", - __func__, (size_t)client_addr, qemu_ram_get_idstr(rb), - strerror(errno)); - } - return ret; + return uffd_wakeup(pcfd->fd, + (void *)(uintptr_t)ROUND_DOWN(client_addr, pagesize), + pagesize); } static int postcopy_request_page(MigrationIncomingState *mis, RAMBlock *rb, @@ -1275,18 +1267,10 @@ static int qemu_ufd_copy_ioctl(MigrationIncomingState *mis, void *host_addr, int ret; if (from_addr) { - struct uffdio_copy copy_struct; - copy_struct.dst = (uint64_t)(uintptr_t)host_addr; - copy_struct.src = (uint64_t)(uintptr_t)from_addr; - copy_struct.len = pagesize; - copy_struct.mode = 0; - ret = ioctl(userfault_fd, UFFDIO_COPY, ©_struct); + ret = uffd_copy_page(userfault_fd, host_addr, from_addr, pagesize, + false); } else { - struct uffdio_zeropage zero_struct; - zero_struct.range.start = (uint64_t)(uintptr_t)host_addr; - zero_struct.range.len = pagesize; - zero_struct.mode = 0; - ret = ioctl(userfault_fd, UFFDIO_ZEROPAGE, &zero_struct); + ret = uffd_zero_page(userfault_fd, host_addr, pagesize, false); } if (!ret) { qemu_mutex_lock(&mis->page_request_mutex); @@ -1343,18 +1327,16 @@ int postcopy_place_page(MigrationIncomingState *mis, void *host, void *from, RAMBlock *rb) { size_t pagesize = qemu_ram_pagesize(rb); + int e; /* copy also acks to the kernel waking the stalled thread up * TODO: We can inhibit that ack and only do it if it was requested * which would be slightly cheaper, but we'd have to be careful * of the order of updating our page state. */ - if (qemu_ufd_copy_ioctl(mis, host, from, pagesize, rb)) { - int e = errno; - error_report("%s: %s copy host: %p from: %p (size: %zd)", - __func__, strerror(e), host, from, pagesize); - - return -e; + e = qemu_ufd_copy_ioctl(mis, host, from, pagesize, rb); + if (e) { + return e; } trace_postcopy_place_page(host); @@ -1376,12 +1358,10 @@ int postcopy_place_page_zero(MigrationIncomingState *mis, void *host, * but it's not available for everything (e.g. hugetlbpages) */ if (qemu_ram_is_uf_zeroable(rb)) { - if (qemu_ufd_copy_ioctl(mis, host, NULL, pagesize, rb)) { - int e = errno; - error_report("%s: %s zero host: %p", - __func__, strerror(e), host); - - return -e; + int e; + e = qemu_ufd_copy_ioctl(mis, host, NULL, pagesize, rb); + if (e) { + return e; } return postcopy_notify_shared_wake(rb, qemu_ram_block_host_offset(rb, From ccf6b78275816c9dec84d3a40e9aa3b6ba6ebc06 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 19 Sep 2024 14:46:26 +0100 Subject: [PATCH 09/12] util/userfaultfd: Remove unused uffd_poll_events uffd_poll_events has been unused since it was added; it's also just a wrapper around a plain old poll call, so doesn't add anything. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Peter Xu Link: https://lore.kernel.org/r/20240919134626.166183-8-dave@treblig.org Signed-off-by: Peter Xu --- include/qemu/userfaultfd.h | 1 - util/userfaultfd.c | 28 ---------------------------- 2 files changed, 29 deletions(-) diff --git a/include/qemu/userfaultfd.h b/include/qemu/userfaultfd.h index 18a4314212..a1979308d7 100644 --- a/include/qemu/userfaultfd.h +++ b/include/qemu/userfaultfd.h @@ -39,7 +39,6 @@ int uffd_copy_page(int uffd_fd, void *dst_addr, void *src_addr, int uffd_zero_page(int uffd_fd, void *addr, uint64_t length, bool dont_wake); int uffd_wakeup(int uffd_fd, void *addr, uint64_t length); int uffd_read_events(int uffd_fd, struct uffd_msg *msgs, int count); -bool uffd_poll_events(int uffd_fd, int tmo); #endif /* CONFIG_LINUX */ diff --git a/util/userfaultfd.c b/util/userfaultfd.c index 518d5c3586..2396104f23 100644 --- a/util/userfaultfd.c +++ b/util/userfaultfd.c @@ -358,31 +358,3 @@ int uffd_read_events(int uffd_fd, struct uffd_msg *msgs, int count) return (int) (res / sizeof(struct uffd_msg)); } - -/** - * uffd_poll_events: poll UFFD file descriptor for read - * - * Returns true if events are available for read, false otherwise - * - * @uffd_fd: UFFD file descriptor - * @tmo: timeout value - */ -bool uffd_poll_events(int uffd_fd, int tmo) -{ - int res; - struct pollfd poll_fd = { .fd = uffd_fd, .events = POLLIN, .revents = 0 }; - - do { - res = poll(&poll_fd, 1, tmo); - } while (res < 0 && errno == EINTR); - - if (res == 0) { - return false; - } - if (res < 0) { - error_report("uffd_poll_events() failed: errno=%i", errno); - return false; - } - - return (poll_fd.revents & POLLIN) != 0; -} From 9adcdd49e39149b494b7b6174ef0b7f2d906845b Mon Sep 17 00:00:00 2001 From: Juraj Marcin Date: Fri, 20 Sep 2024 18:13:02 +0200 Subject: [PATCH 10/12] tests/migration-test: Wait for cancellation sooner in multifd cancel The source QEMU might not finish the cancellation of the migration before we start setting up the next attempt. During the setup, the test_migrate_start() function and others might need to interact with the source in a way that is not possible unless the migration is fully canceled. For example, setting capabilities when the migration is still running leads to an error. By moving the wait before the setup, we ensure this does not happen. Cc: Peter Xu Signed-off-by: Juraj Marcin Link: https://lore.kernel.org/r/20240920161319.2337625-1-jmarcin@redhat.com Signed-off-by: Peter Xu --- tests/qtest/migration-test.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 814ec109a6..95e45b5029 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -3267,6 +3267,16 @@ static void test_multifd_tcp_cancel(void) qtest_wait_qemu(to); qtest_quit(to); + /* + * Ensure the source QEMU finishes its cancellation process before we + * proceed with the setup of the next migration. The test_migrate_start() + * function and others might want to interact with the source in a way that + * is not possible while the migration is not canceled properly. For + * example, setting migration capabilities when the migration is still + * running leads to an error. + */ + wait_for_migration_status(from, "cancelled", NULL); + args = (MigrateStart){ .only_target = true, }; @@ -3282,8 +3292,6 @@ static void test_multifd_tcp_cancel(void) /* Start incoming migration from the 1st socket */ migrate_incoming_qmp(to2, "tcp:127.0.0.1:0", "{}"); - wait_for_migration_status(from, "cancelled", NULL); - migrate_ensure_non_converge(from); migrate_qmp(from, to2, NULL, NULL, "{}"); From 255db3ba80a985f11a9d7b2d2c0f014427ba4639 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 18 Sep 2024 15:25:15 +0100 Subject: [PATCH 11/12] util/iova-tree: Remove deadcode iova_tree_find_address, and iova_tree_foreach have never been used since the code was originally added by: eecf5eedbd ("util: implement simple iova tree") Remove them. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Peter Xu Reviewed-by: Thomas Huth Link: https://lore.kernel.org/r/20240918142515.153074-1-dave@treblig.org Signed-off-by: Peter Xu --- include/qemu/iova-tree.h | 25 ------------------------- util/iova-tree.c | 23 ----------------------- 2 files changed, 48 deletions(-) diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h index 2a10a7052e..44a45931d5 100644 --- a/include/qemu/iova-tree.h +++ b/include/qemu/iova-tree.h @@ -111,31 +111,6 @@ const DMAMap *iova_tree_find(const IOVATree *tree, const DMAMap *map); */ const DMAMap *iova_tree_find_iova(const IOVATree *tree, const DMAMap *map); -/** - * iova_tree_find_address: - * - * @tree: the iova tree to search from - * @iova: the iova address to find - * - * Similar to iova_tree_find(), but it tries to find mapping with - * range iova=iova & size=0. - * - * Return: same as iova_tree_find(). - */ -const DMAMap *iova_tree_find_address(const IOVATree *tree, hwaddr iova); - -/** - * iova_tree_foreach: - * - * @tree: the iova tree to iterate on - * @iterator: the iterator for the mappings, return true to stop - * - * Iterate over the iova tree. - * - * Return: 1 if found any overlap, 0 if not, <0 if error. - */ -void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator); - /** * iova_tree_alloc_map: * diff --git a/util/iova-tree.c b/util/iova-tree.c index 536789797e..06295e2755 100644 --- a/util/iova-tree.c +++ b/util/iova-tree.c @@ -115,13 +115,6 @@ const DMAMap *iova_tree_find_iova(const IOVATree *tree, const DMAMap *map) return args.result; } -const DMAMap *iova_tree_find_address(const IOVATree *tree, hwaddr iova) -{ - const DMAMap map = { .iova = iova, .size = 0 }; - - return iova_tree_find(tree, &map); -} - static inline void iova_tree_insert_internal(GTree *gtree, DMAMap *range) { /* Key and value are sharing the same range data */ @@ -148,22 +141,6 @@ int iova_tree_insert(IOVATree *tree, const DMAMap *map) return IOVA_OK; } -static gboolean iova_tree_traverse(gpointer key, gpointer value, - gpointer data) -{ - iova_tree_iterator iterator = data; - DMAMap *map = key; - - g_assert(key == value); - - return iterator(map); -} - -void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator) -{ - g_tree_foreach(tree->tree, iova_tree_traverse, iterator); -} - void iova_tree_remove(IOVATree *tree, DMAMap map) { const DMAMap *overlap; From 2e49d6a20b2193378e508b01de82eaffc5adc3bc Mon Sep 17 00:00:00 2001 From: Yuan Liu Date: Tue, 8 Oct 2024 18:45:27 +0800 Subject: [PATCH 12/12] migration/multifd: fix build error when qpl compression is enabled The page_size member has been removed from the MultiFDSendParams and MultiFDRecvParams. The function multifd_ram_page_size is used to provide the page size in the multifd compressor. Fixes: 90fa121c6c ("migration/multifd: Inline page_size and page_count") Signed-off-by: Yuan Liu Link: https://lore.kernel.org/r/20241008104527.3516755-1-yuan1.liu@intel.com Signed-off-by: Peter Xu --- migration/multifd-qpl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/migration/multifd-qpl.c b/migration/multifd-qpl.c index b0f1e2ba46..bbe466617f 100644 --- a/migration/multifd-qpl.c +++ b/migration/multifd-qpl.c @@ -389,7 +389,7 @@ static void multifd_qpl_compress_pages_slow_path(MultiFDSendParams *p) { QplData *qpl = p->compress_data; MultiFDPages_t *pages = &p->data->u.ram; - uint32_t size = p->page_size; + uint32_t size = multifd_ram_page_size(); qpl_job *job = qpl->sw_job; uint8_t *zbuf = qpl->zbuf; uint8_t *buf; @@ -420,7 +420,7 @@ static void multifd_qpl_compress_pages(MultiFDSendParams *p) { QplData *qpl = p->compress_data; MultiFDPages_t *pages = &p->data->u.ram; - uint32_t size = p->page_size; + uint32_t size = multifd_ram_page_size(); QplHwJob *hw_job; uint8_t *buf; uint8_t *zbuf; @@ -560,7 +560,7 @@ static int multifd_qpl_decompress_pages_slow_path(MultiFDRecvParams *p, Error **errp) { QplData *qpl = p->compress_data; - uint32_t size = p->page_size; + uint32_t size = multifd_ram_page_size(); qpl_job *job = qpl->sw_job; uint8_t *zbuf = qpl->zbuf; uint8_t *addr; @@ -598,7 +598,7 @@ static int multifd_qpl_decompress_pages_slow_path(MultiFDRecvParams *p, static int multifd_qpl_decompress_pages(MultiFDRecvParams *p, Error **errp) { QplData *qpl = p->compress_data; - uint32_t size = p->page_size; + uint32_t size = multifd_ram_page_size(); uint8_t *zbuf = qpl->zbuf; uint8_t *addr; uint32_t len; @@ -677,7 +677,7 @@ static int multifd_qpl_recv(MultiFDRecvParams *p, Error **errp) } for (int i = 0; i < p->normal_num; i++) { qpl->zlen[i] = be32_to_cpu(qpl->zlen[i]); - assert(qpl->zlen[i] <= p->page_size); + assert(qpl->zlen[i] <= multifd_ram_page_size()); zbuf_len += qpl->zlen[i]; }