Add helpers to create and retrieve Live Update Orchestrator (LUO) sessions.
The LUO API is available only on Linux. Provide error stubs on other hosts. Signed-off-by: Dongli Zhang <[email protected]> --- include/migration/cpr.h | 3 ++ migration/cpr-luo-stub.c | 26 ++++++++++++++ migration/cpr-luo.c | 74 ++++++++++++++++++++++++++++++++++++++++ migration/meson.build | 6 ++++ 4 files changed, 109 insertions(+) create mode 100644 migration/cpr-luo-stub.c create mode 100644 migration/cpr-luo.c diff --git a/include/migration/cpr.h b/include/migration/cpr.h index e33eaf588b..f8b161b3d6 100644 --- a/include/migration/cpr.h +++ b/include/migration/cpr.h @@ -74,4 +74,7 @@ bool cpr_exec_persist_state(QEMUFile *f, Error **errp); bool cpr_exec_has_state(void); void cpr_exec_unpersist_state(void); void cpr_exec_unpreserve_fds(void); + +int cpr_luo_create_session(const char *name, Error **errp); +int cpr_luo_retrieve_session(const char *name, Error **errp); #endif diff --git a/migration/cpr-luo-stub.c b/migration/cpr-luo-stub.c new file mode 100644 index 0000000000..ca060ae8c8 --- /dev/null +++ b/migration/cpr-luo-stub.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2026 Oracle and/or its affiliates. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include "migration/cpr.h" +#include "qapi/error.h" + +static int cpr_luo_unsupported(Error **errp) +{ + error_setg(errp, "cpr-luo requires Linux"); + return -1; +} + +int cpr_luo_create_session(const char *name, Error **errp) +{ + return cpr_luo_unsupported(errp); +} + +int cpr_luo_retrieve_session(const char *name, Error **errp) +{ + return cpr_luo_unsupported(errp); +} diff --git a/migration/cpr-luo.c b/migration/cpr-luo.c new file mode 100644 index 0000000000..48288ed5f9 --- /dev/null +++ b/migration/cpr-luo.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2026 Oracle and/or its affiliates. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" + +#include <sys/ioctl.h> + +#include "linux-headers/linux/liveupdate.h" +#include "migration/cpr.h" +#include "qapi/error.h" + +static int luo_open(Error **errp) +{ + return qemu_open("/dev/liveupdate", O_RDWR, errp); +} + +int cpr_luo_create_session(const char *name, Error **errp) +{ + struct liveupdate_ioctl_create_session create = { 0 }; + int fd; + + if (g_strlcpy((char *)create.name, name, sizeof(create.name)) >= + sizeof(create.name)) { + error_setg(errp, "LUO session name is too long"); + return -1; + } + + fd = luo_open(errp); + if (fd < 0) { + return -1; + } + + create.size = sizeof(create); + if (ioctl(fd, LIVEUPDATE_IOCTL_CREATE_SESSION, &create) < 0) { + error_setg_errno(errp, errno, "failed to create LUO session '%s'", + (char *)create.name); + close(fd); + return -1; + } + + close(fd); + return create.fd; +} + +int cpr_luo_retrieve_session(const char *name, Error **errp) +{ + struct liveupdate_ioctl_retrieve_session retrieve = { 0 }; + int fd; + + if (g_strlcpy((char *)retrieve.name, name, sizeof(retrieve.name)) >= + sizeof(retrieve.name)) { + error_setg(errp, "LUO session name is too long"); + return -1; + } + + fd = luo_open(errp); + if (fd < 0) { + return -1; + } + + retrieve.size = sizeof(retrieve); + if (ioctl(fd, LIVEUPDATE_IOCTL_RETRIEVE_SESSION, &retrieve) < 0) { + error_setg_errno(errp, errno, "failed to retrieve LUO session '%s'", + (char *)retrieve.name); + close(fd); + return -1; + } + + close(fd); + return retrieve.fd; +} diff --git a/migration/meson.build b/migration/meson.build index 4ab9d99cea..a6363c2bf7 100644 --- a/migration/meson.build +++ b/migration/meson.build @@ -54,3 +54,9 @@ system_ss.add(when: qatzip, if_true: files('multifd-qatzip.c')) system_ss.add(when: 'CONFIG_VFIO', if_true: files('vfio.c')) stub_ss.add(files('vfio-stub.c')) + +if host_os == 'linux' + system_ss.add(files('cpr-luo.c')) +else + system_ss.add(files('cpr-luo-stub.c')) +endif -- 2.43.5
