Add helpers for creating an outgoing memfd-backed migration channel and for wrapping an existing memfd fd as an incoming migration channel. The outgoing helper can optionally duplicate the memfd fd for the caller.
Signed-off-by: Dongli Zhang <[email protected]> --- migration/memfd.c | 67 +++++++++++++++++++++++++++++++++++++++++++ migration/memfd.h | 17 +++++++++++ migration/meson.build | 1 + 3 files changed, 85 insertions(+) create mode 100644 migration/memfd.c create mode 100644 migration/memfd.h diff --git a/migration/memfd.c b/migration/memfd.c new file mode 100644 index 0000000000..0b5ef0234f --- /dev/null +++ b/migration/memfd.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * QEMU live migration via memfd + * + * Copyright (c) 2026 Oracle and/or its affiliates. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/cutils.h" +#include "qemu/memfd.h" +#include "memfd.h" + +QIOChannel *memfd_create_outgoing(const char *name, int *dup_fdp, + Error **errp) +{ + QIOChannelFile *fioc; + QIOChannel *ioc; + int fd; + +#ifdef CONFIG_LINUX + fd = qemu_memfd_create(name, 0, false, 0, 0, errp); +#else + fd = -1; + error_setg(errp, "memfd migration is only supported on Linux"); +#endif + + if (fd < 0) { + return NULL; + } + + if (dup_fdp) { + int dup_fd = dup(fd); + + if (dup_fd < 0) { + error_setg_errno(errp, errno, + "failed to duplicate memfd migration fd"); + close(fd); + return NULL; + } + + qemu_set_cloexec(dup_fd); + *dup_fdp = dup_fd; + } + + fioc = qio_channel_file_new_fd(fd); + ioc = QIO_CHANNEL(fioc); + qio_channel_set_name(ioc, name); + return ioc; +} + +QIOChannel *memfd_open_incoming(int fd, const char *name, Error **errp) +{ + QIOChannelFile *fioc; + QIOChannel *ioc; + + if (lseek(fd, 0, SEEK_SET) < 0) { + error_setg_errno(errp, errno, "failed to rewind memfd migration fd"); + close(fd); + return NULL; + } + + fioc = qio_channel_file_new_fd(fd); + ioc = QIO_CHANNEL(fioc); + qio_channel_set_name(ioc, name); + return ioc; +} diff --git a/migration/memfd.h b/migration/memfd.h new file mode 100644 index 0000000000..cb6afe3eeb --- /dev/null +++ b/migration/memfd.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * QEMU live migration via memfd + * + * Copyright (c) 2026 Oracle and/or its affiliates. + */ + +#ifndef QEMU_MIGRATION_MEMFD_H +#define QEMU_MIGRATION_MEMFD_H + +#include "io/channel-file.h" + +QIOChannel *memfd_create_outgoing(const char *name, int *dup_fdp, + Error **errp); +QIOChannel *memfd_open_incoming(int fd, const char *name, Error **errp); + +#endif diff --git a/migration/meson.build b/migration/meson.build index 0a9a5d0d37..1d852b8c6d 100644 --- a/migration/meson.build +++ b/migration/meson.build @@ -23,6 +23,7 @@ system_ss.add(files( 'fd.c', 'file.c', 'global_state.c', + 'memfd.c', 'migration.c', 'multifd.c', 'multifd-device-state.c', -- 2.43.5
