[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 08/10] migration: Fix iocs leaks during file and fd migration
From: |
peterx |
Subject: |
[PULL 08/10] migration: Fix iocs leaks during file and fd migration |
Date: |
Sun, 17 Mar 2024 16:58:01 -0400 |
From: Fabiano Rosas <farosas@suse.de>
The memory for the io channels is being leaked in three different ways
during file migration:
1) if the offset check fails we never drop the ioc reference;
2) we allocate an extra channel for no reason;
3) if multifd is enabled but channel creation fails when calling
dup(), we leave the previous channels around along with the glib
polling;
Fix all issues by restructuring the code to first allocate the
channels and only register the watches when all channels have been
created.
For multifd, the file and fd migrations can share code because both
are backed by a QIOChannelFile. For the non-multifd case, the fd needs
to be separate because it is backed by a QIOChannelSocket.
Fixes: 2dd7ee7a51 ("migration/multifd: Add incoming QIOChannelFile support")
Fixes: decdc76772 ("migration/multifd: Add mapped-ram support to fd: URI")
Reported-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
Link: 20240313212824.16974-2-farosas@suse.de">https://lore.kernel.org/r/20240313212824.16974-2-farosas@suse.de
Signed-off-by: Peter Xu <peterx@redhat.com>
---
migration/file.h | 1 +
migration/fd.c | 29 +++++++-----------------
migration/file.c | 58 ++++++++++++++++++++++++++++++------------------
3 files changed, 46 insertions(+), 42 deletions(-)
diff --git a/migration/file.h b/migration/file.h
index 9f71e87f74..7699c04677 100644
--- a/migration/file.h
+++ b/migration/file.h
@@ -20,6 +20,7 @@ void file_start_outgoing_migration(MigrationState *s,
int file_parse_offset(char *filespec, uint64_t *offsetp, Error **errp);
void file_cleanup_outgoing_migration(void);
bool file_send_channel_create(gpointer opaque, Error **errp);
+void file_create_incoming_channels(QIOChannel *ioc, Error **errp);
int file_write_ramblock_iov(QIOChannel *ioc, const struct iovec *iov,
int niov, RAMBlock *block, Error **errp);
int multifd_file_recv_data(MultiFDRecvParams *p, Error **errp);
diff --git a/migration/fd.c b/migration/fd.c
index 4e2a63a73d..39a52e5c90 100644
--- a/migration/fd.c
+++ b/migration/fd.c
@@ -18,6 +18,7 @@
#include "qapi/error.h"
#include "channel.h"
#include "fd.h"
+#include "file.h"
#include "migration.h"
#include "monitor/monitor.h"
#include "io/channel-file.h"
@@ -80,7 +81,6 @@ static gboolean fd_accept_incoming_migration(QIOChannel *ioc,
void fd_start_incoming_migration(const char *fdname, Error **errp)
{
QIOChannel *ioc;
- QIOChannelFile *fioc;
int fd = monitor_fd_param(monitor_cur(), fdname, errp);
if (fd == -1) {
return;
@@ -94,26 +94,13 @@ void fd_start_incoming_migration(const char *fdname, Error
**errp)
return;
}
- qio_channel_set_name(ioc, "migration-fd-incoming");
- qio_channel_add_watch_full(ioc, G_IO_IN,
- fd_accept_incoming_migration,
- NULL, NULL,
- g_main_context_get_thread_default());
-
if (migrate_multifd()) {
- int channels = migrate_multifd_channels();
-
- while (channels--) {
- fioc = qio_channel_file_new_dupfd(fd, errp);
- if (!fioc) {
- return;
- }
-
- qio_channel_set_name(ioc, "migration-fd-incoming");
- qio_channel_add_watch_full(QIO_CHANNEL(fioc), G_IO_IN,
- fd_accept_incoming_migration,
- NULL, NULL,
- g_main_context_get_thread_default());
- }
+ file_create_incoming_channels(ioc, errp);
+ } else {
+ qio_channel_set_name(ioc, "migration-fd-incoming");
+ qio_channel_add_watch_full(ioc, G_IO_IN,
+ fd_accept_incoming_migration,
+ NULL, NULL,
+ g_main_context_get_thread_default());
}
}
diff --git a/migration/file.c b/migration/file.c
index e56c5eb0a5..ddde0ca818 100644
--- a/migration/file.c
+++ b/migration/file.c
@@ -115,13 +115,46 @@ static gboolean file_accept_incoming_migration(QIOChannel
*ioc,
return G_SOURCE_REMOVE;
}
+void file_create_incoming_channels(QIOChannel *ioc, Error **errp)
+{
+ int i, fd, channels = 1;
+ g_autofree QIOChannel **iocs = NULL;
+
+ if (migrate_multifd()) {
+ channels += migrate_multifd_channels();
+ }
+
+ iocs = g_new0(QIOChannel *, channels);
+ fd = QIO_CHANNEL_FILE(ioc)->fd;
+ iocs[0] = ioc;
+
+ for (i = 1; i < channels; i++) {
+ QIOChannelFile *fioc = qio_channel_file_new_dupfd(fd, errp);
+
+ if (!fioc) {
+ while (i) {
+ object_unref(iocs[--i]);
+ }
+ return;
+ }
+
+ iocs[i] = QIO_CHANNEL(fioc);
+ }
+
+ for (i = 0; i < channels; i++) {
+ qio_channel_set_name(iocs[i], "migration-file-incoming");
+ qio_channel_add_watch_full(iocs[i], G_IO_IN,
+ file_accept_incoming_migration,
+ NULL, NULL,
+ g_main_context_get_thread_default());
+ }
+}
+
void file_start_incoming_migration(FileMigrationArgs *file_args, Error **errp)
{
g_autofree char *filename = g_strdup(file_args->filename);
QIOChannelFile *fioc = NULL;
uint64_t offset = file_args->offset;
- int channels = 1;
- int i = 0;
trace_migration_file_incoming(filename);
@@ -132,28 +165,11 @@ void file_start_incoming_migration(FileMigrationArgs
*file_args, Error **errp)
if (offset &&
qio_channel_io_seek(QIO_CHANNEL(fioc), offset, SEEK_SET, errp) < 0) {
+ object_unref(OBJECT(fioc));
return;
}
- if (migrate_multifd()) {
- channels += migrate_multifd_channels();
- }
-
- do {
- QIOChannel *ioc = QIO_CHANNEL(fioc);
-
- qio_channel_set_name(ioc, "migration-file-incoming");
- qio_channel_add_watch_full(ioc, G_IO_IN,
- file_accept_incoming_migration,
- NULL, NULL,
- g_main_context_get_thread_default());
-
- fioc = qio_channel_file_new_dupfd(fioc->fd, errp);
-
- if (!fioc) {
- break;
- }
- } while (++i < channels);
+ file_create_incoming_channels(QIO_CHANNEL(fioc), errp);
}
int file_write_ramblock_iov(QIOChannel *ioc, const struct iovec *iov,
--
2.44.0
- [PULL 00/10] Migration 20240317 patches, peterx, 2024/03/17
- [PULL 01/10] io: Introduce qio_channel_file_new_dupfd, peterx, 2024/03/17
- [PULL 02/10] migration: Fix error handling after dup in file migration, peterx, 2024/03/17
- [PULL 03/10] physmem: Expose tlb_reset_dirty_range_all(), peterx, 2024/03/17
- [PULL 04/10] physmem: Factor cpu_physical_memory_dirty_bits_cleared() out, peterx, 2024/03/17
- [PULL 05/10] physmem: Fix migration dirty bitmap coherency with TCG memory access, peterx, 2024/03/17
- [PULL 06/10] migration: Skip only empty block devices, peterx, 2024/03/17
- [PULL 07/10] migration: cpr-reboot documentation, peterx, 2024/03/17
- [PULL 09/10] migration/multifd: Ensure we're not given a socket for file migration, peterx, 2024/03/17
- [PULL 08/10] migration: Fix iocs leaks during file and fd migration,
peterx <=
- [PULL 10/10] migration/multifd: Duplicate the fd for the outgoing_args, peterx, 2024/03/17
- Re: [PULL 00/10] Migration 20240317 patches, Peter Maydell, 2024/03/19