diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2024-10-09 20:12:11 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2024-10-09 20:12:11 +0100 |
commit | 05adb38839ba656c7383a548b460d95c91e2febe (patch) | |
tree | 43a8616f6267c89a03991baabbb4a1699dc66a11 | |
parent | 838fc0a8769d7cc6edfe50451ba4e3368395f5c1 (diff) | |
parent | 2e49d6a20b2193378e508b01de82eaffc5adc3bc (diff) | |
download | qemu-05adb38839ba656c7383a548b460d95c91e2febe.zip qemu-05adb38839ba656c7383a548b460d95c91e2febe.tar.gz qemu-05adb38839ba656c7383a548b460d95c91e2febe.tar.bz2 |
Merge tag 'migration-20241009-pull-request' of https://gitlab.com/peterx/qemu into staging
Migration pull request
- Ani's patch to complete the memory API on coalesced IO / eventfd notifies
- Fabiano's Coverity fix on using pstrcpy() over strncpy()
- Dave's series on removing/deprecating zero-blocks and uffd cleanups
- Juraj's one more fix on multifd/cancel test where it can fail when
cancellation happens too slow on src
- Dave's one more remove deadcode patch in iova-tree.c
- Yuan's build fix for multifd qpl compressor
# -----BEGIN PGP SIGNATURE-----
#
# iIgEABYKADAWIQS5GE3CDMRX2s990ak7X8zN86vXBgUCZwZ6CBIccGV0ZXJ4QHJl
# ZGhhdC5jb20ACgkQO1/MzfOr1wa3ZwD9HiAN9m7WOfZxXKOVIIwhOjUNTw0FiFeO
# HMxp8A2jeYsBAK+d5lYGX1V2FtQ152YiOJQzRW31MkdAOishJzcHCXgO
# =gBW0
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 09 Oct 2024 13:41:44 BST
# gpg: using EDDSA key B9184DC20CC457DACF7DD1A93B5FCCCDF3ABD706
# gpg: issuer "peterx@redhat.com"
# gpg: Good signature from "Peter Xu <xzpeter@gmail.com>" [marginal]
# gpg: aka "Peter Xu <peterx@redhat.com>" [marginal]
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg: It is not certain that the signature belongs to the owner.
# Primary key fingerprint: B918 4DC2 0CC4 57DA CF7D D1A9 3B5F CCCD F3AB D706
* tag 'migration-20241009-pull-request' of https://gitlab.com/peterx/qemu:
migration/multifd: fix build error when qpl compression is enabled
util/iova-tree: Remove deadcode
tests/migration-test: Wait for cancellation sooner in multifd cancel
util/userfaultfd: Remove unused uffd_poll_events
migration/postcopy: Use uffd helpers
util/userfaultfd: Return -errno on error
migration: Remove unused socket_send_channel_create_sync
migration: Deprecate zero-blocks capability
migration: Remove unused migrate_zero_blocks
migration: Remove migrate_cap_set
migration/multifd: Ensure packet->ramblock is null-terminated
memory: notify hypervisor of all eventfds during listener (de)registration
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | docs/about/deprecated.rst | 6 | ||||
-rw-r--r-- | include/qemu/iova-tree.h | 25 | ||||
-rw-r--r-- | include/qemu/userfaultfd.h | 1 | ||||
-rw-r--r-- | migration/multifd-nocomp.c | 4 | ||||
-rw-r--r-- | migration/multifd-qpl.c | 10 | ||||
-rw-r--r-- | migration/options.c | 31 | ||||
-rw-r--r-- | migration/options.h | 2 | ||||
-rw-r--r-- | migration/postcopy-ram.c | 48 | ||||
-rw-r--r-- | migration/socket.c | 18 | ||||
-rw-r--r-- | migration/socket.h | 1 | ||||
-rw-r--r-- | qapi/migration.json | 5 | ||||
-rw-r--r-- | system/memory.c | 83 | ||||
-rw-r--r-- | tests/qtest/migration-test.c | 12 | ||||
-rw-r--r-- | util/iova-tree.c | 23 | ||||
-rw-r--r-- | util/userfaultfd.c | 49 |
15 files changed, 141 insertions, 177 deletions
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 82bb492..ce38a3d 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -473,3 +473,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/include/qemu/iova-tree.h b/include/qemu/iova-tree.h index 2a10a70..44a4593 100644 --- a/include/qemu/iova-tree.h +++ b/include/qemu/iova-tree.h @@ -112,31 +112,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: * * @tree: the iova tree to allocate from diff --git a/include/qemu/userfaultfd.h b/include/qemu/userfaultfd.h index 18a4314..a197930 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/migration/multifd-nocomp.c b/migration/multifd-nocomp.c index 07c63f4..5519115 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++) { diff --git a/migration/multifd-qpl.c b/migration/multifd-qpl.c index b0f1e2b..bbe4666 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]; } diff --git a/migration/options.c b/migration/options.c index 147cd2b..ad8d698 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(); @@ -457,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" @@ -605,26 +602,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 a0bd6ed..79084ee 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); /* @@ -58,7 +57,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 */ diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 0fe9d83..83f6160 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, diff --git a/migration/socket.c b/migration/socket.c index 9ab89b1..5ec65b8 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 46c233e..04ebbe9 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); diff --git a/qapi/migration.json b/qapi/migration.json index b66cccf..3af6aa1 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', diff --git a/system/memory.c b/system/memory.c index f6f6fee..85f6834 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); } diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 814ec10..95e45b5 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, "{}"); diff --git a/util/iova-tree.c b/util/iova-tree.c index 5367897..06295e2 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; diff --git a/util/userfaultfd.c b/util/userfaultfd.c index 1b2fa94..2396104 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; @@ -355,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; -} |