diff --git a/src/qemu/qemu_fd.c b/src/qemu/qemu_fd.c index 4641122d1f..baa16fd669 100644 --- a/src/qemu/qemu_fd.c +++ b/src/qemu/qemu_fd.c @@ -324,3 +324,132 @@ qemuFDPassGetPath(qemuFDPass *fdpass) return fdpass->path; } + + +struct _qemuFDPassDirect { + int fd; + char *path; + char *name; + + bool passed; /* passed to qemu via monitor */ +}; + + +void +qemuFDPassDirectFree(qemuFDPassDirect *fdpass) +{ + + if (!fdpass) + return; + + VIR_FORCE_CLOSE(fdpass->fd); + g_free(fdpass->name); + g_free(fdpass->path); + g_free(fdpass); +} + + +/** + * qemuFDPassDirectNew: + * @name: Name of the fd (for monitor passing use-case) + * @fd: The FD, cleared when passed. + * + * The qemuFDPassDirect helper returned by this helper is used to hold a FD + * passed to qemu either direcly via FD number when used on commandline or the + * 'getfd' QMP command. + */ +qemuFDPassDirect * +qemuFDPassDirectNew(const char *name, + int *fd) +{ + qemuFDPassDirect *fdpass = g_new0(qemuFDPassDirect, 1); + + fdpass->name = g_strdup(name); + fdpass->fd = *fd; + *fd = -1; + + return fdpass; +} + + +/** + * qemuFDPassDirectTransferCommand: + * @fdpass: The fd passing helper struct + * @cmd: Command to pass the filedescriptors to + * + * Pass the fds in @fdpass to a commandline object @cmd. @fdpass may be NULL + * in which case this is a no-op. + */ +void +qemuFDPassDirectTransferCommand(qemuFDPassDirect *fdpass, + virCommand *cmd) +{ + if (!fdpass) + return; + + virCommandPassFD(cmd, fdpass->fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT); + fdpass->path = g_strdup_printf("%d", fdpass->fd); + fdpass->fd = -1; +} + + +/** + * qemuFDPassDirectTransferMonitor: + * @fdpass: The fd passing helper struct + * @mon: monitor object + * + * Pass the fds in @fdpass to qemu via the monitor. @fdpass may be NULL + * in which case this is a no-op. Caller needs to enter the monitor context. + */ +int +qemuFDPassDirectTransferMonitor(qemuFDPassDirect *fdpass, + qemuMonitor *mon) +{ + if (!fdpass) + return 0; + + if (qemuMonitorSendFileHandle(mon, fdpass->name, fdpass->fd) < 0) + return -1; + + fdpass->path = g_strdup(fdpass->name); + VIR_FORCE_CLOSE(fdpass->fd); + fdpass->passed = true; + + return 0; +} + + +/** + * qemuFDPassDirectTransferMonitorRollback: + * @fdpass: The fd passing helper struct + * @mon: monitor object + * + * Rolls back the addition of @fdpass to @mon if it was added originally. + */ +void +qemuFDPassDirectTransferMonitorRollback(qemuFDPassDirect *fdpass, + qemuMonitor *mon) +{ + if (!fdpass || !fdpass->passed) + return; + + ignore_value(qemuMonitorCloseFileHandle(mon, fdpass->name)); +} + + +/** + * qemuFDPassDirectGetPath: + * @fdpass: The fd passing helper struct + * + * Returns the path/fd name that is used in qemu to refer to the passed FD. + * Note that it's only valid to call this function after @fdpass was already + * transferred to the command or monitor. + */ +const char * +qemuFDPassDirectGetPath(qemuFDPassDirect *fdpass) +{ + if (!fdpass) + return NULL; + + return fdpass->path; +} diff --git a/src/qemu/qemu_fd.h b/src/qemu/qemu_fd.h index d078d4ce5d..dbb4ab0aa5 100644 --- a/src/qemu/qemu_fd.h +++ b/src/qemu/qemu_fd.h @@ -53,3 +53,25 @@ qemuFDPassTransferMonitorRollback(qemuFDPass *fdpass, const char * qemuFDPassGetPath(qemuFDPass *fdpass); + + +typedef struct _qemuFDPassDirect qemuFDPassDirect; + +void +qemuFDPassDirectFree(qemuFDPassDirect *fdpass); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuFDPassDirect, qemuFDPassDirectFree); + +qemuFDPassDirect * +qemuFDPassDirectNew(const char *name, + int *fd); +void +qemuFDPassDirectTransferCommand(qemuFDPassDirect *fdpass, + virCommand *cmd); +int +qemuFDPassDirectTransferMonitor(qemuFDPassDirect *fdpass, + qemuMonitor *mon); +void +qemuFDPassDirectTransferMonitorRollback(qemuFDPassDirect *fdpass, + qemuMonitor *mon); +const char * +qemuFDPassDirectGetPath(qemuFDPassDirect *fdpass);