Add the helper function cpr_get_fd_param, to use when preserving a file descriptor that is opened externally and passed to QEMU. cpr_get_fd_param returns a descriptor number either from a QEMU command-line parameter, from a getfd command, or from CPR state.
When a descriptor is passed to new QEMU via SCM_RIGHTS, its number changes. Hence, during CPR, the command-line parameter is ignored in new QEMU, and over-ridden by the value found in CPR state. Similarly, if the descriptor was originally specified by a getfd command in old QEMU, the fd number is not known outside of QEMU, and it changes when sent to new QEMU via SCM_RIGHTS. Hence the user cannot send getfd to new QEMU, but when the user sends a hotplug command that references the fd, cpr_get_fd_param finds its value in CPR state. Signed-off-by: Steve Sistare <steven.sist...@oracle.com> --- include/migration/cpr.h | 2 ++ migration/cpr.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/include/migration/cpr.h b/include/migration/cpr.h index c5c191d..23d0af4 100644 --- a/include/migration/cpr.h +++ b/include/migration/cpr.h @@ -33,6 +33,8 @@ struct QIOChannel *cpr_state_ioc(void); bool cpr_needed_for_reuse(void *opaque); void cpr_kvm_close(void); +int cpr_get_fd_param(const char *name, const char *fdname, int index, + bool *reused, Error **errp); void cpr_transfer_init(void); QEMUFile *cpr_transfer_output(MigrationChannel *channel, Error **errp); diff --git a/migration/cpr.c b/migration/cpr.c index 351e12d..c903b24 100644 --- a/migration/cpr.c +++ b/migration/cpr.c @@ -14,6 +14,7 @@ #include "migration/qemu-file.h" #include "migration/savevm.h" #include "migration/vmstate.h" +#include "monitor/monitor.h" #include "system/kvm.h" #include "system/runstate.h" #include "trace.h" @@ -274,3 +275,42 @@ void cpr_kvm_close(void) kvm_close(); vfio_kvm_device_close(); } + +/* + * cpr_get_fd_param: find a descriptor and return its value. + * + * @name: CPR name for the descriptor + * @fdname: An integer-valued string, or a name passed to a getfd command + * @index: CPR index of the descriptor + * @reused: returns true if the fd is found in CPR state, else false. + * @errp: returned error message + * + * If CPR is not being performed, then use @fdname to find the fd. + * If CPR is being performed, then ignore @fdname, and look for @name + * and @index in CPR state. + * + * On success returns the fd value, else returns -1. + */ +int cpr_get_fd_param(const char *name, const char *fdname, int index, + bool *reused, Error **errp) +{ + ERRP_GUARD(); + int fd; + + if (cpr_is_incoming()) { + fd = cpr_find_fd(name, index); + if (fd < 0) { + error_setg(errp, "cannot find saved value for fd %s", fdname); + } + *reused = true; + } else { + fd = monitor_fd_param(monitor_cur(), fdname, errp); + if (fd >= 0) { + cpr_save_fd(name, index, fd); + } else { + error_prepend(errp, "Could not parse object fd %s:", fdname); + } + *reused = false; + } + return fd; +} -- 1.8.3.1