diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index a160c9a44b..3f1aed8595 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1,7 +1,7 @@ /* * qemu_monitor.c: interaction with QEMU monitor console * - * Copyright (C) 2006-2012 Red Hat, Inc. + * Copyright (C) 2006-2013 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -2353,6 +2353,78 @@ cleanup: } +/* Add the open file descriptor FD into the non-negative set FDSET. + * If NAME is present, it will be passed along for logging purposes. + * Returns the counterpart fd that qemu received, or -1 on error. */ +int +qemuMonitorAddFd(qemuMonitorPtr mon, int fdset, int fd, const char *name) +{ + int ret = -1; + VIR_DEBUG("mon=%p, fdset=%d, fd=%d, name=%s", + mon, fdset, fd, NULLSTR(name)); + + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + + if (fd < 0 || fdset < 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("fd and fdset must be valid")); + return -1; + } + + if (!mon->hasSendFD) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, + _("qemu is not using a unix socket monitor, " + "cannot send fd %s"), NULLSTR(name)); + return -1; + } + + if (mon->json) + ret = qemuMonitorJSONAddFd(mon, fdset, fd, name); + else + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("add fd requires JSON monitor")); + return ret; +} + + +/* Remove one of qemu's fds from the given FDSET, or if FD is + * negative, remove the entire set. Preserve any previous error on + * entry. Returns 0 on success, -1 on error. */ +int +qemuMonitorRemoveFd(qemuMonitorPtr mon, int fdset, int fd) +{ + int ret = -1; + virErrorPtr error; + + VIR_DEBUG("mon=%p, fdset=%d, fd=%d", mon, fdset, fd); + + error = virSaveLastError(); + + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + goto cleanup; + } + + if (mon->json) + ret = qemuMonitorJSONRemoveFd(mon, fdset, fd); + else + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("remove fd requires JSON monitor")); + +cleanup: + if (error) { + virSetError(error); + virFreeError(error); + } + return ret; +} + + int qemuMonitorAddHostNetwork(qemuMonitorPtr mon, const char *netstr, int tapfd, const char *tapfd_name, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 7953b8201f..ac77158ecc 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1,7 +1,7 @@ /* * qemu_monitor.h: interaction with QEMU monitor console * - * Copyright (C) 2006-2012 Red Hat, Inc. + * Copyright (C) 2006-2013 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -439,13 +439,14 @@ int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon, int qemuMonitorSendFileHandle(qemuMonitorPtr mon, const char *fdname, int fd); +int qemuMonitorAddFd(qemuMonitorPtr mon, int fdset, int fd, const char *name); -/* The function preserves previous error and only sets it's own error if no - * error was set before. +/* These two functions preserve previous error and only set their own + * error if no error was set before. */ int qemuMonitorCloseFileHandle(qemuMonitorPtr mon, const char *fdname); - +int qemuMonitorRemoveFd(qemuMonitorPtr mon, int fdset, int fd); /* XXX do we really want to hardcode 'netstr' as the * sendable item here diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 2d2a5d0450..686cee9adf 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1,7 +1,7 @@ /* * qemu_monitor_json.c: interaction with QEMU monitor console * - * Copyright (C) 2006-2012 Red Hat, Inc. + * Copyright (C) 2006-2013 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -2646,6 +2646,77 @@ int qemuMonitorJSONCloseFileHandle(qemuMonitorPtr mon, } +int +qemuMonitorJSONAddFd(qemuMonitorPtr mon, int fdset, int fd, const char *name) +{ + int ret; + virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("add-fd", + "i:fdset-id", fdset, + name ? "s:opaque" : NULL, + name, NULL); + virJSONValuePtr reply = NULL; + if (!cmd) + return -1; + + ret = qemuMonitorJSONCommandWithFd(mon, cmd, fd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + if (ret == 0) { + virJSONValuePtr data = virJSONValueObjectGet(reply, "return"); + + if (!data || data->type != VIR_JSON_TYPE_OBJECT) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing return information")); + goto error; + } + data = virJSONValueObjectGet(data, "fd"); + if (!data || data->type != VIR_JSON_TYPE_NUMBER || + virJSONValueGetNumberInt(data, &ret) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("incomplete return information")); + goto error; + } + } + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; + +error: + /* Best effort cleanup - kill the entire fdset (even if it has + * earlier successful fd registrations), since we don't know which + * fd qemu got, and don't want to leave the fd leaked in qemu. */ + qemuMonitorJSONRemoveFd(mon, fdset, -1); + ret = -1; + goto cleanup; +} + + +int +qemuMonitorJSONRemoveFd(qemuMonitorPtr mon, int fdset, int fd) +{ + int ret; + virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("remove-fd", + "i:fdset-id", fdset, + fd < 0 ? NULL : "i:fd", + fd, NULL); + virJSONValuePtr reply = NULL; + if (!cmd) + return -1; + + ret = qemuMonitorJSONCommand(mon, cmd, &reply); + + if (ret == 0) + ret = qemuMonitorJSONCheckError(cmd, reply); + + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + + int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon, const char *netdevstr) { diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 2b09a8f340..925d937cbc 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -1,7 +1,7 @@ /* * qemu_monitor_json.h: interaction with QEMU monitor console * - * Copyright (C) 2006-2009, 2011-2012 Red Hat, Inc. + * Copyright (C) 2006-2009, 2011-2013 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -175,9 +175,12 @@ int qemuMonitorJSONRemovePCIDevice(qemuMonitorPtr mon, int qemuMonitorJSONSendFileHandle(qemuMonitorPtr mon, const char *fdname, int fd); +int qemuMonitorJSONAddFd(qemuMonitorPtr mon, int fdset, int fd, + const char *name); int qemuMonitorJSONCloseFileHandle(qemuMonitorPtr mon, const char *fdname); +int qemuMonitorJSONRemoveFd(qemuMonitorPtr mon, int fdset, int fd); int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon, const char *netdevstr);