2009-10-09 18:07:55 +00:00
|
|
|
/*
|
|
|
|
* qemu_monitor.c: interaction with QEMU monitor console
|
|
|
|
*
|
2015-03-13 16:05:32 +00:00
|
|
|
* Copyright (C) 2006-2015 Red Hat, Inc.
|
2009-10-09 18:07:55 +00:00
|
|
|
* Copyright (C) 2006 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2009-10-09 18:07:55 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <poll.h>
|
2013-05-30 20:51:58 +00:00
|
|
|
#include <sys/socket.h>
|
2009-10-09 18:07:55 +00:00
|
|
|
#include <sys/un.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include "qemu_monitor.h"
|
2009-10-09 20:13:06 +00:00
|
|
|
#include "qemu_monitor_text.h"
|
2009-11-03 18:59:18 +00:00
|
|
|
#include "qemu_monitor_json.h"
|
2013-09-18 14:17:39 +00:00
|
|
|
#include "qemu_domain.h"
|
|
|
|
#include "qemu_process.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2012-09-24 16:54:51 +00:00
|
|
|
#include "virprocess.h"
|
2012-07-11 13:35:47 +00:00
|
|
|
#include "virobject.h"
|
2014-02-27 13:41:11 +00:00
|
|
|
#include "virprobe.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2016-04-08 11:11:10 +00:00
|
|
|
#include "virtime.h"
|
2009-10-09 18:07:55 +00:00
|
|
|
|
2012-04-02 17:24:29 +00:00
|
|
|
#ifdef WITH_DTRACE_PROBES
|
|
|
|
# include "libvirt_qemu_probes.h"
|
|
|
|
#endif
|
|
|
|
|
2018-12-13 14:53:50 +00:00
|
|
|
#define LIBVIRT_QEMU_MONITOR_PRIV_H_ALLOW
|
2018-05-04 14:26:08 +00:00
|
|
|
#include "qemu_monitor_priv.h"
|
|
|
|
|
2009-10-09 18:07:55 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_QEMU
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("qemu.qemu_monitor");
|
|
|
|
|
2010-03-22 18:44:58 +00:00
|
|
|
#define DEBUG_IO 0
|
|
|
|
#define DEBUG_RAW_IO 0
|
2009-12-08 18:05:02 +00:00
|
|
|
|
2018-01-16 17:00:11 +00:00
|
|
|
/* We read from QEMU until seeing a \r\n pair to indicate a
|
|
|
|
* completed reply or event. To avoid memory denial-of-service
|
|
|
|
* though, we must have a size limit on amount of data we
|
|
|
|
* buffer. 10 MB is large enough that it ought to cope with
|
|
|
|
* normal QEMU replies, and small enough that we're not
|
|
|
|
* consuming unreasonable mem.
|
|
|
|
*/
|
|
|
|
#define QEMU_MONITOR_MAX_RESPONSE (10 * 1024 * 1024)
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
struct _qemuMonitor {
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectLockable parent;
|
2012-07-11 13:35:47 +00:00
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
virCond notify;
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
int fd;
|
2017-06-07 08:46:40 +00:00
|
|
|
|
|
|
|
/* Represents the watch number to be used for updating and
|
|
|
|
* unregistering the monitor @fd for events in the event loop:
|
|
|
|
* > 0: valid watch number
|
|
|
|
* = 0: not registered
|
|
|
|
* < 0: an error occurred during the registration of @fd */
|
2009-10-09 19:13:29 +00:00
|
|
|
int watch;
|
|
|
|
int hasSendFD;
|
|
|
|
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
|
2009-10-15 17:56:52 +00:00
|
|
|
qemuMonitorCallbacksPtr cb;
|
2013-07-25 17:26:15 +00:00
|
|
|
void *callbackOpaque;
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
|
|
|
|
/* If there's a command being processed this will be
|
|
|
|
* non-NULL */
|
|
|
|
qemuMonitorMessagePtr msg;
|
|
|
|
|
|
|
|
/* Buffer incoming data ready for Text/QMP monitor
|
|
|
|
* code to process & find message boundaries */
|
|
|
|
size_t bufferOffset;
|
|
|
|
size_t bufferLength;
|
|
|
|
char *buffer;
|
|
|
|
|
|
|
|
/* If anything went wrong, this will be fed back
|
|
|
|
* the next monitor msg */
|
2011-05-29 12:51:08 +00:00
|
|
|
virError lastError;
|
|
|
|
|
|
|
|
int nextSerial;
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
|
2013-04-26 02:32:41 +00:00
|
|
|
bool waitGreeting;
|
2013-04-26 17:13:45 +00:00
|
|
|
|
|
|
|
/* cache of query-command-line-options results */
|
|
|
|
virJSONValuePtr options;
|
2013-06-27 15:00:31 +00:00
|
|
|
|
|
|
|
/* If found, path to the virtio memballoon driver */
|
|
|
|
char *balloonpath;
|
|
|
|
bool ballooninit;
|
2013-09-18 14:12:17 +00:00
|
|
|
|
2015-11-12 13:54:04 +00:00
|
|
|
/* Log file context of the qemu process to dig for usable info */
|
|
|
|
qemuMonitorReportDomainLogError logFunc;
|
|
|
|
void *logOpaque;
|
|
|
|
virFreeCallback logDestroy;
|
2009-10-09 19:13:29 +00:00
|
|
|
};
|
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
/**
|
|
|
|
* QEMU_CHECK_MONITOR_FULL:
|
|
|
|
* @mon: monitor pointer variable to check, evaluated multiple times, no parentheses
|
|
|
|
* @exit: statement that is used to exit the function
|
|
|
|
*
|
|
|
|
* This macro checks that the monitor is valid for given operation and exits
|
|
|
|
* the function if not. The macro also adds a debug statement regarding the
|
|
|
|
* monitor.
|
|
|
|
*/
|
2018-05-22 11:23:34 +00:00
|
|
|
#define QEMU_CHECK_MONITOR_FULL(mon, exit) \
|
2017-11-03 12:09:47 +00:00
|
|
|
do { \
|
|
|
|
if (!mon) { \
|
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s", \
|
|
|
|
_("monitor must not be NULL")); \
|
|
|
|
exit; \
|
|
|
|
} \
|
2019-06-14 18:05:44 +00:00
|
|
|
VIR_DEBUG("mon:%p vm:%p fd:%d", mon, mon->vm, mon->fd); \
|
2016-07-29 07:04:34 +00:00
|
|
|
} while (0)
|
2015-04-14 15:52:48 +00:00
|
|
|
|
|
|
|
/* Check monitor and return NULL on error */
|
|
|
|
#define QEMU_CHECK_MONITOR_NULL(mon) \
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_FULL(mon, return NULL)
|
2015-04-14 15:52:48 +00:00
|
|
|
|
|
|
|
/* Check monitor and return -1 on error */
|
|
|
|
#define QEMU_CHECK_MONITOR(mon) \
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_FULL(mon, return -1)
|
2015-04-14 15:52:48 +00:00
|
|
|
|
|
|
|
/* Check monitor and jump to the provided label */
|
|
|
|
#define QEMU_CHECK_MONITOR_GOTO(mon, label) \
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_FULL(mon, goto label)
|
2015-04-14 15:52:48 +00:00
|
|
|
|
2012-07-11 13:35:47 +00:00
|
|
|
static virClassPtr qemuMonitorClass;
|
|
|
|
static void qemuMonitorDispose(void *obj);
|
|
|
|
|
|
|
|
static int qemuMonitorOnceInit(void)
|
|
|
|
{
|
2018-04-17 15:42:33 +00:00
|
|
|
if (!VIR_CLASS_NEW(qemuMonitor, virClassForObjectLockable()))
|
2012-07-11 13:35:47 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:23:29 +00:00
|
|
|
VIR_ONCE_GLOBAL_INIT(qemuMonitor);
|
2012-07-11 13:35:47 +00:00
|
|
|
|
2009-11-26 13:29:29 +00:00
|
|
|
|
2009-11-26 13:37:11 +00:00
|
|
|
VIR_ENUM_IMPL(qemuMonitorMigrationStatus,
|
|
|
|
QEMU_MONITOR_MIGRATION_STATUS_LAST,
|
2015-11-26 11:45:25 +00:00
|
|
|
"inactive", "setup",
|
2017-10-20 08:11:32 +00:00
|
|
|
"active", "pre-switchover",
|
|
|
|
"device", "postcopy-active",
|
2015-11-26 11:45:25 +00:00
|
|
|
"completed", "failed",
|
2019-01-20 16:30:15 +00:00
|
|
|
"cancelling", "cancelled",
|
|
|
|
);
|
2009-11-26 13:37:11 +00:00
|
|
|
|
2011-09-27 09:42:04 +00:00
|
|
|
VIR_ENUM_IMPL(qemuMonitorVMStatus,
|
|
|
|
QEMU_MONITOR_VM_STATUS_LAST,
|
|
|
|
"debug", "inmigrate", "internal-error", "io-error", "paused",
|
|
|
|
"postmigrate", "prelaunch", "finish-migrate", "restore-vm",
|
2019-01-20 16:30:15 +00:00
|
|
|
"running", "save-vm", "shutdown", "watchdog", "guest-panicked",
|
|
|
|
);
|
2011-09-27 09:42:04 +00:00
|
|
|
|
2012-01-19 16:58:58 +00:00
|
|
|
typedef enum {
|
|
|
|
QEMU_MONITOR_BLOCK_IO_STATUS_OK,
|
|
|
|
QEMU_MONITOR_BLOCK_IO_STATUS_FAILED,
|
|
|
|
QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE,
|
|
|
|
|
|
|
|
QEMU_MONITOR_BLOCK_IO_STATUS_LAST
|
|
|
|
} qemuMonitorBlockIOStatus;
|
|
|
|
|
2019-01-20 16:04:56 +00:00
|
|
|
VIR_ENUM_DECL(qemuMonitorBlockIOStatus);
|
2012-01-19 16:58:58 +00:00
|
|
|
|
|
|
|
VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
|
|
|
|
QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
|
2019-01-20 16:30:15 +00:00
|
|
|
"ok", "failed", "nospace",
|
|
|
|
);
|
2012-01-19 16:58:58 +00:00
|
|
|
|
2017-11-20 13:56:24 +00:00
|
|
|
VIR_ENUM_IMPL(qemuMonitorDumpStatus,
|
|
|
|
QEMU_MONITOR_DUMP_STATUS_LAST,
|
2019-01-20 16:30:15 +00:00
|
|
|
"none", "active", "completed", "failed",
|
|
|
|
);
|
2017-11-20 13:56:24 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2010-04-27 08:11:46 +00:00
|
|
|
#if DEBUG_RAW_IO
|
2015-04-14 13:14:23 +00:00
|
|
|
static char *
|
|
|
|
qemuMonitorEscapeNonPrintable(const char *text)
|
2009-12-08 18:05:02 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/qemu files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2009-12-08 18:05:02 +00:00
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
2013-05-21 07:21:20 +00:00
|
|
|
for (i = 0; text[i] != '\0'; i++) {
|
2019-11-18 14:14:47 +00:00
|
|
|
if (g_ascii_isprint(text[i]) ||
|
2009-12-08 18:05:02 +00:00
|
|
|
text[i] == '\n' ||
|
2013-11-19 22:45:43 +00:00
|
|
|
(text[i] == '\r' && text[i + 1] == '\n'))
|
|
|
|
virBufferAddChar(&buf, text[i]);
|
2009-12-08 18:05:02 +00:00
|
|
|
else
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(&buf, "0x%02x", text[i]);
|
2009-12-08 18:05:02 +00:00
|
|
|
}
|
|
|
|
return virBufferContentAndReset(&buf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
qemuMonitorDispose(void *obj)
|
2009-10-09 18:07:55 +00:00
|
|
|
{
|
2012-07-11 13:35:47 +00:00
|
|
|
qemuMonitorPtr mon = obj;
|
|
|
|
|
2009-11-26 13:29:29 +00:00
|
|
|
VIR_DEBUG("mon=%p", mon);
|
2010-06-29 10:57:54 +00:00
|
|
|
if (mon->cb && mon->cb->destroy)
|
2013-07-25 17:26:15 +00:00
|
|
|
(mon->cb->destroy)(mon, mon->vm, mon->callbackOpaque);
|
2013-10-08 14:50:33 +00:00
|
|
|
virObjectUnref(mon->vm);
|
|
|
|
|
2013-11-06 10:50:26 +00:00
|
|
|
virResetError(&mon->lastError);
|
2013-02-07 14:03:17 +00:00
|
|
|
virCondDestroy(&mon->notify);
|
2010-11-24 16:04:33 +00:00
|
|
|
VIR_FREE(mon->buffer);
|
2013-04-26 17:13:45 +00:00
|
|
|
virJSONValueFree(mon->options);
|
2013-06-27 15:00:31 +00:00
|
|
|
VIR_FREE(mon->balloonpath);
|
2009-10-09 18:07:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2017-03-11 06:23:42 +00:00
|
|
|
qemuMonitorOpenUnix(const char *monitor,
|
|
|
|
pid_t cpid,
|
2018-03-14 17:27:49 +00:00
|
|
|
bool retry,
|
2017-03-11 06:23:42 +00:00
|
|
|
unsigned long long timeout)
|
2009-10-09 18:07:55 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
int monfd;
|
2017-03-11 06:23:42 +00:00
|
|
|
virTimeBackOffVar timebackoff;
|
2016-04-08 11:11:10 +00:00
|
|
|
int ret = -1;
|
2009-10-09 18:07:55 +00:00
|
|
|
|
|
|
|
if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-10-09 18:07:55 +00:00
|
|
|
"%s", _("failed to create socket"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
|
|
addr.sun_family = AF_UNIX;
|
2018-07-20 07:50:37 +00:00
|
|
|
if (virStrcpyStatic(addr.sun_path, monitor) < 0) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Monitor path %s too big for destination"), monitor);
|
2009-10-09 18:07:55 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2018-03-14 17:27:49 +00:00
|
|
|
if (retry) {
|
|
|
|
if (virTimeBackOffStart(&timebackoff, 1, timeout * 1000) < 0)
|
|
|
|
goto error;
|
|
|
|
while (virTimeBackOffWait(&timebackoff)) {
|
|
|
|
ret = connect(monfd, (struct sockaddr *)&addr, sizeof(addr));
|
2009-10-09 18:07:55 +00:00
|
|
|
|
2018-03-14 17:27:49 +00:00
|
|
|
if (ret == 0)
|
|
|
|
break;
|
2009-10-09 18:07:55 +00:00
|
|
|
|
2018-03-14 17:27:49 +00:00
|
|
|
if ((errno == ENOENT || errno == ECONNREFUSED) &&
|
|
|
|
(!cpid || virProcessKill(cpid, 0) == 0)) {
|
|
|
|
/* ENOENT : Socket may not have shown up yet
|
|
|
|
* ECONNREFUSED : Leftover socket hasn't been removed yet */
|
|
|
|
continue;
|
|
|
|
}
|
2009-10-09 18:07:55 +00:00
|
|
|
|
2018-03-14 17:27:49 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("failed to connect to monitor socket"));
|
|
|
|
goto error;
|
|
|
|
}
|
2009-10-09 18:07:55 +00:00
|
|
|
|
2018-03-14 17:27:49 +00:00
|
|
|
if (ret != 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("monitor socket did not show up"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = connect(monfd, (struct sockaddr *) &addr, sizeof(addr));
|
|
|
|
if (ret < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("failed to connect to monitor socket"));
|
|
|
|
goto error;
|
|
|
|
}
|
2009-10-09 18:07:55 +00:00
|
|
|
}
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
return monfd;
|
2009-10-09 18:07:55 +00:00
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
error:
|
2010-11-09 20:48:48 +00:00
|
|
|
VIR_FORCE_CLOSE(monfd);
|
2009-10-09 18:07:55 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2009-10-09 18:07:55 +00:00
|
|
|
static int
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
qemuMonitorOpenPty(const char *monitor)
|
2009-10-09 18:07:55 +00:00
|
|
|
{
|
|
|
|
int monfd;
|
|
|
|
|
|
|
|
if ((monfd = open(monitor, O_RDWR)) < 0) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to open monitor path %s"), monitor);
|
2009-10-09 18:07:55 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
return monfd;
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
}
|
2009-10-09 18:07:55 +00:00
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
|
2011-05-29 12:51:08 +00:00
|
|
|
/* This method processes data that has been received
|
|
|
|
* from the monitor. Looking for async events and
|
|
|
|
* replies/errors.
|
|
|
|
*/
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
static int
|
|
|
|
qemuMonitorIOProcess(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
qemuMonitorMessagePtr msg = NULL;
|
|
|
|
|
|
|
|
/* See if there's a message & whether its ready for its reply
|
|
|
|
* ie whether its completed writing all its data */
|
|
|
|
if (mon->msg && mon->msg->txOffset == mon->msg->txLength)
|
|
|
|
msg = mon->msg;
|
|
|
|
|
2010-03-22 18:44:58 +00:00
|
|
|
#if DEBUG_IO
|
2010-03-26 16:00:50 +00:00
|
|
|
# if DEBUG_RAW_IO
|
2009-12-08 18:05:02 +00:00
|
|
|
char *str1 = qemuMonitorEscapeNonPrintable(msg ? msg->txBuffer : "");
|
|
|
|
char *str2 = qemuMonitorEscapeNonPrintable(mon->buffer);
|
2010-05-20 06:15:46 +00:00
|
|
|
VIR_ERROR(_("Process %d %p %p [[[[%s]]][[[%s]]]"), (int)mon->bufferOffset, mon->msg, msg, str1, str2);
|
2009-12-08 18:05:02 +00:00
|
|
|
VIR_FREE(str1);
|
|
|
|
VIR_FREE(str2);
|
2010-03-26 16:00:50 +00:00
|
|
|
# else
|
2009-11-11 10:30:01 +00:00
|
|
|
VIR_DEBUG("Process %d", (int)mon->bufferOffset);
|
2010-03-26 16:00:50 +00:00
|
|
|
# endif
|
2010-03-22 18:44:58 +00:00
|
|
|
#endif
|
|
|
|
|
2017-12-20 12:09:07 +00:00
|
|
|
PROBE_QUIET(QEMU_MONITOR_IO_PROCESS, "mon=%p buf=%s len=%zu",
|
|
|
|
mon, mon->buffer, mon->bufferOffset);
|
2011-10-24 14:31:37 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
len = qemuMonitorJSONIOProcess(mon,
|
|
|
|
mon->buffer, mon->bufferOffset,
|
|
|
|
msg);
|
2011-05-29 12:51:08 +00:00
|
|
|
if (len < 0)
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
return -1;
|
|
|
|
|
2013-04-26 02:32:41 +00:00
|
|
|
if (len && mon->waitGreeting)
|
|
|
|
mon->waitGreeting = false;
|
2012-09-06 15:14:25 +00:00
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
if (len < mon->bufferOffset) {
|
|
|
|
memmove(mon->buffer, mon->buffer + len, mon->bufferOffset - len);
|
|
|
|
mon->bufferOffset -= len;
|
|
|
|
} else {
|
|
|
|
VIR_FREE(mon->buffer);
|
|
|
|
mon->bufferOffset = mon->bufferLength = 0;
|
|
|
|
}
|
2010-03-22 18:44:58 +00:00
|
|
|
#if DEBUG_IO
|
2009-11-11 10:30:01 +00:00
|
|
|
VIR_DEBUG("Process done %d used %d", (int)mon->bufferOffset, len);
|
2010-03-22 18:44:58 +00:00
|
|
|
#endif
|
qemu: fix msg could be a wild pointer in qemuMonitorIOProcess()
As qemuMonitorJSONIOProcess will call qemuMonitorJSONIOProcessEvent
which unlocks the monitor mutex, there is some extreme situation,
eg qemu send message to monitor twice in a short time, where the
local viriable 'msg' of qemuMonitorIOProcess could be a wild point:
1. qemuMonitorSend() assign mon->msg to parameter 'msg', which is alse a
local variable of its caller qemuMonitorJSONCommandWithFd(), cause
eventloop to send message to monitor, then wait condition.
2. qemu send message to monitor for the first time immediately.
3. qemuMonitorIOProcess() is called, then wake up the qemuMonitorSend()
thread, but the qemuMonitorSend() thread stuck for a while as cpu pressure
or some other reasons, which means the qemu monitor is still unlocked.
4. qemu send event message to monitor for the second time,
such as RTC_CHANGE event
5. qemuMonitorIOProcess() is called again, the local viriable 'msg' is
assigned to mon->msg.
6. qemuMonitorIOProcess() call qemuMonitorJSONIOProcess() to deal with
the qemu event.
7. qemuMonitorJSONIOProcess() unlock the qemu monitor in the macro
'QEMU_MONITOR_CALLBACK', then qemuMonitorSend() thread get the mutex
and free the mon->msg, assign mon->msg to NULL.
Signed-off-by: Weilun Zhu <zhuweilun@huawei.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
2018-06-20 08:45:27 +00:00
|
|
|
|
|
|
|
/* As the monitor mutex was unlocked in qemuMonitorJSONIOProcess()
|
|
|
|
* while dealing with qemu event, mon->msg could be changed which
|
|
|
|
* means the above 'msg' may be invalid, thus we use 'mon->msg' here */
|
|
|
|
if (mon->msg && mon->msg->finished)
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
virCondBroadcast(&mon->notify);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-17 15:19:13 +00:00
|
|
|
/* Call this function while holding the monitor lock. */
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
static int
|
|
|
|
qemuMonitorIOWriteWithFD(qemuMonitorPtr mon,
|
|
|
|
const char *data,
|
|
|
|
size_t len,
|
|
|
|
int fd)
|
|
|
|
{
|
|
|
|
struct msghdr msg;
|
|
|
|
struct iovec iov[1];
|
|
|
|
int ret;
|
|
|
|
char control[CMSG_SPACE(sizeof(int))];
|
|
|
|
struct cmsghdr *cmsg;
|
|
|
|
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
2011-06-30 14:04:23 +00:00
|
|
|
memset(control, 0, sizeof(control));
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
|
|
|
|
iov[0].iov_base = (void *)data;
|
|
|
|
iov[0].iov_len = len;
|
|
|
|
|
|
|
|
msg.msg_iov = iov;
|
|
|
|
msg.msg_iovlen = 1;
|
|
|
|
|
|
|
|
msg.msg_control = control;
|
|
|
|
msg.msg_controllen = sizeof(control);
|
|
|
|
|
|
|
|
cmsg = CMSG_FIRSTHDR(&msg);
|
2010-05-05 17:14:54 +00:00
|
|
|
/* Some static analyzers, like clang 2.6-0.6.pre2, fail to see
|
|
|
|
that our use of CMSG_FIRSTHDR will not return NULL. */
|
|
|
|
sa_assert(cmsg);
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
|
|
|
cmsg->cmsg_level = SOL_SOCKET;
|
|
|
|
cmsg->cmsg_type = SCM_RIGHTS;
|
|
|
|
memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
|
|
|
|
|
|
|
|
do {
|
|
|
|
ret = sendmsg(mon->fd, &msg, 0);
|
|
|
|
} while (ret < 0 && errno == EINTR);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2010-11-17 15:19:13 +00:00
|
|
|
/*
|
|
|
|
* Called when the monitor is able to write data
|
|
|
|
* Call this function while holding the monitor lock.
|
|
|
|
*/
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
static int
|
|
|
|
qemuMonitorIOWrite(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
int done;
|
2014-09-12 12:22:58 +00:00
|
|
|
char *buf;
|
|
|
|
size_t len;
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
|
|
|
|
/* If no active message, or fully transmitted, the no-op */
|
|
|
|
if (!mon->msg || mon->msg->txOffset == mon->msg->txLength)
|
|
|
|
return 0;
|
|
|
|
|
2011-05-29 12:51:08 +00:00
|
|
|
if (mon->msg->txFD != -1 && !mon->hasSendFD) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Monitor does not support sending of file descriptors"));
|
2011-05-29 12:51:08 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-09-12 12:22:58 +00:00
|
|
|
buf = mon->msg->txBuffer + mon->msg->txOffset;
|
|
|
|
len = mon->msg->txLength - mon->msg->txOffset;
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
if (mon->msg->txFD == -1)
|
2014-09-12 12:22:58 +00:00
|
|
|
done = write(mon->fd, buf, len);
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
else
|
2014-09-12 12:22:58 +00:00
|
|
|
done = qemuMonitorIOWriteWithFD(mon, buf, len, mon->msg->txFD);
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
|
2011-10-24 14:31:37 +00:00
|
|
|
PROBE(QEMU_MONITOR_IO_WRITE,
|
2014-09-15 15:37:20 +00:00
|
|
|
"mon=%p buf=%s len=%zu ret=%d errno=%d",
|
2016-08-02 10:48:01 +00:00
|
|
|
mon, buf, len, done, done < 0 ? errno : 0);
|
2011-10-24 14:31:37 +00:00
|
|
|
|
2014-08-27 19:59:08 +00:00
|
|
|
if (mon->msg->txFD != -1) {
|
2011-10-24 14:31:37 +00:00
|
|
|
PROBE(QEMU_MONITOR_IO_SEND_FD,
|
|
|
|
"mon=%p fd=%d ret=%d errno=%d",
|
2016-08-02 10:48:01 +00:00
|
|
|
mon, mon->msg->txFD, done, done < 0 ? errno : 0);
|
2014-08-27 19:59:08 +00:00
|
|
|
}
|
2011-10-24 14:31:37 +00:00
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
if (done < 0) {
|
|
|
|
if (errno == EAGAIN)
|
|
|
|
return 0;
|
|
|
|
|
2011-05-29 12:51:08 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to write to monitor"));
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
mon->msg->txOffset += done;
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
/*
|
|
|
|
* Called when the monitor has incoming data to read
|
2010-11-17 15:19:13 +00:00
|
|
|
* Call this function while holding the monitor lock.
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
*
|
|
|
|
* Returns -1 on error, or number of bytes read
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
qemuMonitorIORead(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
size_t avail = mon->bufferLength - mon->bufferOffset;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (avail < 1024) {
|
2018-01-16 17:00:11 +00:00
|
|
|
if (mon->bufferLength >= QEMU_MONITOR_MAX_RESPONSE) {
|
|
|
|
virReportSystemError(ERANGE,
|
|
|
|
_("No complete monitor response found in %d bytes"),
|
|
|
|
QEMU_MONITOR_MAX_RESPONSE);
|
|
|
|
return -1;
|
|
|
|
}
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
if (VIR_REALLOC_N(mon->buffer,
|
2013-07-04 10:14:12 +00:00
|
|
|
mon->bufferLength + 1024) < 0)
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
return -1;
|
|
|
|
mon->bufferLength += 1024;
|
|
|
|
avail += 1024;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Read as much as we can get into our buffer,
|
|
|
|
until we block on EAGAIN, or hit EOF */
|
|
|
|
while (avail > 1) {
|
|
|
|
int got;
|
|
|
|
got = read(mon->fd,
|
|
|
|
mon->buffer + mon->bufferOffset,
|
|
|
|
avail - 1);
|
|
|
|
if (got < 0) {
|
|
|
|
if (errno == EAGAIN)
|
|
|
|
break;
|
2011-05-29 12:51:08 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to read from monitor"));
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
ret = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (got == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ret += got;
|
|
|
|
avail -= got;
|
|
|
|
mon->bufferOffset += got;
|
|
|
|
mon->buffer[mon->bufferOffset] = '\0';
|
|
|
|
}
|
|
|
|
|
2010-03-22 18:44:58 +00:00
|
|
|
#if DEBUG_IO
|
2009-11-11 10:30:01 +00:00
|
|
|
VIR_DEBUG("Now read %d bytes of data", (int)mon->bufferOffset);
|
2010-03-22 18:44:58 +00:00
|
|
|
#endif
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
static void
|
|
|
|
qemuMonitorUpdateWatch(qemuMonitorPtr mon)
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
{
|
|
|
|
int events =
|
|
|
|
VIR_EVENT_HANDLE_HANGUP |
|
|
|
|
VIR_EVENT_HANDLE_ERROR;
|
|
|
|
|
2012-09-28 14:27:39 +00:00
|
|
|
if (!mon->watch)
|
|
|
|
return;
|
|
|
|
|
2011-05-29 12:51:08 +00:00
|
|
|
if (mon->lastError.code == VIR_ERR_OK) {
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
events |= VIR_EVENT_HANDLE_READABLE;
|
|
|
|
|
2012-09-06 15:14:25 +00:00
|
|
|
if ((mon->msg && mon->msg->txOffset < mon->msg->txLength) &&
|
2013-04-26 02:32:41 +00:00
|
|
|
!mon->waitGreeting)
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
events |= VIR_EVENT_HANDLE_WRITABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
virEventUpdateHandle(mon->watch, events);
|
2009-10-09 18:07:55 +00:00
|
|
|
}
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
|
|
|
|
static void
|
2014-03-18 08:15:21 +00:00
|
|
|
qemuMonitorIO(int watch, int fd, int events, void *opaque)
|
|
|
|
{
|
2009-10-09 19:13:29 +00:00
|
|
|
qemuMonitorPtr mon = opaque;
|
2011-05-29 12:37:29 +00:00
|
|
|
bool error = false;
|
|
|
|
bool eof = false;
|
2013-09-18 14:17:39 +00:00
|
|
|
bool hangup = false;
|
2009-10-09 19:13:29 +00:00
|
|
|
|
2012-07-11 13:35:47 +00:00
|
|
|
virObjectRef(mon);
|
|
|
|
|
2010-11-17 15:19:13 +00:00
|
|
|
/* lock access to the monitor and protect fd */
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectLock(mon);
|
2010-03-22 18:44:58 +00:00
|
|
|
#if DEBUG_IO
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
VIR_DEBUG("Monitor %p I/O on watch %d fd %d events %d", mon, watch, fd, events);
|
2010-03-22 18:44:58 +00:00
|
|
|
#endif
|
2012-09-28 14:27:39 +00:00
|
|
|
if (mon->fd == -1 || mon->watch == 0) {
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(mon);
|
2012-09-28 14:27:39 +00:00
|
|
|
virObjectUnref(mon);
|
|
|
|
return;
|
|
|
|
}
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
if (mon->fd != fd || mon->watch != watch) {
|
2011-06-02 10:50:03 +00:00
|
|
|
if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
|
2011-05-29 12:51:08 +00:00
|
|
|
eof = true;
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("event from unexpected fd %d!=%d / watch %d!=%d"),
|
|
|
|
mon->fd, fd, mon->watch, watch);
|
2011-05-29 12:51:08 +00:00
|
|
|
error = true;
|
|
|
|
} else if (mon->lastError.code != VIR_ERR_OK) {
|
2011-06-02 10:50:03 +00:00
|
|
|
if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
|
2011-05-29 12:51:08 +00:00
|
|
|
eof = true;
|
2011-05-29 12:37:29 +00:00
|
|
|
error = true;
|
2009-10-09 19:13:29 +00:00
|
|
|
} else {
|
2011-05-29 12:51:08 +00:00
|
|
|
if (events & VIR_EVENT_HANDLE_WRITABLE) {
|
2014-09-05 23:16:20 +00:00
|
|
|
if (qemuMonitorIOWrite(mon) < 0) {
|
2011-05-29 12:51:08 +00:00
|
|
|
error = true;
|
2014-09-05 23:16:20 +00:00
|
|
|
if (errno == ECONNRESET)
|
|
|
|
hangup = true;
|
|
|
|
}
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
events &= ~VIR_EVENT_HANDLE_WRITABLE;
|
|
|
|
}
|
2011-05-29 12:51:08 +00:00
|
|
|
|
|
|
|
if (!error &&
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
events & VIR_EVENT_HANDLE_READABLE) {
|
|
|
|
int got = qemuMonitorIORead(mon);
|
2011-05-29 12:51:08 +00:00
|
|
|
events &= ~VIR_EVENT_HANDLE_READABLE;
|
|
|
|
if (got < 0) {
|
2011-05-29 12:37:29 +00:00
|
|
|
error = true;
|
2014-09-05 23:16:20 +00:00
|
|
|
if (errno == ECONNRESET)
|
|
|
|
hangup = true;
|
2011-05-29 12:51:08 +00:00
|
|
|
} else if (got == 0) {
|
|
|
|
eof = true;
|
|
|
|
} else {
|
|
|
|
/* Ignore hangup/error events if we read some data, to
|
|
|
|
* give time for that data to be consumed */
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
events = 0;
|
|
|
|
|
|
|
|
if (qemuMonitorIOProcess(mon) < 0)
|
2011-05-29 12:37:29 +00:00
|
|
|
error = true;
|
2011-05-29 12:51:08 +00:00
|
|
|
}
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
}
|
|
|
|
|
2013-09-18 14:17:39 +00:00
|
|
|
if (events & VIR_EVENT_HANDLE_HANGUP) {
|
|
|
|
hangup = true;
|
|
|
|
if (!error) {
|
2018-01-19 12:53:57 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("End of file from qemu monitor"));
|
2013-09-18 14:17:39 +00:00
|
|
|
eof = true;
|
|
|
|
events &= ~VIR_EVENT_HANDLE_HANGUP;
|
|
|
|
}
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
}
|
|
|
|
|
2011-05-29 12:51:08 +00:00
|
|
|
if (!error && !eof &&
|
|
|
|
events & VIR_EVENT_HANDLE_ERROR) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Invalid file descriptor while waiting for monitor"));
|
2013-05-24 10:14:02 +00:00
|
|
|
eof = true;
|
2011-06-02 10:50:03 +00:00
|
|
|
events &= ~VIR_EVENT_HANDLE_ERROR;
|
2011-05-29 12:51:08 +00:00
|
|
|
}
|
|
|
|
if (!error && events) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unhandled event %d for monitor fd %d"),
|
|
|
|
events, mon->fd);
|
2013-05-24 10:14:02 +00:00
|
|
|
error = true;
|
2009-10-09 19:13:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-29 12:51:08 +00:00
|
|
|
if (error || eof) {
|
2015-11-12 13:54:04 +00:00
|
|
|
if (hangup && mon->logFunc != NULL) {
|
2013-09-18 14:17:39 +00:00
|
|
|
/* Check if an error message from qemu is available and if so, use
|
|
|
|
* it to overwrite the actual message. It's done only in early
|
2014-09-05 23:16:20 +00:00
|
|
|
* startup phases or during incoming migration when the message
|
|
|
|
* from qemu is certainly more interesting than a
|
|
|
|
* "connection reset by peer" message.
|
2013-09-18 14:17:39 +00:00
|
|
|
*/
|
2015-11-12 13:54:04 +00:00
|
|
|
mon->logFunc(mon,
|
2016-06-08 09:59:57 +00:00
|
|
|
_("qemu unexpectedly closed the monitor"),
|
2015-11-12 13:54:04 +00:00
|
|
|
mon->logOpaque);
|
2015-11-12 11:01:07 +00:00
|
|
|
virCopyLastError(&mon->lastError);
|
|
|
|
virResetLastError();
|
2013-09-18 14:17:39 +00:00
|
|
|
}
|
|
|
|
|
2011-05-29 12:51:08 +00:00
|
|
|
if (mon->lastError.code != VIR_ERR_OK) {
|
|
|
|
/* Already have an error, so clear any new error */
|
|
|
|
virResetLastError();
|
2018-01-19 12:53:57 +00:00
|
|
|
} else {
|
2018-05-05 12:04:21 +00:00
|
|
|
if (virGetLastErrorCode() == VIR_ERR_OK)
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Error while processing monitor IO"));
|
2011-05-29 12:51:08 +00:00
|
|
|
virCopyLastError(&mon->lastError);
|
|
|
|
virResetLastError();
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Error on monitor %s", NULLSTR(mon->lastError.message));
|
|
|
|
/* If IO process resulted in an error & we have a message,
|
|
|
|
* then wakeup that waiter */
|
|
|
|
if (mon->msg && !mon->msg->finished) {
|
|
|
|
mon->msg->finished = 1;
|
|
|
|
virCondSignal(&mon->notify);
|
|
|
|
}
|
|
|
|
}
|
2011-05-29 12:37:29 +00:00
|
|
|
|
|
|
|
qemuMonitorUpdateWatch(mon);
|
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
/* We have to unlock to avoid deadlock against command thread,
|
|
|
|
* but is this safe ? I think it is, because the callback
|
|
|
|
* will try to acquire the virDomainObjPtr mutex next */
|
2011-05-29 12:37:29 +00:00
|
|
|
if (eof) {
|
2013-07-25 15:27:52 +00:00
|
|
|
qemuMonitorEofNotifyCallback eofNotify = mon->cb->eofNotify;
|
2009-11-26 13:29:29 +00:00
|
|
|
virDomainObjPtr vm = mon->vm;
|
2011-03-30 01:43:25 +00:00
|
|
|
|
2011-05-29 12:37:29 +00:00
|
|
|
/* Make sure anyone waiting wakes up now */
|
|
|
|
virCondSignal(&mon->notify);
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(mon);
|
2011-05-29 12:37:29 +00:00
|
|
|
VIR_DEBUG("Triggering EOF callback");
|
2013-07-25 17:26:15 +00:00
|
|
|
(eofNotify)(mon, vm, mon->callbackOpaque);
|
qemuMonitorIO: Don't use @mon after it's unrefed
https://bugzilla.redhat.com/show_bug.cgi?id=1018267
The aim of virObject refing and urefing is to tell where the object is
to be used and when is no longer needed. Hence any object shouldn't be
used after it has been unrefed, as we might be the last to hold the
reference. The better way is to call virObjectUnref() *after* the last
object usage. In this specific case, the monitor EOF handler was called
after the qemuMonitorIO called virObjectUnref. Not only that @mon was
disposed (which is not used in the handler anyway) but the @mon->vm
which is causing a SIGSEGV:
2013-11-15 10:17:54.425+0000: 20110: error : qemuMonitorIO:688 : internal error: early end of file from monitor: possible problem:
qemu-kvm: -incoming tcp:01.01.01.0:49152: Failed to bind socket: Cannot assign requested address
Program received signal SIGSEGV, Segmentation fault.
qemuProcessHandleMonitorEOF (mon=<optimized out>, vm=0x7fb728004170) at qemu/qemu_process.c:299
299 if (priv->beingDestroyed) {
(gdb) p *priv
Cannot access memory at address 0x0
(gdb) p vm
$1 = (virDomainObj *) 0x7fb728004170
(gdb) p *vm
$2 = {parent = {parent = {magic = 3735928559, refs = 0, klass = 0xdeadbeef}, lock = {lock = {__data = {__lock = 2, __count = 0, __owner = 20110, __nusers = 1, __kind = 0, __spins = 0, __list = {__prev = 0x0,
__next = 0x0}}, __size = "\002\000\000\000\000\000\000\000\216N\000\000\001", '\000' <repeats 26 times>, __align = 2}}}, pid = 0, state = {state = 0, reason = 0}, autostart = 0, persistent = 0,
updated = 0, def = 0x0, newDef = 0x0, snapshots = 0x0, current_snapshot = 0x0, hasManagedSave = false, privateData = 0x0, privateDataFreeFunc = 0x0, taint = 304}
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2013-11-15 10:26:47 +00:00
|
|
|
virObjectUnref(mon);
|
2011-05-29 12:37:29 +00:00
|
|
|
} else if (error) {
|
2013-07-25 15:27:52 +00:00
|
|
|
qemuMonitorErrorNotifyCallback errorNotify = mon->cb->errorNotify;
|
2011-05-29 12:37:29 +00:00
|
|
|
virDomainObjPtr vm = mon->vm;
|
2011-03-30 01:43:25 +00:00
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
/* Make sure anyone waiting wakes up now */
|
|
|
|
virCondSignal(&mon->notify);
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(mon);
|
2011-05-29 12:37:29 +00:00
|
|
|
VIR_DEBUG("Triggering error callback");
|
2013-07-25 17:26:15 +00:00
|
|
|
(errorNotify)(mon, vm, mon->callbackOpaque);
|
qemuMonitorIO: Don't use @mon after it's unrefed
https://bugzilla.redhat.com/show_bug.cgi?id=1018267
The aim of virObject refing and urefing is to tell where the object is
to be used and when is no longer needed. Hence any object shouldn't be
used after it has been unrefed, as we might be the last to hold the
reference. The better way is to call virObjectUnref() *after* the last
object usage. In this specific case, the monitor EOF handler was called
after the qemuMonitorIO called virObjectUnref. Not only that @mon was
disposed (which is not used in the handler anyway) but the @mon->vm
which is causing a SIGSEGV:
2013-11-15 10:17:54.425+0000: 20110: error : qemuMonitorIO:688 : internal error: early end of file from monitor: possible problem:
qemu-kvm: -incoming tcp:01.01.01.0:49152: Failed to bind socket: Cannot assign requested address
Program received signal SIGSEGV, Segmentation fault.
qemuProcessHandleMonitorEOF (mon=<optimized out>, vm=0x7fb728004170) at qemu/qemu_process.c:299
299 if (priv->beingDestroyed) {
(gdb) p *priv
Cannot access memory at address 0x0
(gdb) p vm
$1 = (virDomainObj *) 0x7fb728004170
(gdb) p *vm
$2 = {parent = {parent = {magic = 3735928559, refs = 0, klass = 0xdeadbeef}, lock = {lock = {__data = {__lock = 2, __count = 0, __owner = 20110, __nusers = 1, __kind = 0, __spins = 0, __list = {__prev = 0x0,
__next = 0x0}}, __size = "\002\000\000\000\000\000\000\000\216N\000\000\001", '\000' <repeats 26 times>, __align = 2}}}, pid = 0, state = {state = 0, reason = 0}, autostart = 0, persistent = 0,
updated = 0, def = 0x0, newDef = 0x0, snapshots = 0x0, current_snapshot = 0x0, hasManagedSave = false, privateData = 0x0, privateDataFreeFunc = 0x0, taint = 304}
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2013-11-15 10:26:47 +00:00
|
|
|
virObjectUnref(mon);
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
} else {
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(mon);
|
2012-07-11 13:35:47 +00:00
|
|
|
virObjectUnref(mon);
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
}
|
2009-10-09 19:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-06 15:23:57 +00:00
|
|
|
static qemuMonitorPtr
|
|
|
|
qemuMonitorOpenInternal(virDomainObjPtr vm,
|
|
|
|
int fd,
|
|
|
|
bool hasSendFD,
|
2013-07-25 17:26:15 +00:00
|
|
|
qemuMonitorCallbacksPtr cb,
|
|
|
|
void *opaque)
|
2009-10-09 18:07:55 +00:00
|
|
|
{
|
2009-10-09 19:13:29 +00:00
|
|
|
qemuMonitorPtr mon;
|
|
|
|
|
2012-08-20 12:39:47 +00:00
|
|
|
if (!cb->eofNotify) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("EOF notify callback must be supplied"));
|
2009-10-15 17:56:52 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-08-20 12:39:47 +00:00
|
|
|
if (!cb->errorNotify) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Error notify callback must be supplied"));
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-10-15 17:56:52 +00:00
|
|
|
|
2012-07-11 13:35:47 +00:00
|
|
|
if (qemuMonitorInitialize() < 0)
|
|
|
|
return NULL;
|
|
|
|
|
2013-01-09 21:00:32 +00:00
|
|
|
if (!(mon = virObjectLockableNew(qemuMonitorClass)))
|
2009-10-09 19:13:29 +00:00
|
|
|
return NULL;
|
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
if (virCondInit(&mon->notify) < 0) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("cannot initialize monitor condition"));
|
2013-01-09 21:00:32 +00:00
|
|
|
goto cleanup;
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
}
|
2012-09-06 15:23:57 +00:00
|
|
|
mon->fd = fd;
|
|
|
|
mon->hasSendFD = hasSendFD;
|
2013-10-08 14:50:33 +00:00
|
|
|
mon->vm = virObjectRef(vm);
|
2019-06-14 18:08:00 +00:00
|
|
|
mon->waitGreeting = true;
|
2009-10-15 17:56:52 +00:00
|
|
|
mon->cb = cb;
|
2013-07-25 17:26:15 +00:00
|
|
|
mon->callbackOpaque = opaque;
|
2009-10-09 19:13:29 +00:00
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
if (virSetCloseExec(mon->fd) < 0) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("Unable to set monitor close-on-exec flag"));
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virSetNonBlock(mon->fd) < 0) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("Unable to put monitor into non-blocking mode"));
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-22 20:19:43 +00:00
|
|
|
virObjectLock(mon);
|
2017-04-03 08:24:37 +00:00
|
|
|
if (!qemuMonitorRegister(mon)) {
|
2013-02-22 20:19:43 +00:00
|
|
|
virObjectUnlock(mon);
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("unable to register monitor events"));
|
2009-10-09 19:13:29 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-10-24 14:31:37 +00:00
|
|
|
PROBE(QEMU_MONITOR_NEW,
|
|
|
|
"mon=%p refs=%d fd=%d",
|
object: require maximal alignment in base class
Recent changes to events (commit 8a29ffcf) resulted in new compile
failures on some targets (such as ARM OMAP5):
conf/domain_event.c: In function 'virDomainEventDispatchDefaultFunc':
conf/domain_event.c:1198:30: error: cast increases required alignment of
target type [-Werror=cast-align]
conf/domain_event.c:1314:34: error: cast increases required alignment of
target type [-Werror=cast-align]
cc1: all warnings being treated as errors
The error is due to alignment; the base class is merely aligned
to the worst of 'int' and 'void*', while the child class must
be aligned to a 'long long'. The solution is to include a
'long long' (and for good measure, a function pointer) in the
base class to ensure correct alignment regardless of what a
child class may add, but to wrap the inclusion in a union so
as to not incur any wasted space. On a typical x86_64 platform,
the base class remains 16 bytes; on i686, the base class remains
12 bytes; and on the impacted ARM platform, the base class grows
from 12 bytes to 16 bytes due to the increase of alignment from
4 to 8 bytes.
Reported by Michele Paolino and others.
* src/util/virobject.h (_virObject): Use a union to ensure that
subclasses never have stricter alignment than the parent.
* src/util/virobject.c (virObjectNew, virObjectUnref)
(virObjectRef): Adjust clients.
* src/libvirt.c (virConnectRef, virDomainRef, virNetworkRef)
(virInterfaceRef, virStoragePoolRef, virStorageVolRef)
(virNodeDeviceRef, virSecretRef, virStreamRef, virNWFilterRef)
(virDomainSnapshotRef): Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorOpenInternal)
(qemuMonitorClose): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-12 23:01:15 +00:00
|
|
|
mon, mon->parent.parent.u.s.refs, mon->fd);
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(mon);
|
2009-10-09 19:34:24 +00:00
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
return mon;
|
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2010-06-29 10:57:54 +00:00
|
|
|
/* We don't want the 'destroy' callback invoked during
|
|
|
|
* cleanup from construction failure, because that can
|
|
|
|
* give a double-unref on virDomainObjPtr in the caller,
|
|
|
|
* so kill the callbacks now.
|
|
|
|
*/
|
|
|
|
mon->cb = NULL;
|
2012-09-06 15:23:57 +00:00
|
|
|
/* The caller owns 'fd' on failure */
|
|
|
|
mon->fd = -1;
|
2009-10-09 19:13:29 +00:00
|
|
|
qemuMonitorClose(mon);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2017-03-11 06:23:42 +00:00
|
|
|
#define QEMU_DEFAULT_MONITOR_WAIT 30
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuMonitorOpen:
|
|
|
|
* @vm: domain object
|
|
|
|
* @config: monitor configuration
|
|
|
|
* @timeout: number of seconds to add to default timeout
|
|
|
|
* @cb: monitor event handles
|
|
|
|
* @opaque: opaque data for @cb
|
|
|
|
*
|
|
|
|
* Opens the monitor for running qemu. It may happen that it
|
|
|
|
* takes some time for qemu to create the monitor socket (e.g.
|
|
|
|
* because kernel is zeroing configured hugepages), therefore we
|
|
|
|
* wait up to default + timeout seconds for the monitor to show
|
|
|
|
* up after which a failure is claimed.
|
|
|
|
*
|
|
|
|
* Returns monitor object, NULL on error.
|
|
|
|
*/
|
2012-09-06 15:23:57 +00:00
|
|
|
qemuMonitorPtr
|
|
|
|
qemuMonitorOpen(virDomainObjPtr vm,
|
|
|
|
virDomainChrSourceDefPtr config,
|
2018-03-14 17:27:49 +00:00
|
|
|
bool retry,
|
2017-03-11 06:23:42 +00:00
|
|
|
unsigned long long timeout,
|
2013-07-25 17:26:15 +00:00
|
|
|
qemuMonitorCallbacksPtr cb,
|
|
|
|
void *opaque)
|
2012-09-06 15:23:57 +00:00
|
|
|
{
|
qemu: Fix @vm locking issue when connecting to the monitor
When connecting to qemu's monitor the @vm object is unlocked.
This is justified - connecting may take a long time and we don't
want to wait with the domain object locked. However, just before
the domain object is locked again, the monitor's FD is registered
in the event loop. Therefore, there is a small window where the
event loop has a chance to call a handler for an event that
occurred on the monitor FD but vm is not initalized properly just
yet (i.e. priv->mon is not set). For instance, if there's an
incoming migration, qemu creates its socket but then fails to
initialize (for various reasons, I'm reproducing this by using
hugepages but leaving the HP pool empty) then the following may
happen:
1) qemuConnectMonitor() unlocks @vm
2) qemuMonitorOpen() connects to the monitor socket and by
calling qemuMonitorOpenInternal() which subsequently calls
qemuMonitorRegister() the event handler is installed
3) qemu fails to initialize and exit()-s, which closes the
monitor
4) The even loop sees EOF on the monitor and the control gets to
qemuProcessEventHandler() which locks @vm and calls
processMonitorEOFEvent() which then calls
qemuMonitorLastError(priv->mon). But priv->mon is not set just
yet.
5) qemuMonitorLastError() dereferences NULL pointer
The solution is to unlock the domain object for a shorter time
and most importantly, register event handler with domain object
locked so that any possible event processing is done only after
@vm's private data was properly initialized.
This issue is also mentioned in v4.2.0-99-ga5a777a8ba.
Since we are unlocking @vm and locking it back, another thread
might have destroyed the domain meanwhile. Therefore we have to
check if domain is still active, and we have to do it at the
same place where domain lock is acquired back, i.e. in
qemuMonitorOpen(). This creates a small problem for our test
suite which calls qemuMonitorOpen() directly and passes @vm which
has no definition. This makes virDomainObjIsActive() call crash.
Fortunately, allocating empty domain definition is sufficient.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2019-10-08 07:24:23 +00:00
|
|
|
int fd = -1;
|
2012-09-06 15:23:57 +00:00
|
|
|
bool hasSendFD = false;
|
qemu: Fix @vm locking issue when connecting to the monitor
When connecting to qemu's monitor the @vm object is unlocked.
This is justified - connecting may take a long time and we don't
want to wait with the domain object locked. However, just before
the domain object is locked again, the monitor's FD is registered
in the event loop. Therefore, there is a small window where the
event loop has a chance to call a handler for an event that
occurred on the monitor FD but vm is not initalized properly just
yet (i.e. priv->mon is not set). For instance, if there's an
incoming migration, qemu creates its socket but then fails to
initialize (for various reasons, I'm reproducing this by using
hugepages but leaving the HP pool empty) then the following may
happen:
1) qemuConnectMonitor() unlocks @vm
2) qemuMonitorOpen() connects to the monitor socket and by
calling qemuMonitorOpenInternal() which subsequently calls
qemuMonitorRegister() the event handler is installed
3) qemu fails to initialize and exit()-s, which closes the
monitor
4) The even loop sees EOF on the monitor and the control gets to
qemuProcessEventHandler() which locks @vm and calls
processMonitorEOFEvent() which then calls
qemuMonitorLastError(priv->mon). But priv->mon is not set just
yet.
5) qemuMonitorLastError() dereferences NULL pointer
The solution is to unlock the domain object for a shorter time
and most importantly, register event handler with domain object
locked so that any possible event processing is done only after
@vm's private data was properly initialized.
This issue is also mentioned in v4.2.0-99-ga5a777a8ba.
Since we are unlocking @vm and locking it back, another thread
might have destroyed the domain meanwhile. Therefore we have to
check if domain is still active, and we have to do it at the
same place where domain lock is acquired back, i.e. in
qemuMonitorOpen(). This creates a small problem for our test
suite which calls qemuMonitorOpen() directly and passes @vm which
has no definition. This makes virDomainObjIsActive() call crash.
Fortunately, allocating empty domain definition is sufficient.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2019-10-08 07:24:23 +00:00
|
|
|
qemuMonitorPtr ret = NULL;
|
2012-09-06 15:23:57 +00:00
|
|
|
|
2017-03-11 06:23:42 +00:00
|
|
|
timeout += QEMU_DEFAULT_MONITOR_WAIT;
|
|
|
|
|
qemu: Fix @vm locking issue when connecting to the monitor
When connecting to qemu's monitor the @vm object is unlocked.
This is justified - connecting may take a long time and we don't
want to wait with the domain object locked. However, just before
the domain object is locked again, the monitor's FD is registered
in the event loop. Therefore, there is a small window where the
event loop has a chance to call a handler for an event that
occurred on the monitor FD but vm is not initalized properly just
yet (i.e. priv->mon is not set). For instance, if there's an
incoming migration, qemu creates its socket but then fails to
initialize (for various reasons, I'm reproducing this by using
hugepages but leaving the HP pool empty) then the following may
happen:
1) qemuConnectMonitor() unlocks @vm
2) qemuMonitorOpen() connects to the monitor socket and by
calling qemuMonitorOpenInternal() which subsequently calls
qemuMonitorRegister() the event handler is installed
3) qemu fails to initialize and exit()-s, which closes the
monitor
4) The even loop sees EOF on the monitor and the control gets to
qemuProcessEventHandler() which locks @vm and calls
processMonitorEOFEvent() which then calls
qemuMonitorLastError(priv->mon). But priv->mon is not set just
yet.
5) qemuMonitorLastError() dereferences NULL pointer
The solution is to unlock the domain object for a shorter time
and most importantly, register event handler with domain object
locked so that any possible event processing is done only after
@vm's private data was properly initialized.
This issue is also mentioned in v4.2.0-99-ga5a777a8ba.
Since we are unlocking @vm and locking it back, another thread
might have destroyed the domain meanwhile. Therefore we have to
check if domain is still active, and we have to do it at the
same place where domain lock is acquired back, i.e. in
qemuMonitorOpen(). This creates a small problem for our test
suite which calls qemuMonitorOpen() directly and passes @vm which
has no definition. This makes virDomainObjIsActive() call crash.
Fortunately, allocating empty domain definition is sufficient.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2019-10-08 07:24:23 +00:00
|
|
|
/* Hold an extra reference because we can't allow 'vm' to be
|
|
|
|
* deleted until the monitor gets its own reference. */
|
|
|
|
virObjectRef(vm);
|
|
|
|
|
2012-09-06 15:23:57 +00:00
|
|
|
switch (config->type) {
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
|
|
|
hasSendFD = true;
|
qemu: Fix @vm locking issue when connecting to the monitor
When connecting to qemu's monitor the @vm object is unlocked.
This is justified - connecting may take a long time and we don't
want to wait with the domain object locked. However, just before
the domain object is locked again, the monitor's FD is registered
in the event loop. Therefore, there is a small window where the
event loop has a chance to call a handler for an event that
occurred on the monitor FD but vm is not initalized properly just
yet (i.e. priv->mon is not set). For instance, if there's an
incoming migration, qemu creates its socket but then fails to
initialize (for various reasons, I'm reproducing this by using
hugepages but leaving the HP pool empty) then the following may
happen:
1) qemuConnectMonitor() unlocks @vm
2) qemuMonitorOpen() connects to the monitor socket and by
calling qemuMonitorOpenInternal() which subsequently calls
qemuMonitorRegister() the event handler is installed
3) qemu fails to initialize and exit()-s, which closes the
monitor
4) The even loop sees EOF on the monitor and the control gets to
qemuProcessEventHandler() which locks @vm and calls
processMonitorEOFEvent() which then calls
qemuMonitorLastError(priv->mon). But priv->mon is not set just
yet.
5) qemuMonitorLastError() dereferences NULL pointer
The solution is to unlock the domain object for a shorter time
and most importantly, register event handler with domain object
locked so that any possible event processing is done only after
@vm's private data was properly initialized.
This issue is also mentioned in v4.2.0-99-ga5a777a8ba.
Since we are unlocking @vm and locking it back, another thread
might have destroyed the domain meanwhile. Therefore we have to
check if domain is still active, and we have to do it at the
same place where domain lock is acquired back, i.e. in
qemuMonitorOpen(). This creates a small problem for our test
suite which calls qemuMonitorOpen() directly and passes @vm which
has no definition. This makes virDomainObjIsActive() call crash.
Fortunately, allocating empty domain definition is sufficient.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2019-10-08 07:24:23 +00:00
|
|
|
virObjectUnlock(vm);
|
|
|
|
fd = qemuMonitorOpenUnix(config->data.nix.path,
|
|
|
|
vm->pid, retry, timeout);
|
|
|
|
virObjectLock(vm);
|
2012-09-06 15:23:57 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PTY:
|
qemu: Fix @vm locking issue when connecting to the monitor
When connecting to qemu's monitor the @vm object is unlocked.
This is justified - connecting may take a long time and we don't
want to wait with the domain object locked. However, just before
the domain object is locked again, the monitor's FD is registered
in the event loop. Therefore, there is a small window where the
event loop has a chance to call a handler for an event that
occurred on the monitor FD but vm is not initalized properly just
yet (i.e. priv->mon is not set). For instance, if there's an
incoming migration, qemu creates its socket but then fails to
initialize (for various reasons, I'm reproducing this by using
hugepages but leaving the HP pool empty) then the following may
happen:
1) qemuConnectMonitor() unlocks @vm
2) qemuMonitorOpen() connects to the monitor socket and by
calling qemuMonitorOpenInternal() which subsequently calls
qemuMonitorRegister() the event handler is installed
3) qemu fails to initialize and exit()-s, which closes the
monitor
4) The even loop sees EOF on the monitor and the control gets to
qemuProcessEventHandler() which locks @vm and calls
processMonitorEOFEvent() which then calls
qemuMonitorLastError(priv->mon). But priv->mon is not set just
yet.
5) qemuMonitorLastError() dereferences NULL pointer
The solution is to unlock the domain object for a shorter time
and most importantly, register event handler with domain object
locked so that any possible event processing is done only after
@vm's private data was properly initialized.
This issue is also mentioned in v4.2.0-99-ga5a777a8ba.
Since we are unlocking @vm and locking it back, another thread
might have destroyed the domain meanwhile. Therefore we have to
check if domain is still active, and we have to do it at the
same place where domain lock is acquired back, i.e. in
qemuMonitorOpen(). This creates a small problem for our test
suite which calls qemuMonitorOpen() directly and passes @vm which
has no definition. This makes virDomainObjIsActive() call crash.
Fortunately, allocating empty domain definition is sufficient.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2019-10-08 07:24:23 +00:00
|
|
|
virObjectUnlock(vm);
|
|
|
|
fd = qemuMonitorOpenPty(config->data.file.path);
|
|
|
|
virObjectLock(vm);
|
2012-09-06 15:23:57 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unable to handle monitor type: %s"),
|
|
|
|
virDomainChrTypeToString(config->type));
|
qemu: Fix @vm locking issue when connecting to the monitor
When connecting to qemu's monitor the @vm object is unlocked.
This is justified - connecting may take a long time and we don't
want to wait with the domain object locked. However, just before
the domain object is locked again, the monitor's FD is registered
in the event loop. Therefore, there is a small window where the
event loop has a chance to call a handler for an event that
occurred on the monitor FD but vm is not initalized properly just
yet (i.e. priv->mon is not set). For instance, if there's an
incoming migration, qemu creates its socket but then fails to
initialize (for various reasons, I'm reproducing this by using
hugepages but leaving the HP pool empty) then the following may
happen:
1) qemuConnectMonitor() unlocks @vm
2) qemuMonitorOpen() connects to the monitor socket and by
calling qemuMonitorOpenInternal() which subsequently calls
qemuMonitorRegister() the event handler is installed
3) qemu fails to initialize and exit()-s, which closes the
monitor
4) The even loop sees EOF on the monitor and the control gets to
qemuProcessEventHandler() which locks @vm and calls
processMonitorEOFEvent() which then calls
qemuMonitorLastError(priv->mon). But priv->mon is not set just
yet.
5) qemuMonitorLastError() dereferences NULL pointer
The solution is to unlock the domain object for a shorter time
and most importantly, register event handler with domain object
locked so that any possible event processing is done only after
@vm's private data was properly initialized.
This issue is also mentioned in v4.2.0-99-ga5a777a8ba.
Since we are unlocking @vm and locking it back, another thread
might have destroyed the domain meanwhile. Therefore we have to
check if domain is still active, and we have to do it at the
same place where domain lock is acquired back, i.e. in
qemuMonitorOpen(). This creates a small problem for our test
suite which calls qemuMonitorOpen() directly and passes @vm which
has no definition. This makes virDomainObjIsActive() call crash.
Fortunately, allocating empty domain definition is sufficient.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2019-10-08 07:24:23 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!virDomainObjIsActive(vm)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
|
_("domain is not running"));
|
|
|
|
goto cleanup;
|
2012-09-06 15:23:57 +00:00
|
|
|
}
|
|
|
|
|
2019-06-14 18:08:00 +00:00
|
|
|
ret = qemuMonitorOpenInternal(vm, fd, hasSendFD, cb, opaque);
|
qemu: Fix @vm locking issue when connecting to the monitor
When connecting to qemu's monitor the @vm object is unlocked.
This is justified - connecting may take a long time and we don't
want to wait with the domain object locked. However, just before
the domain object is locked again, the monitor's FD is registered
in the event loop. Therefore, there is a small window where the
event loop has a chance to call a handler for an event that
occurred on the monitor FD but vm is not initalized properly just
yet (i.e. priv->mon is not set). For instance, if there's an
incoming migration, qemu creates its socket but then fails to
initialize (for various reasons, I'm reproducing this by using
hugepages but leaving the HP pool empty) then the following may
happen:
1) qemuConnectMonitor() unlocks @vm
2) qemuMonitorOpen() connects to the monitor socket and by
calling qemuMonitorOpenInternal() which subsequently calls
qemuMonitorRegister() the event handler is installed
3) qemu fails to initialize and exit()-s, which closes the
monitor
4) The even loop sees EOF on the monitor and the control gets to
qemuProcessEventHandler() which locks @vm and calls
processMonitorEOFEvent() which then calls
qemuMonitorLastError(priv->mon). But priv->mon is not set just
yet.
5) qemuMonitorLastError() dereferences NULL pointer
The solution is to unlock the domain object for a shorter time
and most importantly, register event handler with domain object
locked so that any possible event processing is done only after
@vm's private data was properly initialized.
This issue is also mentioned in v4.2.0-99-ga5a777a8ba.
Since we are unlocking @vm and locking it back, another thread
might have destroyed the domain meanwhile. Therefore we have to
check if domain is still active, and we have to do it at the
same place where domain lock is acquired back, i.e. in
qemuMonitorOpen(). This creates a small problem for our test
suite which calls qemuMonitorOpen() directly and passes @vm which
has no definition. This makes virDomainObjIsActive() call crash.
Fortunately, allocating empty domain definition is sufficient.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2019-10-08 07:24:23 +00:00
|
|
|
cleanup:
|
2012-09-06 15:23:57 +00:00
|
|
|
if (!ret)
|
|
|
|
VIR_FORCE_CLOSE(fd);
|
qemu: Fix @vm locking issue when connecting to the monitor
When connecting to qemu's monitor the @vm object is unlocked.
This is justified - connecting may take a long time and we don't
want to wait with the domain object locked. However, just before
the domain object is locked again, the monitor's FD is registered
in the event loop. Therefore, there is a small window where the
event loop has a chance to call a handler for an event that
occurred on the monitor FD but vm is not initalized properly just
yet (i.e. priv->mon is not set). For instance, if there's an
incoming migration, qemu creates its socket but then fails to
initialize (for various reasons, I'm reproducing this by using
hugepages but leaving the HP pool empty) then the following may
happen:
1) qemuConnectMonitor() unlocks @vm
2) qemuMonitorOpen() connects to the monitor socket and by
calling qemuMonitorOpenInternal() which subsequently calls
qemuMonitorRegister() the event handler is installed
3) qemu fails to initialize and exit()-s, which closes the
monitor
4) The even loop sees EOF on the monitor and the control gets to
qemuProcessEventHandler() which locks @vm and calls
processMonitorEOFEvent() which then calls
qemuMonitorLastError(priv->mon). But priv->mon is not set just
yet.
5) qemuMonitorLastError() dereferences NULL pointer
The solution is to unlock the domain object for a shorter time
and most importantly, register event handler with domain object
locked so that any possible event processing is done only after
@vm's private data was properly initialized.
This issue is also mentioned in v4.2.0-99-ga5a777a8ba.
Since we are unlocking @vm and locking it back, another thread
might have destroyed the domain meanwhile. Therefore we have to
check if domain is still active, and we have to do it at the
same place where domain lock is acquired back, i.e. in
qemuMonitorOpen(). This creates a small problem for our test
suite which calls qemuMonitorOpen() directly and passes @vm which
has no definition. This makes virDomainObjIsActive() call crash.
Fortunately, allocating empty domain definition is sufficient.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
2019-10-08 07:24:23 +00:00
|
|
|
virObjectUnref(vm);
|
2012-09-06 15:23:57 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
qemuMonitorPtr
|
|
|
|
qemuMonitorOpenFD(virDomainObjPtr vm,
|
|
|
|
int sockfd,
|
|
|
|
qemuMonitorCallbacksPtr cb,
|
|
|
|
void *opaque)
|
2012-09-06 15:23:57 +00:00
|
|
|
{
|
2019-06-14 18:08:00 +00:00
|
|
|
return qemuMonitorOpenInternal(vm, sockfd, true, cb, opaque);
|
2012-09-06 15:23:57 +00:00
|
|
|
}
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
|
2017-04-03 08:24:37 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorRegister:
|
|
|
|
* @mon: QEMU monitor
|
|
|
|
*
|
|
|
|
* Registers the monitor in the event loop. The caller has to hold the
|
|
|
|
* lock for @mon.
|
|
|
|
*
|
|
|
|
* Returns true in case of success, false otherwise
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
qemuMonitorRegister(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
virObjectRef(mon);
|
|
|
|
if ((mon->watch = virEventAddHandle(mon->fd,
|
|
|
|
VIR_EVENT_HANDLE_HANGUP |
|
|
|
|
VIR_EVENT_HANDLE_ERROR |
|
|
|
|
VIR_EVENT_HANDLE_READABLE,
|
|
|
|
qemuMonitorIO,
|
|
|
|
mon,
|
|
|
|
virObjectFreeCallback)) < 0) {
|
|
|
|
virObjectUnref(mon);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-11 14:32:48 +00:00
|
|
|
void
|
|
|
|
qemuMonitorUnregister(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
if (mon->watch) {
|
|
|
|
virEventRemoveHandle(mon->watch);
|
|
|
|
mon->watch = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
void
|
|
|
|
qemuMonitorClose(qemuMonitorPtr mon)
|
2009-10-09 19:13:29 +00:00
|
|
|
{
|
|
|
|
if (!mon)
|
2010-06-10 14:11:30 +00:00
|
|
|
return;
|
2009-11-26 13:29:29 +00:00
|
|
|
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectLock(mon);
|
2011-10-24 14:31:37 +00:00
|
|
|
PROBE(QEMU_MONITOR_CLOSE,
|
object: require maximal alignment in base class
Recent changes to events (commit 8a29ffcf) resulted in new compile
failures on some targets (such as ARM OMAP5):
conf/domain_event.c: In function 'virDomainEventDispatchDefaultFunc':
conf/domain_event.c:1198:30: error: cast increases required alignment of
target type [-Werror=cast-align]
conf/domain_event.c:1314:34: error: cast increases required alignment of
target type [-Werror=cast-align]
cc1: all warnings being treated as errors
The error is due to alignment; the base class is merely aligned
to the worst of 'int' and 'void*', while the child class must
be aligned to a 'long long'. The solution is to include a
'long long' (and for good measure, a function pointer) in the
base class to ensure correct alignment regardless of what a
child class may add, but to wrap the inclusion in a union so
as to not incur any wasted space. On a typical x86_64 platform,
the base class remains 16 bytes; on i686, the base class remains
12 bytes; and on the impacted ARM platform, the base class grows
from 12 bytes to 16 bytes due to the increase of alignment from
4 to 8 bytes.
Reported by Michele Paolino and others.
* src/util/virobject.h (_virObject): Use a union to ensure that
subclasses never have stricter alignment than the parent.
* src/util/virobject.c (virObjectNew, virObjectUnref)
(virObjectRef): Adjust clients.
* src/libvirt.c (virConnectRef, virDomainRef, virNetworkRef)
(virInterfaceRef, virStoragePoolRef, virStorageVolRef)
(virNodeDeviceRef, virSecretRef, virStreamRef, virNWFilterRef)
(virDomainSnapshotRef): Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorOpenInternal)
(qemuMonitorClose): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-12-12 23:01:15 +00:00
|
|
|
"mon=%p refs=%d", mon, mon->parent.parent.u.s.refs);
|
2010-11-17 15:19:13 +00:00
|
|
|
|
qemu: Fix two use-after-free situations
There were multiple race conditions that could lead to segmentation
faults. The first precondition for this is qemuProcessLaunch must fail
sometime shortly after starting the new QEMU process. The second
precondition for the segmentation faults is that the new QEMU process
dies - or to be more precise the QEMU monitor has to be closed
irregularly. If both happens during qemuProcessStart (starting a
domain) there are race windows between the thread with the event
loop (T1) and the thread that is starting the domain (T2).
First segmentation fault scenario:
If qemuProcessLaunch fails during qemuProcessStart the code branches
to the 'stop' path where 'qemuMonitorSetDomainLog(priv->mon, NULL,
NULL, NULL)' will set the log function of the monitor to NULL (done in
T2). In the meantime the event loop of T1 will wake up with an EOF
event for the QEMU monitor because the QEMU process has died. The
crash occurs if T1 has checked 'mon->logFunc != NULL' in qemuMonitorIO
just before the logFunc was set to NULL by T2. If this situation
occurs T1 will try to call mon->logFunc which leads to the
segmentation fault.
Solution:
Require the monitor lock for setting the log function.
Backtrace:
0 0x0000000000000000 in ?? ()
1 0x000003ffe9e45316 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe08aa860) at
../../src/qemu/qemu_monitor.c:727
2 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
3 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
4 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
5 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
6 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Second segmentation fault scenario:
If qemuProcessLaunch fails it will unref the log context and with
invoking qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL)
qemuDomainLogContextFree() will be invoked. qemuDomainLogContextFree()
invokes virNetClientClose() to close the client and cleans everything
up (including unref of _virLogManager.client) when virNetClientClose()
returns. When T1 is now trying to report 'qemu unexpectedly closed the
monitor' libvirtd will crash because the client has already been
freed.
Solution:
As the critical section in qemuMonitorIO is protected with the monitor
lock we can use the same solution as proposed for the first
segmentation fault.
Backtrace:
0 virClassIsDerivedFrom (klass=0x3100979797979797,
parent=0x2aa000d92f0) at ../../src/util/virobject.c:169
1 0x000003fffda659e6 in virObjectIsClass (anyobj=<optimized out>,
klass=<optimized out>) at ../../src/util/virobject.c:365
2 0x000003fffda65a24 in virObjectLock (anyobj=0x3ffe08c1db0) at
../../src/util/virobject.c:317
3 0x000003fffdba4688 in
virNetClientIOEventLoop (client=client@entry=0x3ffe08c1db0,
thiscall=thiscall@entry=0x2aa000fbfa0) at
../../src/rpc/virnetclient.c:1668
4 0x000003fffdba4b4c in
virNetClientIO (client=client@entry=0x3ffe08c1db0,
thiscall=0x2aa000fbfa0) at ../../src/rpc/virnetclient.c:1944
5 0x000003fffdba4d42 in
virNetClientSendInternal (client=client@entry=0x3ffe08c1db0,
msg=msg@entry=0x2aa000cc710, expectReply=expectReply@entry=true,
nonBlock=nonBlock@entry=false) at ../../src/rpc/virnetclient.c:2116
6 0x000003fffdba6268 in
virNetClientSendWithReply (client=0x3ffe08c1db0, msg=0x2aa000cc710) at
../../src/rpc/virnetclient.c:2144
7 0x000003fffdba6e8e in virNetClientProgramCall (prog=0x3ffe08c1120,
client=<optimized out>, serial=<optimized out>, proc=<optimized out>,
noutfds=<optimized out>, outfds=0x0, ninfds=0x0, infds=0x0,
args_filter=0x3fffdb64440
<xdr_virLogManagerProtocolDomainReadLogFileArgs>, args=0x3ffffffe010,
ret_filter=0x3fffdb644c0
<xdr_virLogManagerProtocolDomainReadLogFileRet>, ret=0x3ffffffe008) at
../../src/rpc/virnetclientprogram.c:329
8 0x000003fffdb64042 in
virLogManagerDomainReadLogFile (mgr=<optimized out>, path=<optimized
out>, inode=<optimized out>, offset=<optimized out>, maxlen=<optimized
out>, flags=0) at ../../src/logging/log_manager.c:272
9 0x000003ffe9e0315c in qemuDomainLogContextRead (ctxt=0x3ffe08c2980,
msg=0x3ffffffe1c0) at ../../src/qemu/qemu_domain.c:4422
10 0x000003ffe9e280a8 in qemuProcessReadLog (logCtxt=<optimized out>,
msg=msg@entry=0x3ffffffe288) at ../../src/qemu/qemu_process.c:1800
11 0x000003ffe9e28206 in qemuProcessReportLogError (logCtxt=<optimized
out>, msgprefix=0x3ffe9ec276a "qemu unexpectedly closed the monitor")
at ../../src/qemu/qemu_process.c:1836
12 0x000003ffe9e28306 in
qemuProcessMonitorReportLogError (mon=mon@entry=0x3ffe085cf10,
msg=<optimized out>, opaque=<optimized out>) at
../../src/qemu/qemu_process.c:1856
13 0x000003ffe9e452b6 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe085cf10) at
../../src/qemu/qemu_monitor.c:726
14 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
15 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
16 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
17 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
18 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Other code parts where the same problem was possible to occur are
fixed as well (qemuMigrationFinish, qemuProcessStart, and
qemuDomainSaveImageStartVM).
Signed-off-by: Marc Hartmayer <mhartmay@linux.vnet.ibm.com>
Reported-by: Sascha Silbe <silbe@linux.vnet.ibm.com>
2017-04-03 08:24:35 +00:00
|
|
|
qemuMonitorSetDomainLogLocked(mon, NULL, NULL, NULL);
|
2015-11-04 11:45:15 +00:00
|
|
|
|
2010-11-17 15:19:13 +00:00
|
|
|
if (mon->fd >= 0) {
|
2016-02-11 14:32:48 +00:00
|
|
|
qemuMonitorUnregister(mon);
|
2010-11-17 15:19:13 +00:00
|
|
|
VIR_FORCE_CLOSE(mon->fd);
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
}
|
2009-10-09 19:13:29 +00:00
|
|
|
|
2011-12-14 08:57:07 +00:00
|
|
|
/* In case another thread is waiting for its monitor command to be
|
|
|
|
* processed, we need to wake it up with appropriate error set.
|
|
|
|
*/
|
|
|
|
if (mon->msg) {
|
|
|
|
if (mon->lastError.code == VIR_ERR_OK) {
|
2018-12-06 17:33:04 +00:00
|
|
|
virErrorPtr err;
|
|
|
|
|
|
|
|
virErrorPreserveLast(&err);
|
2011-12-14 08:57:07 +00:00
|
|
|
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
2017-03-07 17:09:58 +00:00
|
|
|
_("QEMU monitor was closed"));
|
2011-12-14 08:57:07 +00:00
|
|
|
virCopyLastError(&mon->lastError);
|
2018-12-06 17:33:04 +00:00
|
|
|
if (err)
|
|
|
|
virErrorRestore(&err);
|
|
|
|
else
|
2011-12-14 08:57:07 +00:00
|
|
|
virResetLastError();
|
|
|
|
}
|
|
|
|
mon->msg->finished = 1;
|
|
|
|
virCondSignal(&mon->notify);
|
|
|
|
}
|
|
|
|
|
2014-03-17 10:04:07 +00:00
|
|
|
/* Propagate existing monitor error in case the current thread has no
|
|
|
|
* error set.
|
|
|
|
*/
|
2018-05-05 12:04:21 +00:00
|
|
|
if (mon->lastError.code != VIR_ERR_OK && virGetLastErrorCode() == VIR_ERR_OK)
|
2014-03-17 10:04:07 +00:00
|
|
|
virSetError(&mon->lastError);
|
|
|
|
|
2013-01-09 21:00:32 +00:00
|
|
|
virObjectUnlock(mon);
|
2012-07-11 13:35:47 +00:00
|
|
|
virObjectUnref(mon);
|
2009-10-09 19:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
char *
|
|
|
|
qemuMonitorNextCommandID(qemuMonitorPtr mon)
|
2011-05-29 12:51:08 +00:00
|
|
|
{
|
|
|
|
char *id;
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
id = g_strdup_printf("libvirt-%d", ++mon->nextSerial);
|
2011-05-29 12:51:08 +00:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-04 14:26:08 +00:00
|
|
|
/* for use only in the test suite */
|
|
|
|
void
|
|
|
|
qemuMonitorResetCommandID(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
mon->nextSerial = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSend(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorMessagePtr msg)
|
2009-10-09 19:13:29 +00:00
|
|
|
{
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
int ret = -1;
|
2009-10-09 19:13:29 +00:00
|
|
|
|
2013-11-18 23:31:42 +00:00
|
|
|
/* Check whether qemu quit unexpectedly */
|
2011-05-29 12:51:08 +00:00
|
|
|
if (mon->lastError.code != VIR_ERR_OK) {
|
|
|
|
VIR_DEBUG("Attempt to send command while error is set %s",
|
|
|
|
NULLSTR(mon->lastError.message));
|
|
|
|
virSetError(&mon->lastError);
|
2011-03-30 01:43:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
mon->msg = msg;
|
|
|
|
qemuMonitorUpdateWatch(mon);
|
2009-10-09 19:13:29 +00:00
|
|
|
|
2011-10-24 14:31:37 +00:00
|
|
|
PROBE(QEMU_MONITOR_SEND_MSG,
|
|
|
|
"mon=%p msg=%s fd=%d",
|
|
|
|
mon, mon->msg->txBuffer, mon->msg->txFD);
|
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
while (!mon->msg->finished) {
|
2013-01-09 21:00:32 +00:00
|
|
|
if (virCondWait(&mon->notify, &mon->parent.lock) < 0) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Unable to wait on monitor condition"));
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
goto cleanup;
|
2011-05-29 12:51:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mon->lastError.code != VIR_ERR_OK) {
|
|
|
|
VIR_DEBUG("Send command resulted in error %s",
|
|
|
|
NULLSTR(mon->lastError.message));
|
|
|
|
virSetError(&mon->lastError);
|
|
|
|
goto cleanup;
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
}
|
2009-10-09 19:13:29 +00:00
|
|
|
|
2011-05-29 12:51:08 +00:00
|
|
|
ret = 0;
|
2009-10-09 19:13:29 +00:00
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
mon->msg = NULL;
|
|
|
|
qemuMonitorUpdateWatch(mon);
|
2009-10-09 19:13:29 +00:00
|
|
|
|
Fully asynchronous monitor I/O processing
Change the QEMU monitor file handle watch to poll for both
read & write events, as well as EOF. All I/O to/from the
QEMU monitor FD is now done in the event callback thread.
When the QEMU driver needs to send a command, it puts the
data to be sent into a qemuMonitorMessagePtr object instance,
queues it for dispatch, and then goes to sleep on a condition
variable. The event thread sends all the data, and then waits
for the reply to arrive, putting the response / error data
back into the qemuMonitorMessagePtr and notifying the condition
variable.
There is a temporary hack in the disk passphrase callback to
avoid acquiring the domain lock. This avoids a deadlock in
the command processing, since the domain lock is still held
when running monitor commands. The next commit will remove
the locking when running commands & thus allow re-introduction
of locking the disk passphrase callback
* src/qemu/qemu_driver.c: Temporarily don't acquire lock in
disk passphrase callback. To be reverted in next commit
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Remove
raw I/O functions, and a generic qemuMonitorSend() for
invoking a command
* src/qemu/qemu_monitor_text.c, src/qemu/qemu_monitor_text.h:
Remove all low level I/O, and use the new qemuMonitorSend()
API. Provide a qemuMonitorTextIOProcess() method for detecting
command/reply/prompt boundaries in the monitor data stream
2009-10-14 17:40:51 +00:00
|
|
|
return ret;
|
2009-10-09 18:07:55 +00:00
|
|
|
}
|
2009-10-09 19:34:24 +00:00
|
|
|
|
|
|
|
|
2015-07-02 06:26:48 +00:00
|
|
|
/**
|
|
|
|
* This function returns a new virError object; the caller is responsible
|
|
|
|
* for freeing it.
|
|
|
|
*/
|
|
|
|
virErrorPtr
|
|
|
|
qemuMonitorLastError(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
if (mon->lastError.code == VIR_ERR_OK)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return virErrorCopyNew(&mon->lastError);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-26 17:13:45 +00:00
|
|
|
virJSONValuePtr
|
|
|
|
qemuMonitorGetOptions(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
return mon->options;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2013-04-26 17:13:45 +00:00
|
|
|
void
|
|
|
|
qemuMonitorSetOptions(qemuMonitorPtr mon, virJSONValuePtr options)
|
|
|
|
{
|
|
|
|
mon->options = options;
|
|
|
|
}
|
|
|
|
|
2014-12-09 15:21:45 +00:00
|
|
|
|
|
|
|
/**
|
2015-06-10 07:02:36 +00:00
|
|
|
* Search the qom objects for the balloon driver object by its known names
|
|
|
|
* of "virtio-balloon-pci" or "virtio-balloon-ccw". The entry for the driver
|
|
|
|
* will be found by using function "qemuMonitorJSONFindLinkPath".
|
2014-12-09 15:21:45 +00:00
|
|
|
*
|
|
|
|
* Once found, check the entry to ensure it has the correct property listed.
|
|
|
|
* If it does not, then obtaining statistics from QEMU will not be possible.
|
|
|
|
* This feature was added to QEMU 1.5.
|
|
|
|
*/
|
2015-06-04 13:44:29 +00:00
|
|
|
static void
|
2016-07-25 15:07:38 +00:00
|
|
|
qemuMonitorInitBalloonObjectPath(qemuMonitorPtr mon,
|
|
|
|
virDomainMemballoonDefPtr balloon)
|
2014-12-09 15:21:45 +00:00
|
|
|
{
|
|
|
|
ssize_t i, nprops = 0;
|
|
|
|
char *path = NULL;
|
2016-07-25 15:07:38 +00:00
|
|
|
const char *name;
|
2014-12-09 15:21:45 +00:00
|
|
|
qemuMonitorJSONListPathPtr *bprops = NULL;
|
|
|
|
|
|
|
|
if (mon->balloonpath) {
|
2015-06-04 13:44:29 +00:00
|
|
|
return;
|
2014-12-09 15:21:45 +00:00
|
|
|
} else if (mon->ballooninit) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Cannot determine balloon device path"));
|
2015-06-04 13:44:29 +00:00
|
|
|
return;
|
2014-12-09 15:21:45 +00:00
|
|
|
}
|
2015-06-04 13:44:29 +00:00
|
|
|
mon->ballooninit = true;
|
2014-12-09 15:21:45 +00:00
|
|
|
|
2016-07-25 15:07:38 +00:00
|
|
|
switch (balloon->info.type) {
|
|
|
|
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
|
|
|
|
name = "virtio-balloon-pci";
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
|
|
|
|
name = "virtio-balloon-ccw";
|
|
|
|
break;
|
|
|
|
default:
|
2015-06-04 13:44:29 +00:00
|
|
|
return;
|
2015-06-10 07:02:36 +00:00
|
|
|
}
|
2014-12-09 15:21:45 +00:00
|
|
|
|
2016-07-25 15:07:38 +00:00
|
|
|
if (qemuMonitorJSONFindLinkPath(mon, name, balloon->info.alias, &path) < 0)
|
|
|
|
return;
|
|
|
|
|
2014-12-09 15:21:45 +00:00
|
|
|
nprops = qemuMonitorJSONGetObjectListPaths(mon, path, &bprops);
|
|
|
|
if (nprops < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < nprops; i++) {
|
|
|
|
if (STREQ(bprops[i]->name, "guest-stats-polling-interval")) {
|
|
|
|
VIR_DEBUG("Found Balloon Object Path %s", path);
|
|
|
|
mon->balloonpath = path;
|
|
|
|
path = NULL;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* If we get here, we found the path, but not the property */
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Property 'guest-stats-polling-interval' "
|
|
|
|
"not found on memory balloon driver."));
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
for (i = 0; i < nprops; i++)
|
|
|
|
qemuMonitorJSONListPathFree(bprops[i]);
|
|
|
|
VIR_FREE(bprops);
|
|
|
|
VIR_FREE(path);
|
2015-06-04 13:44:29 +00:00
|
|
|
return;
|
2013-06-27 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
2014-12-10 14:31:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* To update video memory size in status XML we need to load correct values from
|
2019-06-14 18:06:48 +00:00
|
|
|
* QEMU.
|
2014-12-10 14:31:23 +00:00
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure and sets proper error message.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorUpdateVideoMemorySize(qemuMonitorPtr mon,
|
|
|
|
virDomainVideoDefPtr video,
|
|
|
|
const char *videoName)
|
|
|
|
{
|
2019-06-14 19:40:19 +00:00
|
|
|
int rc = -1;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *path = NULL;
|
2014-12-10 14:31:23 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
2019-06-14 19:40:19 +00:00
|
|
|
rc = qemuMonitorJSONFindLinkPath(mon, videoName,
|
|
|
|
video->info.alias, &path);
|
|
|
|
if (rc < 0) {
|
|
|
|
if (rc == -2)
|
2019-06-14 18:06:48 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to find QOM Object path for "
|
|
|
|
"device '%s'"), videoName);
|
|
|
|
return -1;
|
2014-12-10 14:31:23 +00:00
|
|
|
}
|
|
|
|
|
2019-06-14 19:38:40 +00:00
|
|
|
return qemuMonitorJSONUpdateVideoMemorySize(mon, video, path);
|
2014-12-10 14:31:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-23 16:04:19 +00:00
|
|
|
/**
|
|
|
|
* To update video vram64 size in status XML we need to load correct value from
|
2019-06-14 18:06:48 +00:00
|
|
|
* QEMU.
|
2016-02-23 16:04:19 +00:00
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure and sets proper error message.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorUpdateVideoVram64Size(qemuMonitorPtr mon,
|
|
|
|
virDomainVideoDefPtr video,
|
|
|
|
const char *videoName)
|
|
|
|
{
|
2019-06-14 19:40:19 +00:00
|
|
|
int rc = -1;
|
2019-10-15 13:16:31 +00:00
|
|
|
g_autofree char *path = NULL;
|
2016-02-23 16:04:19 +00:00
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
2019-06-14 19:40:19 +00:00
|
|
|
rc = qemuMonitorJSONFindLinkPath(mon, videoName,
|
|
|
|
video->info.alias, &path);
|
|
|
|
if (rc < 0) {
|
|
|
|
if (rc == -2)
|
2019-06-14 18:06:48 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Failed to find QOM Object path for "
|
|
|
|
"device '%s'"), videoName);
|
|
|
|
return -1;
|
2016-02-23 16:04:19 +00:00
|
|
|
}
|
|
|
|
|
2019-06-14 19:38:40 +00:00
|
|
|
return qemuMonitorJSONUpdateVideoVram64Size(mon, video, path);
|
2016-02-23 16:04:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-18 17:27:14 +00:00
|
|
|
/* Ensure proper locking around callbacks. */
|
2017-11-03 12:09:47 +00:00
|
|
|
#define QEMU_MONITOR_CALLBACK(mon, ret, callback, ...) \
|
|
|
|
do { \
|
|
|
|
virObjectRef(mon); \
|
|
|
|
virObjectUnlock(mon); \
|
|
|
|
if ((mon)->cb && (mon)->cb->callback) \
|
|
|
|
(ret) = (mon)->cb->callback(mon, __VA_ARGS__, \
|
2013-07-25 17:26:15 +00:00
|
|
|
(mon)->callbackOpaque); \
|
2017-11-03 12:09:47 +00:00
|
|
|
virObjectLock(mon); \
|
|
|
|
virObjectUnref(mon); \
|
2011-03-18 17:27:14 +00:00
|
|
|
} while (0)
|
2011-03-09 20:24:04 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2014-01-30 00:14:44 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitEvent(qemuMonitorPtr mon, const char *event,
|
|
|
|
long long seconds, unsigned int micros,
|
|
|
|
const char *details)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p event=%s", mon, event);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainEvent, mon->vm, event, seconds,
|
|
|
|
micros, details);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
2017-04-12 10:00:37 +00:00
|
|
|
qemuMonitorEmitShutdown(qemuMonitorPtr mon, virTristateBool guest)
|
2009-11-26 13:05:24 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2017-04-12 10:00:37 +00:00
|
|
|
VIR_DEBUG("mon=%p guest=%u", mon, guest);
|
2009-11-26 13:05:24 +00:00
|
|
|
|
2017-04-12 10:00:37 +00:00
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainShutdown, mon->vm, guest);
|
2009-11-26 13:05:24 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitReset(qemuMonitorPtr mon)
|
2009-11-26 13:05:24 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
2011-03-18 17:27:14 +00:00
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainReset, mon->vm);
|
2009-11-26 13:05:24 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitPowerdown(qemuMonitorPtr mon)
|
2009-11-26 13:05:24 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
2011-03-18 17:27:14 +00:00
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainPowerdown, mon->vm);
|
2009-11-26 13:05:24 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitStop(qemuMonitorPtr mon)
|
2009-11-26 13:05:24 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
2011-03-18 17:27:14 +00:00
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainStop, mon->vm);
|
2009-11-26 13:05:24 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitResume(qemuMonitorPtr mon)
|
2013-01-07 21:25:01 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainResume, mon->vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
2017-03-20 13:35:33 +00:00
|
|
|
qemuMonitorEmitGuestPanic(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorEventPanicInfoPtr info)
|
2013-06-07 10:23:34 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
2017-03-20 13:35:33 +00:00
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainGuestPanic, mon->vm, info);
|
2013-06-07 10:23:34 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset)
|
2010-03-18 18:28:15 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
2011-03-18 17:27:14 +00:00
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainRTCChange, mon->vm, offset);
|
2010-03-18 18:28:15 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action)
|
Add support for an explicit watchdog event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_WATCHDOG
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_WATCHDOG_NONE = 0,
VIR_DOMAIN_EVENT_WATCHDOG_PAUSE,
VIR_DOMAIN_EVENT_WATCHDOG_RESET,
VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF,
VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN,
VIR_DOMAIN_EVENT_WATCHDOG_DEBUG,
} virDomainEventWatchdogAction;
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventWatchdogCallback)(virConnectPtr conn,
virDomainPtr dom,
int action,
void *opaque);
* daemon/remote.c: Dispatch watchdog events to client
* examples/domain-events/events-c/event-test.c: Watch for
watchdog events
* include/libvirt/libvirt.h.in: Define new watchdg event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle watchdog events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for watchdogs and emit a libvirt watchdog event
* src/remote/remote_driver.c: Receive and dispatch watchdog
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
watchdog events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for WATCHDOG event
from QEMU monitor
2010-03-18 19:07:48 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
2011-03-18 17:27:14 +00:00
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainWatchdog, mon->vm, action);
|
Add support for an explicit watchdog event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_WATCHDOG
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_WATCHDOG_NONE = 0,
VIR_DOMAIN_EVENT_WATCHDOG_PAUSE,
VIR_DOMAIN_EVENT_WATCHDOG_RESET,
VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF,
VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN,
VIR_DOMAIN_EVENT_WATCHDOG_DEBUG,
} virDomainEventWatchdogAction;
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventWatchdogCallback)(virConnectPtr conn,
virDomainPtr dom,
int action,
void *opaque);
* daemon/remote.c: Dispatch watchdog events to client
* examples/domain-events/events-c/event-test.c: Watch for
watchdog events
* include/libvirt/libvirt.h.in: Define new watchdg event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle watchdog events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for watchdogs and emit a libvirt watchdog event
* src/remote/remote_driver.c: Receive and dispatch watchdog
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
watchdog events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for WATCHDOG event
from QEMU monitor
2010-03-18 19:07:48 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitIOError(qemuMonitorPtr mon,
|
|
|
|
const char *diskAlias,
|
2018-08-13 15:02:38 +00:00
|
|
|
const char *nodename,
|
2015-04-14 13:14:23 +00:00
|
|
|
int action,
|
|
|
|
const char *reason)
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
2011-03-18 17:27:14 +00:00
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainIOError, mon->vm,
|
2018-08-13 15:02:38 +00:00
|
|
|
diskAlias, nodename, action, reason);
|
Add support for an explicit IO error event
This introduces a new event type
VIR_DOMAIN_EVENT_ID_IO_ERROR
This event includes the action that is about to be taken
as a result of the watchdog triggering
typedef enum {
VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0,
VIR_DOMAIN_EVENT_IO_ERROR_PAUSE,
VIR_DOMAIN_EVENT_IO_ERROR_REPORT,
} virDomainEventIOErrorAction;
In addition it has the source path of the disk that had the
error and its unique device alias. It does not include the
target device name (/dev/sda), since this would preclude
triggering IO errors from other file backed devices (eg
serial ports connected to a file)
Thus there is a new callback definition for this event type
typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
virDomainPtr dom,
const char *srcPath,
const char *devAlias,
int action,
void *opaque);
This is currently wired up to the QEMU block IO error events
* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
from QEMU monitor
2010-03-18 19:37:44 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitGraphics(qemuMonitorPtr mon,
|
|
|
|
int phase,
|
|
|
|
int localFamily,
|
|
|
|
const char *localNode,
|
|
|
|
const char *localService,
|
|
|
|
int remoteFamily,
|
|
|
|
const char *remoteNode,
|
|
|
|
const char *remoteService,
|
|
|
|
const char *authScheme,
|
|
|
|
const char *x509dname,
|
|
|
|
const char *saslUsername)
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
2011-03-18 17:27:14 +00:00
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainGraphics, mon->vm, phase,
|
|
|
|
localFamily, localNode, localService,
|
|
|
|
remoteFamily, remoteNode, remoteService,
|
|
|
|
authScheme, x509dname, saslUsername);
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorEmitTrayChange(qemuMonitorPtr mon,
|
|
|
|
const char *devAlias,
|
2018-08-13 14:02:38 +00:00
|
|
|
const char *devid,
|
2015-04-14 13:14:23 +00:00
|
|
|
int reason)
|
2012-03-23 13:44:50 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainTrayChange, mon->vm,
|
2018-08-13 14:02:38 +00:00
|
|
|
devAlias, devid, reason);
|
2012-03-23 13:44:50 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorEmitPMWakeup(qemuMonitorPtr mon)
|
2012-03-23 14:43:14 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainPMWakeup, mon->vm);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorEmitPMSuspend(qemuMonitorPtr mon)
|
2012-03-23 14:50:36 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainPMSuspend, mon->vm);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon)
|
2012-10-12 19:13:39 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainPMSuspendDisk, mon->vm);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
|
|
|
|
const char *diskAlias,
|
|
|
|
int type,
|
2017-10-27 12:37:22 +00:00
|
|
|
int status,
|
|
|
|
const char *error)
|
2011-07-22 05:57:42 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainBlockJob, mon->vm,
|
2017-10-27 12:37:22 +00:00
|
|
|
diskAlias, type, status, error);
|
2011-07-22 05:57:42 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
|
2018-12-04 16:57:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitJobStatusChange(qemuMonitorPtr mon,
|
|
|
|
const char *jobname,
|
|
|
|
qemuMonitorJobStatus status)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, jobStatusChange, mon->vm, jobname, status);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitBalloonChange(qemuMonitorPtr mon,
|
|
|
|
unsigned long long actual)
|
2012-07-12 15:45:57 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainBalloonChange, mon->vm, actual);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
Add domain events for graphics network clients
This introduces a new event type
VIR_DOMAIN_EVENT_ID_GRAPHICS
The same event can be emitted in 3 scenarios
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0,
VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE,
VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT,
} virDomainEventGraphicsPhase;
Connect/disconnect are triggered at socket accept/close.
The initialize phase is immediately after the protocol
setup and authentication has completed. ie when the
client is authorized and about to start interacting with
the graphical desktop
This event comes with *a lot* of potential information
- IP address, port & address family of client
- IP address, port & address family of server
- Authentication scheme (arbitrary string)
- Authenticated subject identity. A subject may have
multiple identities with some authentication schemes.
For example, vencrypt+sasl results in a x509dname
and saslUsername identities.
This results in a very complicated callback :-(
typedef enum {
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4,
VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6,
} virDomainEventGraphicsAddressType;
struct _virDomainEventGraphicsAddress {
int family;
const char *node;
const char *service;
};
typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress;
typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr;
struct _virDomainEventGraphicsSubject {
int nidentity;
struct {
const char *type;
const char *name;
} *identities;
};
typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject;
typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr;
typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn,
virDomainPtr dom,
int phase,
virDomainEventGraphicsAddressPtr local,
virDomainEventGraphicsAddressPtr remote,
const char *authScheme,
virDomainEventGraphicsSubjectPtr subject,
void *opaque);
The wire protocol is similarly complex
struct remote_domain_event_graphics_address {
int family;
remote_nonnull_string node;
remote_nonnull_string service;
};
const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20;
struct remote_domain_event_graphics_identity {
remote_nonnull_string type;
remote_nonnull_string name;
};
struct remote_domain_event_graphics_msg {
remote_nonnull_domain dom;
int phase;
remote_domain_event_graphics_address local;
remote_domain_event_graphics_address remote;
remote_nonnull_string authScheme;
remote_domain_event_graphics_identity subject<REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX>;
};
This is currently implemented in QEMU for the VNC graphics
protocol, but designed to be usable with SPICE graphics in
the future too.
* daemon/remote.c: Dispatch graphics events to client
* examples/domain-events/events-c/event-test.c: Watch for
graphics events
* include/libvirt/libvirt.h.in: Define new graphics event ID
and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
src/libvirt_private.syms: Extend API to handle graphics events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
for VNC events and emit a libvirt graphics event
* src/remote/remote_driver.c: Receive and dispatch graphics
events to application
* src/remote/remote_protocol.x: Wire protocol definition for
graphics events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED,
VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor
2010-03-19 13:27:45 +00:00
|
|
|
|
2013-07-11 15:07:26 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon,
|
|
|
|
const char *devAlias)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainDeviceDeleted, mon->vm, devAlias);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-17 17:07:50 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
|
|
|
|
const char *devAlias)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainNicRxFilterChanged, mon->vm, devAlias);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-13 13:09:39 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitSerialChange(qemuMonitorPtr mon,
|
|
|
|
const char *devAlias,
|
|
|
|
bool connected)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p, devAlias='%s', connected=%d", mon, devAlias, connected);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainSerialChange, mon->vm, devAlias, connected);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-28 11:35:06 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitSpiceMigrated(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainSpiceMigrated, mon->vm);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-28 11:35:52 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitMigrationStatus(qemuMonitorPtr mon,
|
|
|
|
int status)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p, status=%s",
|
|
|
|
mon, NULLSTR(qemuMonitorMigrationStatusTypeToString(status)));
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainMigrationStatus, mon->vm, status);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-08 14:23:35 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitMigrationPass(qemuMonitorPtr mon,
|
|
|
|
int pass)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p, pass=%d", mon, pass);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainMigrationPass, mon->vm, pass);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-01 14:41:08 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitAcpiOstInfo(qemuMonitorPtr mon,
|
|
|
|
const char *alias,
|
|
|
|
const char *slotType,
|
|
|
|
const char *slot,
|
|
|
|
unsigned int source,
|
|
|
|
unsigned int status)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p, alias='%s', slotType='%s', slot='%s', source='%u' status=%u",
|
|
|
|
mon, NULLSTR(alias), slotType, slot, source, status);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainAcpiOstInfo, mon->vm,
|
|
|
|
alias, slotType, slot, source, status);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-22 15:52:22 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitBlockThreshold(qemuMonitorPtr mon,
|
|
|
|
const char *nodename,
|
|
|
|
unsigned long long threshold,
|
|
|
|
unsigned long long excess)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
VIR_DEBUG("mon=%p, node-name='%s', threshold='%llu', excess='%llu'",
|
|
|
|
mon, nodename, threshold, excess);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainBlockThreshold, mon->vm,
|
|
|
|
nodename, threshold, excess);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-20 13:56:24 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitDumpCompleted(qemuMonitorPtr mon,
|
|
|
|
int status,
|
|
|
|
qemuMonitorDumpStatsPtr stats,
|
|
|
|
const char *error)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
VIR_DEBUG("mon=%p", mon);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainDumpCompleted, mon->vm,
|
|
|
|
status, stats, error);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-27 10:17:59 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitPRManagerStatusChanged(qemuMonitorPtr mon,
|
|
|
|
const char *prManager,
|
|
|
|
bool connected)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p, prManager='%s', connected=%d", mon, prManager, connected);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainPRManagerStatusChanged,
|
|
|
|
mon->vm, prManager, connected);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-12-24 10:15:12 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEmitRdmaGidStatusChanged(qemuMonitorPtr mon,
|
|
|
|
const char *netdev,
|
|
|
|
bool gid_status,
|
2019-01-09 10:27:15 +00:00
|
|
|
unsigned long long subnet_prefix,
|
|
|
|
unsigned long long interface_id)
|
2018-12-24 10:15:12 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2019-01-09 10:27:15 +00:00
|
|
|
VIR_DEBUG("netdev=%s, gid_status=%d, subnet_prefix=0x%llx, interface_id=0x%llx",
|
2018-12-24 10:15:12 +00:00
|
|
|
netdev, gid_status, subnet_prefix, interface_id);
|
|
|
|
|
|
|
|
QEMU_MONITOR_CALLBACK(mon, ret, domainRdmaGidStatusChanged, mon->vm,
|
|
|
|
netdev, gid_status, subnet_prefix, interface_id);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetCapabilities(qemuMonitorPtr mon)
|
2010-02-12 13:45:20 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-02-12 13:45:20 +00:00
|
|
|
|
2015-04-14 13:17:10 +00:00
|
|
|
return qemuMonitorJSONSetCapabilities(mon);
|
2010-02-12 13:45:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-09 20:13:06 +00:00
|
|
|
int
|
2018-02-09 15:40:51 +00:00
|
|
|
qemuMonitorStartCPUs(qemuMonitorPtr mon)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONStartCPUs(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorStopCPUs(qemuMonitorPtr mon)
|
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONStopCPUs(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-12 08:24:21 +00:00
|
|
|
int
|
|
|
|
qemuMonitorCheck(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
bool running;
|
|
|
|
return qemuMonitorGetStatus(mon, &running, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-05-05 11:50:25 +00:00
|
|
|
int
|
2011-09-27 09:42:04 +00:00
|
|
|
qemuMonitorGetStatus(qemuMonitorPtr mon,
|
|
|
|
bool *running,
|
|
|
|
virDomainPausedReason *reason)
|
2011-05-05 11:50:25 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("running=%p, reason=%p", running, reason);
|
2011-05-05 11:50:25 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-05-05 11:50:25 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONGetStatus(mon, running, reason);
|
2011-05-05 11:50:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSystemPowerdown(qemuMonitorPtr mon)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSystemPowerdown(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSystemReset(qemuMonitorPtr mon)
|
2011-06-15 16:49:58 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-06-15 16:49:58 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSystemReset(mon);
|
2011-06-15 16:49:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-01 11:56:23 +00:00
|
|
|
static void
|
|
|
|
qemuMonitorCPUInfoClear(qemuMonitorCPUInfoPtr cpus,
|
|
|
|
size_t ncpus)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < ncpus; i++) {
|
|
|
|
cpus[i].id = 0;
|
2016-11-22 08:32:11 +00:00
|
|
|
cpus[i].qemu_id = -1;
|
2016-08-01 11:56:23 +00:00
|
|
|
cpus[i].socket_id = -1;
|
|
|
|
cpus[i].core_id = -1;
|
|
|
|
cpus[i].thread_id = -1;
|
2017-06-27 14:04:38 +00:00
|
|
|
cpus[i].node_id = -1;
|
2016-08-01 11:56:23 +00:00
|
|
|
cpus[i].vcpus = 0;
|
|
|
|
cpus[i].tid = 0;
|
2016-10-13 11:42:44 +00:00
|
|
|
cpus[i].halted = false;
|
2016-08-01 11:56:23 +00:00
|
|
|
|
|
|
|
VIR_FREE(cpus[i].qom_path);
|
|
|
|
VIR_FREE(cpus[i].alias);
|
|
|
|
VIR_FREE(cpus[i].type);
|
2019-08-29 12:47:10 +00:00
|
|
|
virJSONValueFree(cpus[i].props);
|
2016-08-01 11:56:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-01 05:43:32 +00:00
|
|
|
void
|
|
|
|
qemuMonitorCPUInfoFree(qemuMonitorCPUInfoPtr cpus,
|
2016-08-01 11:56:23 +00:00
|
|
|
size_t ncpus)
|
2016-08-01 05:43:32 +00:00
|
|
|
{
|
|
|
|
if (!cpus)
|
|
|
|
return;
|
|
|
|
|
2016-08-01 11:56:23 +00:00
|
|
|
qemuMonitorCPUInfoClear(cpus, ncpus);
|
|
|
|
|
2016-08-01 05:43:32 +00:00
|
|
|
VIR_FREE(cpus);
|
|
|
|
}
|
|
|
|
|
2016-08-01 11:44:25 +00:00
|
|
|
void
|
|
|
|
qemuMonitorQueryCpusFree(struct qemuMonitorQueryCpusEntry *entries,
|
2016-07-28 08:33:10 +00:00
|
|
|
size_t nentries)
|
2016-08-01 11:44:25 +00:00
|
|
|
{
|
2016-07-28 08:33:10 +00:00
|
|
|
size_t i;
|
|
|
|
|
2016-08-01 11:44:25 +00:00
|
|
|
if (!entries)
|
|
|
|
return;
|
|
|
|
|
2016-07-28 08:33:10 +00:00
|
|
|
for (i = 0; i < nentries; i++)
|
|
|
|
VIR_FREE(entries[i].qom_path);
|
|
|
|
|
2016-08-01 11:44:25 +00:00
|
|
|
VIR_FREE(entries);
|
|
|
|
}
|
|
|
|
|
2016-08-01 05:43:32 +00:00
|
|
|
|
2016-08-01 11:56:23 +00:00
|
|
|
/**
|
|
|
|
* Legacy approach doesn't allow out of order cpus, thus no complex matching
|
|
|
|
* algorithm is necessary */
|
|
|
|
static void
|
|
|
|
qemuMonitorGetCPUInfoLegacy(struct qemuMonitorQueryCpusEntry *cpuentries,
|
|
|
|
size_t ncpuentries,
|
|
|
|
qemuMonitorCPUInfoPtr vcpus,
|
|
|
|
size_t maxvcpus)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < maxvcpus; i++) {
|
2016-10-13 11:42:44 +00:00
|
|
|
if (i < ncpuentries) {
|
2016-08-01 11:56:23 +00:00
|
|
|
vcpus[i].tid = cpuentries[i].tid;
|
2016-10-13 11:42:44 +00:00
|
|
|
vcpus[i].halted = cpuentries[i].halted;
|
2016-11-22 08:32:11 +00:00
|
|
|
vcpus[i].qemu_id = cpuentries[i].qemu_id;
|
2016-10-13 11:42:44 +00:00
|
|
|
}
|
2016-08-01 11:56:23 +00:00
|
|
|
|
|
|
|
/* for legacy hotplug to work we need to fake the vcpu count added by
|
|
|
|
* enabling a given vcpu */
|
|
|
|
vcpus[i].vcpus = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuMonitorGetCPUInfoHotplug:
|
|
|
|
*
|
|
|
|
* This function stitches together data retrieved via query-hotpluggable-cpus
|
|
|
|
* which returns entities on the hotpluggable level (which may describe more
|
2018-04-04 14:45:03 +00:00
|
|
|
* than one guest logical vcpu) with the output of query-cpus (or
|
|
|
|
* query-cpus-fast), having an entry per enabled guest logical vcpu.
|
2016-08-01 11:56:23 +00:00
|
|
|
*
|
|
|
|
* query-hotpluggable-cpus conveys following information:
|
|
|
|
* - topology information and number of logical vcpus this entry creates
|
|
|
|
* - device type name of the entry that needs to be used when hotplugging
|
2018-04-04 14:45:03 +00:00
|
|
|
* - qom path in qemu which can be used to map the entry against
|
|
|
|
* query-cpus[-fast]
|
2016-08-01 11:56:23 +00:00
|
|
|
*
|
2018-04-04 14:45:03 +00:00
|
|
|
* query-cpus[-fast] conveys following information:
|
2016-08-01 11:56:23 +00:00
|
|
|
* - thread id of a given guest logical vcpu
|
|
|
|
* - order in which the vcpus were inserted
|
|
|
|
* - qom path to allow mapping the two together
|
|
|
|
*
|
|
|
|
* The libvirt's internal structure has an entry for each possible (even
|
|
|
|
* disabled) guest vcpu. The purpose is to map the data together so that we are
|
|
|
|
* certain of the thread id mapping and the information required for vcpu
|
|
|
|
* hotplug.
|
|
|
|
*
|
|
|
|
* This function returns 0 on success and -1 on error, but does not report
|
|
|
|
* libvirt errors so that fallback approach can be used.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
qemuMonitorGetCPUInfoHotplug(struct qemuMonitorQueryHotpluggableCpusEntry *hotplugvcpus,
|
|
|
|
size_t nhotplugvcpus,
|
|
|
|
struct qemuMonitorQueryCpusEntry *cpuentries,
|
|
|
|
size_t ncpuentries,
|
|
|
|
qemuMonitorCPUInfoPtr vcpus,
|
|
|
|
size_t maxvcpus)
|
|
|
|
{
|
|
|
|
char *tmp;
|
|
|
|
int order = 1;
|
|
|
|
size_t totalvcpus = 0;
|
2016-09-13 15:28:02 +00:00
|
|
|
size_t mastervcpu; /* this iterator is used for iterating hotpluggable entities */
|
2016-09-13 15:52:38 +00:00
|
|
|
size_t slavevcpu; /* this corresponds to subentries of a hotpluggable entry */
|
2016-09-13 15:38:08 +00:00
|
|
|
size_t anyvcpu; /* this iterator is used for any vcpu entry in the result */
|
2016-08-01 11:56:23 +00:00
|
|
|
size_t i;
|
|
|
|
size_t j;
|
|
|
|
|
|
|
|
/* ensure that the total vcpu count reported by query-hotpluggable-cpus equals
|
|
|
|
* to the libvirt maximum cpu count */
|
|
|
|
for (i = 0; i < nhotplugvcpus; i++)
|
|
|
|
totalvcpus += hotplugvcpus[i].vcpus;
|
|
|
|
|
2018-04-04 14:45:03 +00:00
|
|
|
/* trim '/thread...' suffix from the data returned by query-cpus[-fast] */
|
2016-08-01 11:56:23 +00:00
|
|
|
for (i = 0; i < ncpuentries; i++) {
|
|
|
|
if (cpuentries[i].qom_path &&
|
|
|
|
(tmp = strstr(cpuentries[i].qom_path, "/thread")))
|
|
|
|
*tmp = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
if (totalvcpus != maxvcpus) {
|
|
|
|
VIR_DEBUG("expected '%zu' total vcpus got '%zu'", maxvcpus, totalvcpus);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Note the order in which the hotpluggable entities are inserted by
|
2018-04-04 14:45:03 +00:00
|
|
|
* matching them to the query-cpus[-fast] entries */
|
2016-08-01 11:56:23 +00:00
|
|
|
for (i = 0; i < ncpuentries; i++) {
|
|
|
|
for (j = 0; j < nhotplugvcpus; j++) {
|
|
|
|
if (!cpuentries[i].qom_path ||
|
|
|
|
!hotplugvcpus[j].qom_path ||
|
|
|
|
STRNEQ(cpuentries[i].qom_path, hotplugvcpus[j].qom_path))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* add ordering info for hotpluggable entries */
|
|
|
|
if (hotplugvcpus[j].enable_id == 0)
|
|
|
|
hotplugvcpus[j].enable_id = order++;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* transfer appropriate data from the hotpluggable list to corresponding
|
|
|
|
* entries. the entries returned by qemu may in fact describe multiple
|
|
|
|
* logical vcpus in the guest */
|
2016-09-13 15:28:02 +00:00
|
|
|
mastervcpu = 0;
|
2016-08-01 11:56:23 +00:00
|
|
|
for (i = 0; i < nhotplugvcpus; i++) {
|
2016-09-13 15:52:38 +00:00
|
|
|
vcpus[mastervcpu].online = !!hotplugvcpus[i].qom_path;
|
|
|
|
vcpus[mastervcpu].hotpluggable = !!hotplugvcpus[i].alias ||
|
|
|
|
!vcpus[mastervcpu].online;
|
2016-09-13 15:28:02 +00:00
|
|
|
vcpus[mastervcpu].socket_id = hotplugvcpus[i].socket_id;
|
|
|
|
vcpus[mastervcpu].core_id = hotplugvcpus[i].core_id;
|
|
|
|
vcpus[mastervcpu].thread_id = hotplugvcpus[i].thread_id;
|
2017-06-27 14:04:38 +00:00
|
|
|
vcpus[mastervcpu].node_id = hotplugvcpus[i].node_id;
|
2016-09-13 15:28:02 +00:00
|
|
|
vcpus[mastervcpu].vcpus = hotplugvcpus[i].vcpus;
|
2019-10-16 11:43:18 +00:00
|
|
|
vcpus[mastervcpu].qom_path = g_steal_pointer(&hotplugvcpus[i].qom_path);
|
|
|
|
vcpus[mastervcpu].alias = g_steal_pointer(&hotplugvcpus[i].alias);
|
|
|
|
vcpus[mastervcpu].type = g_steal_pointer(&hotplugvcpus[i].type);
|
|
|
|
vcpus[mastervcpu].props = g_steal_pointer(&hotplugvcpus[i].props);
|
2016-09-13 15:28:02 +00:00
|
|
|
vcpus[mastervcpu].id = hotplugvcpus[i].enable_id;
|
|
|
|
|
2016-09-13 15:52:38 +00:00
|
|
|
/* copy state information to slave vcpus */
|
|
|
|
for (slavevcpu = mastervcpu + 1; slavevcpu < mastervcpu + hotplugvcpus[i].vcpus; slavevcpu++) {
|
|
|
|
vcpus[slavevcpu].online = vcpus[mastervcpu].online;
|
|
|
|
vcpus[slavevcpu].hotpluggable = vcpus[mastervcpu].hotpluggable;
|
|
|
|
}
|
|
|
|
|
2016-09-13 15:28:02 +00:00
|
|
|
/* calculate next master vcpu (hotpluggable unit) entry */
|
|
|
|
mastervcpu += hotplugvcpus[i].vcpus;
|
2016-08-01 11:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* match entries from query cpus to the output array taking into account
|
|
|
|
* multi-vcpu objects */
|
|
|
|
for (j = 0; j < ncpuentries; j++) {
|
|
|
|
/* find the correct entry or beginning of group of entries */
|
2016-09-13 15:38:08 +00:00
|
|
|
for (anyvcpu = 0; anyvcpu < maxvcpus; anyvcpu++) {
|
|
|
|
if (cpuentries[j].qom_path && vcpus[anyvcpu].qom_path &&
|
|
|
|
STREQ(cpuentries[j].qom_path, vcpus[anyvcpu].qom_path))
|
2016-08-01 11:56:23 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-09-13 15:38:08 +00:00
|
|
|
if (anyvcpu == maxvcpus) {
|
2018-04-04 14:45:03 +00:00
|
|
|
VIR_DEBUG("too many query-cpus[-fast] entries for a given "
|
2016-08-01 11:56:23 +00:00
|
|
|
"query-hotpluggable-cpus entry");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-09-13 15:38:08 +00:00
|
|
|
if (vcpus[anyvcpu].vcpus != 1) {
|
2016-08-01 11:56:23 +00:00
|
|
|
/* find a possibly empty vcpu thread for core granularity systems */
|
2016-09-13 15:38:08 +00:00
|
|
|
for (; anyvcpu < maxvcpus; anyvcpu++) {
|
|
|
|
if (vcpus[anyvcpu].tid == 0)
|
2016-08-01 11:56:23 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-22 08:32:11 +00:00
|
|
|
vcpus[anyvcpu].qemu_id = cpuentries[j].qemu_id;
|
2016-09-13 15:38:08 +00:00
|
|
|
vcpus[anyvcpu].tid = cpuentries[j].tid;
|
2016-10-13 11:42:44 +00:00
|
|
|
vcpus[anyvcpu].halted = cpuentries[j].halted;
|
2016-08-01 11:56:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-29 13:30:23 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorGetCPUInfo:
|
|
|
|
* @mon: monitor
|
2016-08-01 05:43:32 +00:00
|
|
|
* @vcpus: pointer filled by array of qemuMonitorCPUInfo structures
|
|
|
|
* @maxvcpus: total possible number of vcpus
|
2016-08-01 11:56:23 +00:00
|
|
|
* @hotplug: query data relevant for hotplug support
|
2018-04-04 14:45:03 +00:00
|
|
|
* @fast: use QMP query-cpus-fast if supported
|
2016-08-01 05:43:32 +00:00
|
|
|
*
|
|
|
|
* Detects VCPU information. If qemu doesn't support or fails reporting
|
|
|
|
* information this function will return success as other parts of libvirt
|
|
|
|
* are able to cope with that.
|
2015-10-29 13:30:23 +00:00
|
|
|
*
|
2016-08-01 05:43:32 +00:00
|
|
|
* Returns 0 on success (including if qemu didn't report any data) and
|
|
|
|
* -1 on error (reports libvirt error).
|
2015-10-29 13:30:23 +00:00
|
|
|
*/
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
|
2016-08-01 05:43:32 +00:00
|
|
|
qemuMonitorCPUInfoPtr *vcpus,
|
2016-08-01 11:56:23 +00:00
|
|
|
size_t maxvcpus,
|
2018-04-04 14:45:03 +00:00
|
|
|
bool hotplug,
|
|
|
|
bool fast)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2016-08-01 11:56:23 +00:00
|
|
|
struct qemuMonitorQueryHotpluggableCpusEntry *hotplugcpus = NULL;
|
|
|
|
size_t nhotplugcpus = 0;
|
2016-08-01 11:44:25 +00:00
|
|
|
struct qemuMonitorQueryCpusEntry *cpuentries = NULL;
|
|
|
|
size_t ncpuentries = 0;
|
2016-08-01 05:43:32 +00:00
|
|
|
int ret = -1;
|
|
|
|
int rc;
|
2016-08-01 11:56:23 +00:00
|
|
|
qemuMonitorCPUInfoPtr info = NULL;
|
2016-08-01 05:43:32 +00:00
|
|
|
|
2016-09-30 10:45:59 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2016-08-01 05:43:32 +00:00
|
|
|
if (VIR_ALLOC_N(info, maxvcpus) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2016-08-01 11:56:23 +00:00
|
|
|
/* initialize a few non-zero defaults */
|
|
|
|
qemuMonitorCPUInfoClear(info, maxvcpus);
|
|
|
|
|
|
|
|
if (hotplug &&
|
|
|
|
(qemuMonitorJSONGetHotpluggableCPUs(mon, &hotplugcpus, &nhotplugcpus)) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
rc = qemuMonitorJSONQueryCPUs(mon, &cpuentries, &ncpuentries, hotplug,
|
|
|
|
fast);
|
2016-08-01 05:43:32 +00:00
|
|
|
|
|
|
|
if (rc < 0) {
|
2016-12-04 17:53:03 +00:00
|
|
|
if (!hotplug && rc == -2) {
|
2019-10-16 11:43:18 +00:00
|
|
|
*vcpus = g_steal_pointer(&info);
|
2016-08-01 11:44:25 +00:00
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
|
2016-08-01 05:43:32 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2016-08-01 11:56:23 +00:00
|
|
|
if (!hotplugcpus ||
|
|
|
|
qemuMonitorGetCPUInfoHotplug(hotplugcpus, nhotplugcpus,
|
|
|
|
cpuentries, ncpuentries,
|
|
|
|
info, maxvcpus) < 0) {
|
|
|
|
/* Fallback to the legacy algorithm. Hotplug paths will make sure that
|
2018-12-04 17:08:14 +00:00
|
|
|
* the appropriate data is present */
|
2016-08-01 11:56:23 +00:00
|
|
|
qemuMonitorCPUInfoClear(info, maxvcpus);
|
|
|
|
qemuMonitorGetCPUInfoLegacy(cpuentries, ncpuentries, info, maxvcpus);
|
|
|
|
}
|
2016-08-01 05:43:32 +00:00
|
|
|
|
2019-10-16 11:43:18 +00:00
|
|
|
*vcpus = g_steal_pointer(&info);
|
2016-08-01 05:43:32 +00:00
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
2016-08-01 11:56:23 +00:00
|
|
|
qemuMonitorQueryHotpluggableCpusFree(hotplugcpus, nhotplugcpus);
|
2016-08-01 11:44:25 +00:00
|
|
|
qemuMonitorQueryCpusFree(cpuentries, ncpuentries);
|
2016-08-01 11:56:23 +00:00
|
|
|
qemuMonitorCPUInfoFree(info, maxvcpus);
|
2016-08-01 05:43:32 +00:00
|
|
|
return ret;
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2016-11-21 13:54:35 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorGetCpuHalted:
|
|
|
|
*
|
|
|
|
* Returns a bitmap of vcpu id's that are halted. The id's correspond to the
|
2018-04-04 14:45:03 +00:00
|
|
|
* 'CPU' field as reported by query-cpus[-fast]'.
|
2016-11-21 13:54:35 +00:00
|
|
|
*/
|
|
|
|
virBitmapPtr
|
|
|
|
qemuMonitorGetCpuHalted(qemuMonitorPtr mon,
|
2018-04-04 14:45:03 +00:00
|
|
|
size_t maxvcpus,
|
2018-04-04 14:45:05 +00:00
|
|
|
bool fast)
|
2016-11-21 13:54:35 +00:00
|
|
|
{
|
|
|
|
struct qemuMonitorQueryCpusEntry *cpuentries = NULL;
|
|
|
|
size_t ncpuentries = 0;
|
|
|
|
size_t i;
|
|
|
|
int rc;
|
|
|
|
virBitmapPtr ret = NULL;
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
rc = qemuMonitorJSONQueryCPUs(mon, &cpuentries, &ncpuentries, false,
|
|
|
|
fast);
|
2016-11-21 13:54:35 +00:00
|
|
|
|
|
|
|
if (rc < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(ret = virBitmapNew(maxvcpus)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < ncpuentries; i++) {
|
|
|
|
if (cpuentries[i].halted)
|
|
|
|
ignore_value(virBitmapSetBit(ret, cpuentries[i].qemu_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
qemuMonitorQueryCpusFree(cpuentries, ncpuentries);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetLink(qemuMonitorPtr mon,
|
|
|
|
const char *name,
|
|
|
|
virDomainNetInterfaceLinkState state)
|
2011-09-06 08:18:57 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("name=%s, state=%u", name, state);
|
2011-09-06 08:18:57 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-09-06 08:18:57 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSetLink(mon, name, state);
|
2011-09-06 08:18:57 +00:00
|
|
|
}
|
2011-06-17 14:31:45 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorGetVirtType(qemuMonitorPtr mon,
|
2015-09-17 08:46:56 +00:00
|
|
|
virDomainVirtType *virtType)
|
2011-06-17 14:31:45 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-06-17 14:31:45 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONGetVirtType(mon, virtType);
|
2011-06-17 14:31:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-27 11:42:32 +00:00
|
|
|
/**
|
|
|
|
* Returns: 0 if balloon not supported, +1 if balloon query worked
|
|
|
|
* or -1 on failure
|
|
|
|
*/
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetBalloonInfo(qemuMonitorPtr mon,
|
|
|
|
unsigned long long *currmem)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONGetBalloonInfo(mon, currmem);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
|
2016-07-25 15:07:38 +00:00
|
|
|
virDomainMemballoonDefPtr balloon,
|
2015-04-14 13:14:23 +00:00
|
|
|
virDomainMemoryStatPtr stats,
|
|
|
|
unsigned int nr_stats)
|
2010-04-12 11:31:15 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("stats=%p nstats=%u", stats, nr_stats);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-04-12 11:31:15 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
qemuMonitorInitBalloonObjectPath(mon, balloon);
|
|
|
|
return qemuMonitorJSONGetMemoryStats(mon, mon->balloonpath,
|
|
|
|
stats, nr_stats);
|
2010-04-12 11:31:15 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2015-03-13 16:05:32 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorSetMemoryStatsPeriod:
|
|
|
|
*
|
|
|
|
* This function sets balloon stats update period.
|
|
|
|
*
|
|
|
|
* Returns 0 on success and -1 on error, but does *not* set an error.
|
|
|
|
*/
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetMemoryStatsPeriod(qemuMonitorPtr mon,
|
2016-07-25 15:07:38 +00:00
|
|
|
virDomainMemballoonDefPtr balloon,
|
2015-04-14 13:14:23 +00:00
|
|
|
int period)
|
2013-06-27 15:00:31 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
VIR_DEBUG("mon=%p period=%d", mon, period);
|
|
|
|
|
2015-03-13 16:05:32 +00:00
|
|
|
if (!mon)
|
2013-06-27 15:00:31 +00:00
|
|
|
return -1;
|
|
|
|
|
2015-03-13 16:05:32 +00:00
|
|
|
if (period < 0)
|
2013-06-27 15:00:31 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-07-25 15:07:38 +00:00
|
|
|
qemuMonitorInitBalloonObjectPath(mon, balloon);
|
2015-06-04 13:44:29 +00:00
|
|
|
if (mon->balloonpath) {
|
2013-06-27 15:00:31 +00:00
|
|
|
ret = qemuMonitorJSONSetMemoryStatsPeriod(mon, mon->balloonpath,
|
|
|
|
period);
|
2015-03-13 16:05:32 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Most of the calls to this function are supposed to be
|
|
|
|
* non-fatal and the only one that should be fatal wants its
|
|
|
|
* own error message. More details for debugging will be in
|
|
|
|
* the log file.
|
|
|
|
*/
|
|
|
|
if (ret < 0)
|
|
|
|
virResetLastError();
|
2013-06-27 15:00:31 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2012-01-19 16:58:58 +00:00
|
|
|
int
|
|
|
|
qemuMonitorBlockIOStatusToError(const char *status)
|
|
|
|
{
|
|
|
|
int st = qemuMonitorBlockIOStatusTypeFromString(status);
|
|
|
|
|
|
|
|
if (st < 0) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown block IO status: %s"), status);
|
2012-01-19 16:58:58 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ((qemuMonitorBlockIOStatus) st) {
|
|
|
|
case QEMU_MONITOR_BLOCK_IO_STATUS_OK:
|
|
|
|
return VIR_DOMAIN_DISK_ERROR_NONE;
|
|
|
|
case QEMU_MONITOR_BLOCK_IO_STATUS_FAILED:
|
|
|
|
return VIR_DOMAIN_DISK_ERROR_UNSPEC;
|
|
|
|
case QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE:
|
|
|
|
return VIR_DOMAIN_DISK_ERROR_NO_SPACE;
|
|
|
|
|
|
|
|
/* unreachable */
|
|
|
|
case QEMU_MONITOR_BLOCK_IO_STATUS_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2017-02-23 18:36:52 +00:00
|
|
|
static void
|
2019-11-21 19:27:58 +00:00
|
|
|
qemuDomainDiskInfoFree(void *value)
|
2017-02-23 18:36:52 +00:00
|
|
|
{
|
|
|
|
struct qemuDomainDiskInfo *info = value;
|
|
|
|
|
|
|
|
VIR_FREE(info->nodename);
|
|
|
|
VIR_FREE(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-18 21:01:30 +00:00
|
|
|
virHashTablePtr
|
|
|
|
qemuMonitorGetBlockInfo(qemuMonitorPtr mon)
|
2011-09-13 13:49:50 +00:00
|
|
|
{
|
|
|
|
int ret;
|
2012-01-18 21:01:30 +00:00
|
|
|
virHashTablePtr table;
|
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
2011-09-13 13:49:50 +00:00
|
|
|
|
2017-02-23 18:36:52 +00:00
|
|
|
if (!(table = virHashCreate(32, qemuDomainDiskInfoFree)))
|
2012-01-18 21:01:30 +00:00
|
|
|
return NULL;
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
ret = qemuMonitorJSONGetBlockInfo(mon, table);
|
2012-01-18 21:01:30 +00:00
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
virHashFree(table);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2017-07-24 10:51:10 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorQueryBlockstats:
|
|
|
|
* @mon: monitor object
|
|
|
|
*
|
|
|
|
* Returns data from a call to 'query-blockstats'.
|
|
|
|
*/
|
|
|
|
virJSONValuePtr
|
2018-07-30 15:08:37 +00:00
|
|
|
qemuMonitorQueryBlockstats(qemuMonitorPtr mon)
|
2017-07-24 10:51:10 +00:00
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
2017-07-24 10:51:10 +00:00
|
|
|
|
2018-07-30 15:08:37 +00:00
|
|
|
return qemuMonitorJSONQueryBlockstats(mon);
|
2017-07-24 10:51:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-10 13:40:58 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorGetAllBlockStatsInfo:
|
|
|
|
* @mon: monitor object
|
|
|
|
* @ret_stats: pointer that is filled with a hash table containing the stats
|
|
|
|
* @backingChain: recurse into the backing chain of devices
|
|
|
|
*
|
|
|
|
* Creates a hash table in @ret_stats with block stats of all devices. In case
|
|
|
|
* @backingChain is true @ret_stats will additionally contain stats for
|
|
|
|
* backing chain members of block devices.
|
|
|
|
*
|
|
|
|
* Returns < 0 on error, count of supported block stats fields on success.
|
2014-09-15 08:48:09 +00:00
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
|
2014-12-11 22:28:41 +00:00
|
|
|
virHashTablePtr *ret_stats,
|
|
|
|
bool backingChain)
|
2014-09-15 08:48:09 +00:00
|
|
|
{
|
2015-03-10 13:40:58 +00:00
|
|
|
int ret = -1;
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("ret_stats=%p, backing=%d", ret_stats, backingChain);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2014-09-15 08:48:09 +00:00
|
|
|
|
2015-03-10 09:02:40 +00:00
|
|
|
if (!(*ret_stats = virHashCreate(10, virHashValueFree)))
|
|
|
|
goto error;
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
ret = qemuMonitorJSONGetAllBlockStatsInfo(mon, *ret_stats,
|
|
|
|
backingChain);
|
2015-03-10 09:02:40 +00:00
|
|
|
|
2015-03-10 13:40:58 +00:00
|
|
|
if (ret < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
return ret;
|
2015-03-10 09:02:40 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
virHashFree(*ret_stats);
|
|
|
|
*ret_stats = NULL;
|
|
|
|
return -1;
|
2014-09-15 08:48:09 +00:00
|
|
|
}
|
|
|
|
|
2014-09-25 10:03:26 +00:00
|
|
|
|
|
|
|
/* Updates "stats" to fill virtual and physical size of the image */
|
2014-12-11 22:28:41 +00:00
|
|
|
int
|
|
|
|
qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon,
|
|
|
|
virHashTablePtr stats,
|
|
|
|
bool backingChain)
|
2014-09-25 10:03:26 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("stats=%p, backing=%d", stats, backingChain);
|
2014-09-25 10:03:26 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2014-09-25 10:03:26 +00:00
|
|
|
|
2014-12-11 22:28:41 +00:00
|
|
|
return qemuMonitorJSONBlockStatsUpdateCapacity(mon, stats, backingChain);
|
2014-09-25 10:03:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-28 10:35:16 +00:00
|
|
|
int
|
|
|
|
qemuMonitorBlockStatsUpdateCapacityBlockdev(qemuMonitorPtr mon,
|
|
|
|
virHashTablePtr stats)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("stats=%p", stats);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONBlockStatsUpdateCapacityBlockdev(mon, stats);
|
|
|
|
}
|
|
|
|
|
2019-10-09 12:13:10 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuMonitorBlockGetNamedNodeData:
|
|
|
|
* @mon: monitor object
|
|
|
|
*
|
|
|
|
* Uses 'query-named-block-nodes' to retrieve information about individual
|
|
|
|
* storage nodes and returns them in a hash table of qemuBlockNamedNodeDataPtrs
|
|
|
|
* filled with the data. The hash table keys are node names.
|
|
|
|
*/
|
|
|
|
virHashTablePtr
|
|
|
|
qemuMonitorBlockGetNamedNodeData(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONBlockGetNamedNodeData(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorBlockResize(qemuMonitorPtr mon,
|
|
|
|
const char *device,
|
2018-08-07 07:31:04 +00:00
|
|
|
const char *nodename,
|
2015-04-14 13:14:23 +00:00
|
|
|
unsigned long long size)
|
2011-11-29 07:34:53 +00:00
|
|
|
{
|
2018-08-07 07:31:04 +00:00
|
|
|
VIR_DEBUG("device=%s nodename=%s size=%llu",
|
|
|
|
NULLSTR(device), NULLSTR(nodename), size);
|
2015-04-14 15:52:48 +00:00
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-11-29 07:34:53 +00:00
|
|
|
|
2018-08-07 07:31:04 +00:00
|
|
|
if ((!device && !nodename) || (device && nodename)) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("exactly one of 'device' and 'nodename' need to be specified"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return qemuMonitorJSONBlockResize(mon, device, nodename, size);
|
2011-11-29 07:34:53 +00:00
|
|
|
}
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
static const char *
|
|
|
|
qemuMonitorTypeToProtocol(int type)
|
2011-01-10 11:12:32 +00:00
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
|
|
|
|
return "vnc";
|
|
|
|
case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
|
|
|
|
return "spice";
|
|
|
|
default:
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG,
|
|
|
|
_("unsupported protocol type %s"),
|
|
|
|
virDomainGraphicsTypeToString(type));
|
2011-01-10 11:12:32 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorSetPassword(qemuMonitorPtr mon,
|
|
|
|
int type,
|
|
|
|
const char *password,
|
|
|
|
const char *action_if_connected)
|
2011-01-10 11:12:32 +00:00
|
|
|
{
|
|
|
|
const char *protocol = qemuMonitorTypeToProtocol(type);
|
|
|
|
|
|
|
|
if (!protocol)
|
|
|
|
return -1;
|
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("protocol=%s, password=%p, action_if_connected=%s",
|
|
|
|
protocol, password, action_if_connected);
|
2011-01-10 11:12:32 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-01-10 11:12:32 +00:00
|
|
|
|
|
|
|
if (!password)
|
|
|
|
password = "";
|
|
|
|
|
|
|
|
if (!action_if_connected)
|
|
|
|
action_if_connected = "keep";
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSetPassword(mon, protocol, password, action_if_connected);
|
2011-01-10 11:12:32 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorExpirePassword(qemuMonitorPtr mon,
|
|
|
|
int type,
|
|
|
|
const char *expire_time)
|
2011-01-10 11:12:32 +00:00
|
|
|
{
|
|
|
|
const char *protocol = qemuMonitorTypeToProtocol(type);
|
|
|
|
|
|
|
|
if (!protocol)
|
|
|
|
return -1;
|
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("protocol=%s, expire_time=%s", protocol, expire_time);
|
2011-01-10 11:12:32 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-01-10 11:12:32 +00:00
|
|
|
|
|
|
|
if (!expire_time)
|
|
|
|
expire_time = "now";
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONExpirePassword(mon, protocol, expire_time);
|
2011-01-10 11:12:32 +00:00
|
|
|
}
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2015-05-27 12:03:17 +00:00
|
|
|
/*
|
|
|
|
* Returns: 0 if balloon not supported, +1 if balloon adjust worked
|
|
|
|
* or -1 on failure
|
|
|
|
*/
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetBalloon(qemuMonitorPtr mon,
|
2015-05-27 12:03:17 +00:00
|
|
|
unsigned long long newmem)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-05-27 12:03:17 +00:00
|
|
|
VIR_DEBUG("newmem=%llu", newmem);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSetBalloon(mon, newmem);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
2010-02-08 16:37:17 +00:00
|
|
|
|
2015-10-27 13:26:03 +00:00
|
|
|
/*
|
|
|
|
* Returns: 0 if CPU modification was successful or -1 on failure
|
|
|
|
*/
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetCPU(qemuMonitorPtr mon, int cpu, bool online)
|
2010-02-08 16:37:17 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("cpu=%d online=%d", cpu, online);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-02-08 16:37:17 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSetCPU(mon, cpu, online);
|
2010-02-08 16:37:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorEjectMedia(qemuMonitorPtr mon,
|
|
|
|
const char *dev_name,
|
|
|
|
bool force)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("dev_name=%s force=%d", dev_name, force);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONEjectMedia(mon, dev_name, force);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorChangeMedia(qemuMonitorPtr mon,
|
|
|
|
const char *dev_name,
|
|
|
|
const char *newmedia,
|
|
|
|
const char *format)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("dev_name=%s newmedia=%s format=%s", dev_name, newmedia, format);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONChangeMedia(mon, dev_name, newmedia, format);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSaveVirtualMemory(qemuMonitorPtr mon,
|
|
|
|
unsigned long long offset,
|
2019-09-27 11:29:53 +00:00
|
|
|
unsigned long long length,
|
2015-04-14 13:14:23 +00:00
|
|
|
const char *path)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2019-09-27 11:29:53 +00:00
|
|
|
VIR_DEBUG("offset=%llu length=%llu path=%s", offset, length, path);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSaveVirtualMemory(mon, offset, length, path);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorSavePhysicalMemory(qemuMonitorPtr mon,
|
|
|
|
unsigned long long offset,
|
2019-09-27 11:29:53 +00:00
|
|
|
unsigned long long length,
|
2015-04-14 13:14:23 +00:00
|
|
|
const char *path)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2019-09-27 11:29:53 +00:00
|
|
|
VIR_DEBUG("offset=%llu length=%llu path=%s", offset, length, path);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSavePhysicalMemory(mon, offset, length, path);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon,
|
|
|
|
unsigned long bandwidth)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("bandwidth=%lu", bandwidth);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2014-04-11 09:24:51 +00:00
|
|
|
if (bandwidth > QEMU_DOMAIN_MIG_BANDWIDTH_MAX) {
|
|
|
|
virReportError(VIR_ERR_OVERFLOW,
|
|
|
|
_("bandwidth must be less than %llu"),
|
|
|
|
QEMU_DOMAIN_MIG_BANDWIDTH_MAX + 1ULL);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSetMigrationSpeed(mon, bandwidth);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
2010-03-17 15:53:14 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetMigrationDowntime(qemuMonitorPtr mon,
|
|
|
|
unsigned long long downtime)
|
2010-03-17 15:53:14 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("downtime=%llu", downtime);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-03-17 15:53:14 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSetMigrationDowntime(mon, downtime);
|
2010-03-17 15:53:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-18 20:54:58 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetMigrationCacheSize(qemuMonitorPtr mon,
|
|
|
|
unsigned long long *cacheSize)
|
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("cacheSize=%p", cacheSize);
|
2013-02-18 20:54:58 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-02-18 20:54:58 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetMigrationCacheSize(mon, cacheSize);
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2013-02-18 20:54:58 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetMigrationCacheSize(qemuMonitorPtr mon,
|
|
|
|
unsigned long long cacheSize)
|
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("cacheSize=%llu", cacheSize);
|
2013-02-18 20:54:58 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-02-18 20:54:58 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONSetMigrationCacheSize(mon, cacheSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-15 17:06:01 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorGetMigrationParams:
|
|
|
|
* @mon: Pointer to the monitor object.
|
|
|
|
* @params: Where to store migration parameters.
|
|
|
|
*
|
|
|
|
* If QEMU does not support querying migration parameters, the function will
|
|
|
|
* set @params to NULL and return 0 (success). The caller is responsible for
|
|
|
|
* freeing @params.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
|
|
|
*/
|
2016-04-14 10:33:49 +00:00
|
|
|
int
|
2016-06-20 13:47:46 +00:00
|
|
|
qemuMonitorGetMigrationParams(qemuMonitorPtr mon,
|
2018-03-15 17:06:01 +00:00
|
|
|
virJSONValuePtr *params)
|
2016-04-14 10:33:49 +00:00
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2016-04-14 10:33:49 +00:00
|
|
|
|
2016-06-20 13:47:46 +00:00
|
|
|
return qemuMonitorJSONGetMigrationParams(mon, params);
|
2016-04-14 10:33:49 +00:00
|
|
|
}
|
|
|
|
|
2018-03-15 19:24:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuMonitorSetMigrationParams:
|
|
|
|
* @mon: Pointer to the monitor object.
|
|
|
|
* @params: Migration parameters.
|
|
|
|
*
|
|
|
|
* The @params object is consumed and should not be referenced by the caller
|
|
|
|
* after this function returns.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
|
|
|
*/
|
2016-04-14 10:33:49 +00:00
|
|
|
int
|
2016-06-20 13:47:46 +00:00
|
|
|
qemuMonitorSetMigrationParams(qemuMonitorPtr mon,
|
2018-03-15 19:24:05 +00:00
|
|
|
virJSONValuePtr params)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_GOTO(mon, error);
|
2016-04-14 10:33:49 +00:00
|
|
|
|
2016-06-20 13:47:46 +00:00
|
|
|
return qemuMonitorJSONSetMigrationParams(mon, params);
|
2018-03-15 19:24:05 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
virJSONValueFree(params);
|
|
|
|
return -1;
|
2016-04-14 10:33:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
2015-11-26 12:23:08 +00:00
|
|
|
qemuMonitorGetMigrationStats(qemuMonitorPtr mon,
|
2017-10-12 13:19:19 +00:00
|
|
|
qemuMonitorMigrationStatsPtr stats,
|
|
|
|
char **error)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2017-10-12 13:19:19 +00:00
|
|
|
if (error)
|
|
|
|
*error = NULL;
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONGetMigrationStats(mon, stats, error);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorMigrateToFd(qemuMonitorPtr mon,
|
|
|
|
unsigned int flags,
|
|
|
|
int fd)
|
2011-03-02 04:37:30 +00:00
|
|
|
{
|
|
|
|
int ret;
|
2017-09-25 10:43:33 +00:00
|
|
|
VIR_DEBUG("fd=%d flags=0x%x", fd, flags);
|
2011-03-02 04:37:30 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-03-02 04:37:30 +00:00
|
|
|
|
|
|
|
if (qemuMonitorSendFileHandle(mon, "migrate", fd) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
ret = qemuMonitorJSONMigrate(mon, flags, "fd:migrate");
|
2011-03-02 04:37:30 +00:00
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
if (qemuMonitorCloseFileHandle(mon, "migrate") < 0)
|
2011-05-09 09:24:09 +00:00
|
|
|
VIR_WARN("failed to close migration handle");
|
2011-03-02 04:37:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorMigrateToHost(qemuMonitorPtr mon,
|
|
|
|
unsigned int flags,
|
|
|
|
const char *protocol,
|
|
|
|
const char *hostname,
|
|
|
|
int port)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2009-11-03 18:59:18 +00:00
|
|
|
int ret;
|
2011-03-04 18:51:48 +00:00
|
|
|
char *uri = NULL;
|
2017-09-25 10:43:33 +00:00
|
|
|
VIR_DEBUG("hostname=%s port=%d flags=0x%x", hostname, port, flags);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2017-01-27 15:01:43 +00:00
|
|
|
if (strchr(hostname, ':')) {
|
2019-10-22 13:26:14 +00:00
|
|
|
uri = g_strdup_printf("%s:[%s]:%d", protocol, hostname, port);
|
|
|
|
} else uri = g_strdup_printf("%s:%s:%d", protocol, hostname, port);
|
2011-03-04 18:51:48 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
ret = qemuMonitorJSONMigrate(mon, flags, uri);
|
2011-03-04 18:51:48 +00:00
|
|
|
|
|
|
|
VIR_FREE(uri);
|
2009-11-03 18:59:18 +00:00
|
|
|
return ret;
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorMigrateCancel(qemuMonitorPtr mon)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONMigrateCancel(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2017-11-20 20:02:59 +00:00
|
|
|
int
|
|
|
|
qemuMonitorQueryDump(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorDumpStatsPtr stats)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2017-11-20 20:02:59 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONQueryDump(mon, stats);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-23 03:51:13 +00:00
|
|
|
/**
|
|
|
|
* Returns 1 if @capability is supported, 0 if it's not, or -1 on error.
|
|
|
|
*/
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetDumpGuestMemoryCapability(qemuMonitorPtr mon,
|
|
|
|
const char *capability)
|
2014-03-23 03:51:13 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("capability=%s", capability);
|
2014-03-23 03:51:13 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2014-03-23 03:51:13 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetDumpGuestMemoryCapability(mon, capability);
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2012-09-17 19:05:29 +00:00
|
|
|
int
|
2017-11-20 20:05:23 +00:00
|
|
|
qemuMonitorDumpToFd(qemuMonitorPtr mon,
|
|
|
|
int fd,
|
|
|
|
const char *dumpformat,
|
|
|
|
bool detach)
|
2012-06-12 03:04:51 +00:00
|
|
|
{
|
|
|
|
int ret;
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("fd=%d dumpformat=%s", fd, dumpformat);
|
2012-06-12 03:04:51 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-06-12 03:04:51 +00:00
|
|
|
|
|
|
|
if (qemuMonitorSendFileHandle(mon, "dump", fd) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2017-11-20 20:05:23 +00:00
|
|
|
ret = qemuMonitorJSONDump(mon, "fd:dump", dumpformat, detach);
|
2012-06-12 03:04:51 +00:00
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
if (qemuMonitorCloseFileHandle(mon, "dump") < 0)
|
|
|
|
VIR_WARN("failed to close dumping handle");
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2011-02-17 13:39:36 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
|
|
|
|
int type,
|
|
|
|
const char *hostname,
|
|
|
|
int port,
|
|
|
|
int tlsPort,
|
|
|
|
const char *tlsSubject)
|
2011-02-17 13:39:36 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("type=%d hostname=%s port=%d tlsPort=%d tlsSubject=%s",
|
|
|
|
type, hostname, port, tlsPort, NULLSTR(tlsSubject));
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-02-17 13:39:36 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONGraphicsRelocate(mon,
|
|
|
|
type,
|
|
|
|
hostname,
|
|
|
|
port,
|
|
|
|
tlsPort,
|
|
|
|
tlsSubject);
|
2011-02-17 13:39:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSendFileHandle(qemuMonitorPtr mon,
|
|
|
|
const char *fdname,
|
|
|
|
int fd)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("fdname=%s fd=%d", fdname, fd);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2011-03-16 01:38:06 +00:00
|
|
|
if (fd < 0) {
|
2012-07-18 15:22:03 +00:00
|
|
|
virReportError(VIR_ERR_INVALID_ARG, "%s",
|
|
|
|
_("fd must be valid"));
|
2011-03-16 01:38:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mon->hasSendFD) {
|
qemu: improve error for failed JSON commands
Only one error in qemu_monitor was already using the relatively
new OPERATION_UNSUPPORTED error, even though it is a better fit
for all of the messages related to options that are unsupported
due to the version of qemu in use rather than due to a user's
XML or .conf file choice. Suggested by Osier Yang.
* src/qemu/qemu_monitor.c (qemuMonitorSendFileHandle)
(qemuMonitorAddHostNetwork, qemuMonitorRemoveHostNetwork)
(qemuMonitorAttachDrive, qemuMonitorDiskSnapshot)
(qemuMonitorDriveMirror, qemuMonitorTransaction)
(qemuMonitorBlockCommit, qemuMonitorDrivePivot)
(qemuMonitorBlockJob, qemuMonitorSystemWakeup)
(qemuMonitorGetVersion, qemuMonitorGetMachines)
(qemuMonitorGetCPUDefinitions, qemuMonitorGetCommands)
(qemuMonitorGetEvents, qemuMonitorGetKVMState)
(qemuMonitorGetObjectTypes, qemuMonitorGetObjectProps)
(qemuMonitorGetTargetArch): Use better error category.
2012-12-04 20:24:40 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
2012-07-18 15:22:03 +00:00
|
|
|
_("qemu is not using a unix socket monitor, "
|
|
|
|
"cannot send fd %s"), fdname);
|
2011-03-16 01:38:06 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSendFileHandle(mon, fdname, fd);
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorCloseFileHandle(qemuMonitorPtr mon,
|
|
|
|
const char *fdname)
|
2009-10-09 20:13:06 +00:00
|
|
|
{
|
2011-07-13 09:16:20 +00:00
|
|
|
int ret = -1;
|
|
|
|
virErrorPtr error;
|
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("fdname=%s", fdname);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2018-12-06 17:33:04 +00:00
|
|
|
virErrorPreserveLast(&error);
|
2011-07-13 09:16:20 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR_GOTO(mon, cleanup);
|
2009-10-09 20:13:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
ret = qemuMonitorJSONCloseFileHandle(mon, fdname);
|
2011-07-13 09:16:20 +00:00
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2018-12-06 17:33:04 +00:00
|
|
|
virErrorRestore(&error);
|
2009-11-03 18:59:18 +00:00
|
|
|
return ret;
|
2009-10-09 20:13:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorAddNetdev(qemuMonitorPtr mon,
|
|
|
|
const char *netdevstr,
|
|
|
|
int *tapfd, char **tapfdName, int tapfdSize,
|
2019-08-08 14:55:13 +00:00
|
|
|
int *vhostfd, char **vhostfdName, int vhostfdSize,
|
|
|
|
int slirpfd, char *slirpfdName)
|
2010-04-15 13:52:03 +00:00
|
|
|
{
|
2011-03-16 02:21:45 +00:00
|
|
|
int ret = -1;
|
Convert 'int i' to 'size_t i' in src/qemu files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i = 0, j = 0;
|
2013-05-21 13:50:09 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("netdevstr=%s tapfd=%p tapfdName=%p tapfdSize=%d"
|
2019-08-08 14:55:13 +00:00
|
|
|
"vhostfd=%p vhostfdName=%p vhostfdSize=%d"
|
|
|
|
"slirpfd=%d slirpfdName=%s",
|
2015-04-14 15:52:48 +00:00
|
|
|
netdevstr, tapfd, tapfdName, tapfdSize,
|
2019-08-08 14:55:13 +00:00
|
|
|
vhostfd, vhostfdName, vhostfdSize, slirpfd, slirpfdName);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-04-15 13:52:03 +00:00
|
|
|
|
2013-05-21 13:50:09 +00:00
|
|
|
for (i = 0; i < tapfdSize; i++) {
|
|
|
|
if (qemuMonitorSendFileHandle(mon, tapfdName[i], tapfd[i]) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
for (j = 0; j < vhostfdSize; j++) {
|
|
|
|
if (qemuMonitorSendFileHandle(mon, vhostfdName[j], vhostfd[j]) < 0)
|
|
|
|
goto cleanup;
|
2011-03-16 02:21:45 +00:00
|
|
|
}
|
|
|
|
|
2019-08-08 14:55:13 +00:00
|
|
|
if (slirpfd > 0 &&
|
|
|
|
qemuMonitorSendFileHandle(mon, slirpfdName, slirpfd) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
ret = qemuMonitorJSONAddNetdev(mon, netdevstr);
|
2011-03-16 02:21:45 +00:00
|
|
|
|
2014-03-25 06:49:44 +00:00
|
|
|
cleanup:
|
2011-03-16 02:21:45 +00:00
|
|
|
if (ret < 0) {
|
2013-05-21 13:50:09 +00:00
|
|
|
while (i--) {
|
|
|
|
if (qemuMonitorCloseFileHandle(mon, tapfdName[i]) < 0)
|
|
|
|
VIR_WARN("failed to close device handle '%s'", tapfdName[i]);
|
|
|
|
}
|
|
|
|
while (j--) {
|
|
|
|
if (qemuMonitorCloseFileHandle(mon, vhostfdName[j]) < 0)
|
|
|
|
VIR_WARN("failed to close device handle '%s'", vhostfdName[j]);
|
|
|
|
}
|
2019-08-08 14:55:13 +00:00
|
|
|
if (qemuMonitorCloseFileHandle(mon, slirpfdName) < 0)
|
|
|
|
VIR_WARN("failed to close device handle '%s'", slirpfdName);
|
2011-03-16 02:21:45 +00:00
|
|
|
}
|
|
|
|
|
2010-04-15 13:52:03 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
|
|
|
|
const char *alias)
|
2010-04-15 13:52:03 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("alias=%s", alias);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-04-15 13:52:03 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONRemoveNetdev(mon, alias);
|
2010-04-15 13:52:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
qemu: qemuMonitorQueryRxFilter - retrieve guest netdev rx-filter
This function can be called at any time to get the current status of a
guest's network device rx-filter. In particular it is useful to call
after libvirt recieves a NIC_RX_FILTER_CHANGED event - this event only
tells you that something has changed in the rx-filter, the details are
retrieved with the query-rx-filter monitor command (only available in
the json monitor). The command sent to the qemu monitor looks like this:
{"execute":"query-rx-filter", "arguments": {"name":"net2"} }'
and the results will look something like this:
{
"return": [
{
"promiscuous": false,
"name": "net2",
"main-mac": "52:54:00:98:2d:e3",
"unicast": "normal",
"vlan": "normal",
"vlan-table": [
42,
0
],
"unicast-table": [
],
"multicast": "normal",
"multicast-overflow": false,
"unicast-overflow": false,
"multicast-table": [
"33:33:ff:98:2d:e3",
"01:80:c2:00:00:21",
"01:00:5e:00:00:fb",
"33:33:ff:98:2d:e2",
"01:00:5e:00:00:01",
"33:33:00:00:00:01"
],
"broadcast-allowed": false
}
],
"id": "libvirt-14"
}
This is all parsed from JSON into a virNetDevRxFilter object for
easier consumption. (unicast-table is usually empty, but is also an
array of mac addresses similar to multicast-table).
(NB: LIBNL_CFLAGS was added to tests/Makefile.am because virnetdev.h
now includes util/virnetlink.h, which includes netlink/msg.h when
appropriate. Without LIBNL_CFLAGS, gcc can't find that file (if
libnl/netlink isn't available, LIBNL_CFLAGS will be empty and
virnetlink.h won't try to include netlink/msg.h anyway).)
2014-09-22 16:19:41 +00:00
|
|
|
int
|
|
|
|
qemuMonitorQueryRxFilter(qemuMonitorPtr mon, const char *alias,
|
|
|
|
virNetDevRxFilterPtr *filter)
|
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("alias=%s filter=%p", alias, filter);
|
qemu: qemuMonitorQueryRxFilter - retrieve guest netdev rx-filter
This function can be called at any time to get the current status of a
guest's network device rx-filter. In particular it is useful to call
after libvirt recieves a NIC_RX_FILTER_CHANGED event - this event only
tells you that something has changed in the rx-filter, the details are
retrieved with the query-rx-filter monitor command (only available in
the json monitor). The command sent to the qemu monitor looks like this:
{"execute":"query-rx-filter", "arguments": {"name":"net2"} }'
and the results will look something like this:
{
"return": [
{
"promiscuous": false,
"name": "net2",
"main-mac": "52:54:00:98:2d:e3",
"unicast": "normal",
"vlan": "normal",
"vlan-table": [
42,
0
],
"unicast-table": [
],
"multicast": "normal",
"multicast-overflow": false,
"unicast-overflow": false,
"multicast-table": [
"33:33:ff:98:2d:e3",
"01:80:c2:00:00:21",
"01:00:5e:00:00:fb",
"33:33:ff:98:2d:e2",
"01:00:5e:00:00:01",
"33:33:00:00:00:01"
],
"broadcast-allowed": false
}
],
"id": "libvirt-14"
}
This is all parsed from JSON into a virNetDevRxFilter object for
easier consumption. (unicast-table is usually empty, but is also an
array of mac addresses similar to multicast-table).
(NB: LIBNL_CFLAGS was added to tests/Makefile.am because virnetdev.h
now includes util/virnetlink.h, which includes netlink/msg.h when
appropriate. Without LIBNL_CFLAGS, gcc can't find that file (if
libnl/netlink isn't available, LIBNL_CFLAGS will be empty and
virnetlink.h won't try to include netlink/msg.h anyway).)
2014-09-22 16:19:41 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-04-14 14:19:04 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONQueryRxFilter(mon, alias, filter);
|
qemu: qemuMonitorQueryRxFilter - retrieve guest netdev rx-filter
This function can be called at any time to get the current status of a
guest's network device rx-filter. In particular it is useful to call
after libvirt recieves a NIC_RX_FILTER_CHANGED event - this event only
tells you that something has changed in the rx-filter, the details are
retrieved with the query-rx-filter monitor command (only available in
the json monitor). The command sent to the qemu monitor looks like this:
{"execute":"query-rx-filter", "arguments": {"name":"net2"} }'
and the results will look something like this:
{
"return": [
{
"promiscuous": false,
"name": "net2",
"main-mac": "52:54:00:98:2d:e3",
"unicast": "normal",
"vlan": "normal",
"vlan-table": [
42,
0
],
"unicast-table": [
],
"multicast": "normal",
"multicast-overflow": false,
"unicast-overflow": false,
"multicast-table": [
"33:33:ff:98:2d:e3",
"01:80:c2:00:00:21",
"01:00:5e:00:00:fb",
"33:33:ff:98:2d:e2",
"01:00:5e:00:00:01",
"33:33:00:00:00:01"
],
"broadcast-allowed": false
}
],
"id": "libvirt-14"
}
This is all parsed from JSON into a virNetDevRxFilter object for
easier consumption. (unicast-table is usually empty, but is also an
array of mac addresses similar to multicast-table).
(NB: LIBNL_CFLAGS was added to tests/Makefile.am because virnetdev.h
now includes util/virnetlink.h, which includes netlink/msg.h when
appropriate. Without LIBNL_CFLAGS, gcc can't find that file (if
libnl/netlink isn't available, LIBNL_CFLAGS will be empty and
virnetlink.h won't try to include netlink/msg.h anyway).)
2014-09-22 16:19:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-28 01:16:12 +00:00
|
|
|
void
|
2019-11-21 19:27:58 +00:00
|
|
|
qemuMonitorChardevInfoFree(void *data)
|
2014-11-13 18:29:14 +00:00
|
|
|
{
|
|
|
|
qemuMonitorChardevInfoPtr info = data;
|
|
|
|
|
|
|
|
VIR_FREE(info->ptyPath);
|
|
|
|
VIR_FREE(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-13 15:17:21 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetChardevInfo(qemuMonitorPtr mon,
|
|
|
|
virHashTablePtr *retinfo)
|
2009-12-14 09:50:01 +00:00
|
|
|
{
|
2010-01-22 13:22:53 +00:00
|
|
|
int ret;
|
2014-11-13 15:17:21 +00:00
|
|
|
virHashTablePtr info = NULL;
|
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("retinfo=%p", retinfo);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR_GOTO(mon, error);
|
2009-12-14 09:50:01 +00:00
|
|
|
|
2014-11-13 18:29:14 +00:00
|
|
|
if (!(info = virHashCreate(10, qemuMonitorChardevInfoFree)))
|
2014-11-13 15:17:21 +00:00
|
|
|
goto error;
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
ret = qemuMonitorJSONGetChardevInfo(mon, info);
|
2014-11-13 15:17:21 +00:00
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
*retinfo = info;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
virHashFree(info);
|
|
|
|
*retinfo = NULL;
|
|
|
|
return -1;
|
2009-12-14 09:50:01 +00:00
|
|
|
}
|
2009-12-07 19:28:05 +00:00
|
|
|
|
|
|
|
|
2016-03-11 15:33:03 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorDriveDel:
|
|
|
|
* @mon: monitor object
|
|
|
|
* @drivestr: identifier of drive to delete.
|
|
|
|
*
|
|
|
|
* Attempts to remove a host drive.
|
|
|
|
* Returns 1 if unsupported, 0 if ok, and -1 on other failure */
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorDriveDel(qemuMonitorPtr mon,
|
|
|
|
const char *drivestr)
|
2010-10-22 14:14:22 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("drivestr=%s", drivestr);
|
2010-10-22 14:14:22 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-10-22 14:14:22 +00:00
|
|
|
|
2016-03-11 15:33:03 +00:00
|
|
|
/* there won't be a direct replacement for drive_del in QMP */
|
|
|
|
return qemuMonitorTextDriveDel(mon, drivestr);
|
2010-10-22 14:14:22 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2019-03-14 07:46:37 +00:00
|
|
|
/**
|
|
|
|
* @mon: monitor object
|
|
|
|
* @devalias: alias of the device to detach
|
|
|
|
*
|
|
|
|
* Sends device detach request to qemu.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success,
|
|
|
|
* -2 if DeviceNotFound error encountered (error NOT reported)
|
|
|
|
* -1 otherwise (error reported)
|
|
|
|
*/
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorDelDevice(qemuMonitorPtr mon,
|
|
|
|
const char *devalias)
|
2010-03-02 08:40:51 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("devalias=%s", devalias);
|
2010-03-02 08:40:51 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONDelDevice(mon, devalias);
|
2010-03-02 08:40:51 +00:00
|
|
|
}
|
|
|
|
|
2010-01-26 15:34:46 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorAddDeviceWithFd(qemuMonitorPtr mon,
|
|
|
|
const char *devicestr,
|
|
|
|
int fd,
|
|
|
|
const char *fdname)
|
2010-01-26 15:34:46 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("device=%s fd=%d fdname=%s", devicestr, fd, NULLSTR(fdname));
|
2010-01-26 15:34:46 +00:00
|
|
|
int ret;
|
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2011-03-15 23:10:16 +00:00
|
|
|
if (fd >= 0 && qemuMonitorSendFileHandle(mon, fdname, fd) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
ret = qemuMonitorJSONAddDevice(mon, devicestr);
|
2011-03-15 23:10:16 +00:00
|
|
|
|
|
|
|
if (ret < 0 && fd >= 0) {
|
|
|
|
if (qemuMonitorCloseFileHandle(mon, fdname) < 0)
|
|
|
|
VIR_WARN("failed to close device handle '%s'", fdname);
|
|
|
|
}
|
|
|
|
|
2010-01-26 15:34:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorAddDevice(qemuMonitorPtr mon,
|
|
|
|
const char *devicestr)
|
2011-03-15 23:10:16 +00:00
|
|
|
{
|
|
|
|
return qemuMonitorAddDeviceWithFd(mon, devicestr, -1, NULL);
|
|
|
|
}
|
|
|
|
|
2014-09-23 11:25:25 +00:00
|
|
|
|
2016-07-31 13:26:12 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorAddDeviceArgs:
|
|
|
|
* @mon: monitor object
|
|
|
|
* @args: arguments for device add, consumed on success or failure
|
|
|
|
*
|
|
|
|
* Adds a device described by @args. Requires JSON monitor.
|
|
|
|
* Returns 0 on success -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorAddDeviceArgs(qemuMonitorPtr mon,
|
|
|
|
virJSONValuePtr args)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2016-07-31 13:26:12 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONAddDeviceArgs(mon, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-17 14:43:58 +00:00
|
|
|
virJSONValuePtr
|
|
|
|
qemuMonitorCreateObjectPropsWrap(const char *type,
|
|
|
|
const char *alias,
|
|
|
|
virJSONValuePtr *props)
|
|
|
|
{
|
|
|
|
virJSONValuePtr ret;
|
|
|
|
|
|
|
|
ignore_value(virJSONValueObjectCreate(&ret,
|
|
|
|
"s:qom-type", type,
|
|
|
|
"s:id", alias,
|
|
|
|
"A:props", props,
|
|
|
|
NULL));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuMonitorCreateObjectProps:
|
|
|
|
* @propsret: returns full object properties
|
|
|
|
* @type: Type name of object to add
|
|
|
|
* @objalias: Alias of the new object
|
|
|
|
* @...: Optional arguments for the given object. See virJSONValueObjectAddVArgs.
|
|
|
|
*
|
|
|
|
* Returns a JSONValue containing everything on success and NULL on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorCreateObjectProps(virJSONValuePtr *propsret,
|
|
|
|
const char *type,
|
|
|
|
const char *alias,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
virJSONValuePtr props = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
*propsret = NULL;
|
|
|
|
|
|
|
|
va_start(args, alias);
|
|
|
|
|
2018-06-18 11:35:38 +00:00
|
|
|
if (virJSONValueObjectCreateVArgs(&props, args) < 0)
|
2018-05-17 14:43:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(*propsret = qemuMonitorCreateObjectPropsWrap(type, alias, &props)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virJSONValueFree(props);
|
|
|
|
va_end(args);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuMonitorAddObject:
|
|
|
|
* @mon: Pointer to monitor object
|
2018-07-04 14:36:37 +00:00
|
|
|
* @props: Pointer to a JSON object holding configuration of the object to add.
|
|
|
|
* The object must be non-null and contain at least the "qom-type" and
|
|
|
|
* "id" field. The object is consumed and the pointer is cleared.
|
2018-05-17 14:43:58 +00:00
|
|
|
* @alias: If not NULL, returns the alias of the added object if it was added
|
|
|
|
* successfully to qemu. Caller should free the returned pointer.
|
|
|
|
*
|
|
|
|
* Returns 0 on success -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorAddObject(qemuMonitorPtr mon,
|
|
|
|
virJSONValuePtr *props,
|
|
|
|
char **alias)
|
|
|
|
{
|
2018-07-04 14:36:37 +00:00
|
|
|
const char *type = NULL;
|
|
|
|
const char *id = NULL;
|
2018-05-17 14:43:58 +00:00
|
|
|
char *tmp = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2018-07-04 14:36:37 +00:00
|
|
|
if (!*props) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("object props can't be NULL"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = virJSONValueObjectGetString(*props, "qom-type");
|
|
|
|
id = virJSONValueObjectGetString(*props, "id");
|
|
|
|
|
2018-05-17 14:43:58 +00:00
|
|
|
VIR_DEBUG("type=%s id=%s", NULLSTR(type), NULLSTR(id));
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR_GOTO(mon, cleanup);
|
|
|
|
|
2018-07-04 14:36:37 +00:00
|
|
|
if (!id || !type) {
|
2018-05-17 14:43:58 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
2018-07-04 14:36:37 +00:00
|
|
|
_("missing alias or qom-type for qemu object '%s'"),
|
|
|
|
NULLSTR(type));
|
2018-05-17 14:43:58 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
if (alias)
|
|
|
|
tmp = g_strdup(id);
|
2018-05-17 14:43:58 +00:00
|
|
|
|
|
|
|
ret = qemuMonitorJSONAddObject(mon, *props);
|
|
|
|
*props = NULL;
|
|
|
|
|
|
|
|
if (alias)
|
2019-10-16 11:43:18 +00:00
|
|
|
*alias = g_steal_pointer(&tmp);
|
2018-05-17 14:43:58 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
virJSONValueFree(*props);
|
|
|
|
*props = NULL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-23 11:25:25 +00:00
|
|
|
int
|
|
|
|
qemuMonitorDelObject(qemuMonitorPtr mon,
|
|
|
|
const char *objalias)
|
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("objalias=%s", objalias);
|
2014-09-23 11:25:25 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2014-09-23 11:25:25 +00:00
|
|
|
|
2015-04-14 14:19:04 +00:00
|
|
|
return qemuMonitorJSONDelObject(mon, objalias);
|
2014-09-23 11:25:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorAddDrive(qemuMonitorPtr mon,
|
|
|
|
const char *drivestr)
|
2010-01-26 15:34:46 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("drive=%s", drivestr);
|
2010-01-26 15:34:46 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2016-03-11 15:33:03 +00:00
|
|
|
/* there won't ever be a direct QMP replacement for this function */
|
|
|
|
return qemuMonitorTextAddDrive(mon, drivestr);
|
2010-01-26 15:34:46 +00:00
|
|
|
}
|
2010-02-11 14:28:16 +00:00
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorCreateSnapshot(qemuMonitorPtr mon, const char *name)
|
2010-04-02 14:10:37 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("name=%s", name);
|
2010-04-02 14:10:37 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2018-05-22 11:46:05 +00:00
|
|
|
/* there won't ever be a direct QMP replacement for this function */
|
|
|
|
return qemuMonitorTextCreateSnapshot(mon, name);
|
2010-04-02 14:10:37 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorLoadSnapshot(qemuMonitorPtr mon, const char *name)
|
2010-04-02 14:10:37 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("name=%s", name);
|
2010-04-02 14:10:37 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2018-05-22 11:46:05 +00:00
|
|
|
/* there won't ever be a direct QMP replacement for this function */
|
|
|
|
return qemuMonitorTextLoadSnapshot(mon, name);
|
2010-04-02 14:10:37 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name)
|
2010-04-02 14:10:37 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("name=%s", name);
|
2010-04-02 14:10:37 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-05-17 11:43:36 +00:00
|
|
|
|
2018-05-22 11:46:05 +00:00
|
|
|
/* there won't ever be a direct QMP replacement for this function */
|
|
|
|
return qemuMonitorTextDeleteSnapshot(mon, name);
|
2010-04-02 14:10:37 +00:00
|
|
|
}
|
2010-04-17 02:12:45 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
blockjob: hoist bandwidth scaling out of monitor code
qemu treats blockjob bandwidth as a 64-bit number, in the units
of bytes/second. But we stupidly modeled block job bandwidth
after migration bandwidth, which in turn was an 'unsigned long'
and therefore subject to 32-bit vs. 64-bit interpretations, and
with a scale of MiB/s. Our code already has to convert between
the two scales, and report overflow as appropriate; although
this conversion currently lives in the monitor code. In fact,
our conversion code limited things to 63 bits, because we
checked against LLONG_MAX and reject what would be negative
bandwidth if treated as signed.
On the bright side, our use of MiB/s means that even with a
32-bit unsigned long, we still have no problem representing a
bandwidth of 2GiB/s, which is starting to be more feasible as
10-gigabit or even faster interfaces are used. And once you
get past the physical speeds of existing interfaces, any larger
bandwidth number behaves the same - effectively unlimited.
But on the low side, the granularity of 1MiB/s tuning is rather
coarse. So the new virDomainBlockJob API decided to go with
a direct 64-bit bytes/sec number instead of the scaled number
that prior blockjob APIs had used. But there is no point in
rounding this number to MiB/s just to scale it back to bytes/s
for handing to qemu.
In order to make future code sharing possible between the old
virDomainBlockRebase and the new virDomainBlockCopy, this patch
moves the scaling and overflow detection into the driver code.
Several of the block job calls that can set speed are fed
through a common interface, so it was easier to adjust all block
jobs at once, for consistency. This patch is just code motion;
there should be no user-visible change in behavior.
* src/qemu/qemu_monitor.h (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Change
parameter type and scale.
* src/qemu/qemu_monitor.c (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Move scaling
and overflow detection...
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl)
(qemuDomainBlockRebase, qemuDomainBlockCommit): ...here.
(qemuDomainBlockCopy): Use bytes/sec.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-08-29 19:58:45 +00:00
|
|
|
/* Start a drive-mirror block job. bandwidth is in bytes/sec. */
|
blockjob: add qemu capabilities related to block jobs
Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror'
and 'block-job-complete'[1], which can drive live block copy and
storage migration. [Additionally, RHEL 6.3 had backported an earlier
version of most of the same functionality, but under the names
'__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with
slightly different JSON arguments, and has been using patches similar
to these upstream patches for several months now.]
The libvirt API virDomainBlockRebase as already committed for 0.9.12
is flexible enough to expose the basics of block copy, but some
additional features in the 'drive-mirror' qemu command, such as
setting error policy, setting granularity, or using a persistent
bitmap, may later require a new libvirt API virDomainBlockCopy. I
will wait to add that API until we know more about what qemu 1.3
will finally provide.
This patch caters only to the upstream qemu 1.3 interface, although
I have proven that the changes for RHEL 6.3 can be isolated to
just qemu_monitor_json.c, and the rest of this series will
gracefully handle either interface once the JSON differences are
papered over in a downstream patch.
For consistency with other block job commands, libvirt must handle
the bandwidth argument as MiB/sec from the user, even though qemu
exposes the speed argument as bytes/sec; then again, qemu rounds
up to cluster size internally, so using MiB hides the worst effects
of that rounding if you pass small numbers.
[1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html
* src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR)
(QEMU_CAPS_DRIVE_REOPEN): New bits.
* src/qemu/qemu_capabilities.c (qemuCaps): Name them.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set
them.
(qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror)
(qemuMonitorDrivePivot): Declare them.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): New passthroughs.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
|
|
|
int
|
|
|
|
qemuMonitorDriveMirror(qemuMonitorPtr mon,
|
|
|
|
const char *device, const char *file,
|
blockjob: hoist bandwidth scaling out of monitor code
qemu treats blockjob bandwidth as a 64-bit number, in the units
of bytes/second. But we stupidly modeled block job bandwidth
after migration bandwidth, which in turn was an 'unsigned long'
and therefore subject to 32-bit vs. 64-bit interpretations, and
with a scale of MiB/s. Our code already has to convert between
the two scales, and report overflow as appropriate; although
this conversion currently lives in the monitor code. In fact,
our conversion code limited things to 63 bits, because we
checked against LLONG_MAX and reject what would be negative
bandwidth if treated as signed.
On the bright side, our use of MiB/s means that even with a
32-bit unsigned long, we still have no problem representing a
bandwidth of 2GiB/s, which is starting to be more feasible as
10-gigabit or even faster interfaces are used. And once you
get past the physical speeds of existing interfaces, any larger
bandwidth number behaves the same - effectively unlimited.
But on the low side, the granularity of 1MiB/s tuning is rather
coarse. So the new virDomainBlockJob API decided to go with
a direct 64-bit bytes/sec number instead of the scaled number
that prior blockjob APIs had used. But there is no point in
rounding this number to MiB/s just to scale it back to bytes/s
for handing to qemu.
In order to make future code sharing possible between the old
virDomainBlockRebase and the new virDomainBlockCopy, this patch
moves the scaling and overflow detection into the driver code.
Several of the block job calls that can set speed are fed
through a common interface, so it was easier to adjust all block
jobs at once, for consistency. This patch is just code motion;
there should be no user-visible change in behavior.
* src/qemu/qemu_monitor.h (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Change
parameter type and scale.
* src/qemu/qemu_monitor.c (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Move scaling
and overflow detection...
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl)
(qemuDomainBlockRebase, qemuDomainBlockCommit): ...here.
(qemuDomainBlockCopy): Use bytes/sec.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-08-29 19:58:45 +00:00
|
|
|
const char *format, unsigned long long bandwidth,
|
blockcopy: add qemu implementation of new tunables
Upstream qemu 1.4 added some drive-mirror tunables not present
when it was first introduced in 1.3. Management apps may want
to set these in some cases (for example, without tuning
granularity down to sector size, a copy may end up occupying
more bytes than the original because an entire cluster is
copied even when only a sector within the cluster is dirty,
although tuning it down results in more CPU time to do the
copy). I haven't personally needed to use the parameters, but
since they exist, and since the new API supports virTypedParams,
we might as well expose them.
Since the tuning parameters aren't often used, and omitted from
the QMP command when unspecified, I think it is safe to rely on
qemu 1.3 to issue an error about them being unsupported, rather
than trying to create a new capability bit in libvirt.
Meanwhile, all versions of qemu from 1.4 to 2.1 have a bug where
a bad granularity (such as non-power-of-2) gives a poor message:
error: internal error: unable to execute QEMU command 'drive-mirror': Invalid parameter 'drive-virtio-disk0'
because of abuse of QERR_INVALID_PARAMETER (which is supposed to
name the parameter that was given a bad value, rather than the
value passed to some other parameter). I don't see that a
capability check will help, so we'll just live with it (and it
has since been improved in upstream qemu).
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror): Add
parameters.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror): Likewise.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror):
Likewise.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONDriveMirror):
Likewise.
* src/qemu/qemu_driver.c (qemuDomainBlockCopyCommon): Likewise.
(qemuDomainBlockRebase, qemuDomainBlockCopy): Adjust callers.
* src/qemu/qemu_migration.c (qemuMigrationDriveMirror): Likewise.
* tests/qemumonitorjsontest.c (qemuMonitorJSONDriveMirror): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-09-08 20:53:12 +00:00
|
|
|
unsigned int granularity, unsigned long long buf_size,
|
2019-05-17 16:13:53 +00:00
|
|
|
bool shallow,
|
|
|
|
bool reuse)
|
blockjob: add qemu capabilities related to block jobs
Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror'
and 'block-job-complete'[1], which can drive live block copy and
storage migration. [Additionally, RHEL 6.3 had backported an earlier
version of most of the same functionality, but under the names
'__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with
slightly different JSON arguments, and has been using patches similar
to these upstream patches for several months now.]
The libvirt API virDomainBlockRebase as already committed for 0.9.12
is flexible enough to expose the basics of block copy, but some
additional features in the 'drive-mirror' qemu command, such as
setting error policy, setting granularity, or using a persistent
bitmap, may later require a new libvirt API virDomainBlockCopy. I
will wait to add that API until we know more about what qemu 1.3
will finally provide.
This patch caters only to the upstream qemu 1.3 interface, although
I have proven that the changes for RHEL 6.3 can be isolated to
just qemu_monitor_json.c, and the rest of this series will
gracefully handle either interface once the JSON differences are
papered over in a downstream patch.
For consistency with other block job commands, libvirt must handle
the bandwidth argument as MiB/sec from the user, even though qemu
exposes the speed argument as bytes/sec; then again, qemu rounds
up to cluster size internally, so using MiB hides the worst effects
of that rounding if you pass small numbers.
[1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html
* src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR)
(QEMU_CAPS_DRIVE_REOPEN): New bits.
* src/qemu/qemu_capabilities.c (qemuCaps): Name them.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set
them.
(qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror)
(qemuMonitorDrivePivot): Declare them.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): New passthroughs.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("device=%s, file=%s, format=%s, bandwidth=%lld, "
|
2019-05-17 16:13:53 +00:00
|
|
|
"granularity=%#x, buf_size=%lld, shallow=%d, reuse=%d",
|
2015-04-14 15:52:48 +00:00
|
|
|
device, file, NULLSTR(format), bandwidth, granularity,
|
2019-05-17 16:13:53 +00:00
|
|
|
buf_size, shallow, reuse);
|
blockjob: add qemu capabilities related to block jobs
Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror'
and 'block-job-complete'[1], which can drive live block copy and
storage migration. [Additionally, RHEL 6.3 had backported an earlier
version of most of the same functionality, but under the names
'__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with
slightly different JSON arguments, and has been using patches similar
to these upstream patches for several months now.]
The libvirt API virDomainBlockRebase as already committed for 0.9.12
is flexible enough to expose the basics of block copy, but some
additional features in the 'drive-mirror' qemu command, such as
setting error policy, setting granularity, or using a persistent
bitmap, may later require a new libvirt API virDomainBlockCopy. I
will wait to add that API until we know more about what qemu 1.3
will finally provide.
This patch caters only to the upstream qemu 1.3 interface, although
I have proven that the changes for RHEL 6.3 can be isolated to
just qemu_monitor_json.c, and the rest of this series will
gracefully handle either interface once the JSON differences are
papered over in a downstream patch.
For consistency with other block job commands, libvirt must handle
the bandwidth argument as MiB/sec from the user, even though qemu
exposes the speed argument as bytes/sec; then again, qemu rounds
up to cluster size internally, so using MiB hides the worst effects
of that rounding if you pass small numbers.
[1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html
* src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR)
(QEMU_CAPS_DRIVE_REOPEN): New bits.
* src/qemu/qemu_capabilities.c (qemuCaps): Name them.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set
them.
(qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror)
(qemuMonitorDrivePivot): Declare them.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): New passthroughs.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-04-14 14:19:04 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONDriveMirror(mon, device, file, format, bandwidth,
|
2019-05-17 16:13:53 +00:00
|
|
|
granularity, buf_size, shallow, reuse);
|
blockjob: add qemu capabilities related to block jobs
Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror'
and 'block-job-complete'[1], which can drive live block copy and
storage migration. [Additionally, RHEL 6.3 had backported an earlier
version of most of the same functionality, but under the names
'__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with
slightly different JSON arguments, and has been using patches similar
to these upstream patches for several months now.]
The libvirt API virDomainBlockRebase as already committed for 0.9.12
is flexible enough to expose the basics of block copy, but some
additional features in the 'drive-mirror' qemu command, such as
setting error policy, setting granularity, or using a persistent
bitmap, may later require a new libvirt API virDomainBlockCopy. I
will wait to add that API until we know more about what qemu 1.3
will finally provide.
This patch caters only to the upstream qemu 1.3 interface, although
I have proven that the changes for RHEL 6.3 can be isolated to
just qemu_monitor_json.c, and the rest of this series will
gracefully handle either interface once the JSON differences are
papered over in a downstream patch.
For consistency with other block job commands, libvirt must handle
the bandwidth argument as MiB/sec from the user, even though qemu
exposes the speed argument as bytes/sec; then again, qemu rounds
up to cluster size internally, so using MiB hides the worst effects
of that rounding if you pass small numbers.
[1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html
* src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR)
(QEMU_CAPS_DRIVE_REOPEN): New bits.
* src/qemu/qemu_capabilities.c (qemuCaps): Name them.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set
them.
(qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror)
(qemuMonitorDrivePivot): Declare them.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): New passthroughs.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2016-03-01 13:55:34 +00:00
|
|
|
int
|
|
|
|
qemuMonitorBlockdevMirror(qemuMonitorPtr mon,
|
|
|
|
const char *jobname,
|
2018-08-16 16:47:20 +00:00
|
|
|
bool persistjob,
|
2016-03-01 13:55:34 +00:00
|
|
|
const char *device,
|
|
|
|
const char *target,
|
|
|
|
unsigned long long bandwidth,
|
|
|
|
unsigned int granularity,
|
|
|
|
unsigned long long buf_size,
|
2019-05-17 16:13:53 +00:00
|
|
|
bool shallow)
|
2016-03-01 13:55:34 +00:00
|
|
|
{
|
2018-08-16 16:47:20 +00:00
|
|
|
VIR_DEBUG("jobname=%s, persistjob=%d, device=%s, target=%s, bandwidth=%lld, "
|
2019-05-17 16:13:53 +00:00
|
|
|
"granularity=%#x, buf_size=%lld, shallow=%d",
|
2018-08-16 16:47:20 +00:00
|
|
|
NULLSTR(jobname), persistjob, device, target, bandwidth, granularity,
|
2019-05-17 16:13:53 +00:00
|
|
|
buf_size, shallow);
|
2016-03-01 13:55:34 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2016-03-01 13:55:34 +00:00
|
|
|
|
2018-08-16 16:47:20 +00:00
|
|
|
return qemuMonitorJSONBlockdevMirror(mon, jobname, persistjob, device, target,
|
|
|
|
bandwidth, granularity, buf_size, shallow);
|
2016-03-01 13:55:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-17 04:17:28 +00:00
|
|
|
/* Use the transaction QMP command to run atomic snapshot commands. */
|
|
|
|
int
|
2018-03-30 10:35:52 +00:00
|
|
|
qemuMonitorTransaction(qemuMonitorPtr mon, virJSONValuePtr *actions)
|
2012-03-17 04:17:28 +00:00
|
|
|
{
|
2018-03-30 10:35:52 +00:00
|
|
|
VIR_DEBUG("actions=%p", *actions);
|
2012-03-17 04:17:28 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-04-14 14:19:04 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONTransaction(mon, actions);
|
2011-08-15 23:25:54 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
blockjob: hoist bandwidth scaling out of monitor code
qemu treats blockjob bandwidth as a 64-bit number, in the units
of bytes/second. But we stupidly modeled block job bandwidth
after migration bandwidth, which in turn was an 'unsigned long'
and therefore subject to 32-bit vs. 64-bit interpretations, and
with a scale of MiB/s. Our code already has to convert between
the two scales, and report overflow as appropriate; although
this conversion currently lives in the monitor code. In fact,
our conversion code limited things to 63 bits, because we
checked against LLONG_MAX and reject what would be negative
bandwidth if treated as signed.
On the bright side, our use of MiB/s means that even with a
32-bit unsigned long, we still have no problem representing a
bandwidth of 2GiB/s, which is starting to be more feasible as
10-gigabit or even faster interfaces are used. And once you
get past the physical speeds of existing interfaces, any larger
bandwidth number behaves the same - effectively unlimited.
But on the low side, the granularity of 1MiB/s tuning is rather
coarse. So the new virDomainBlockJob API decided to go with
a direct 64-bit bytes/sec number instead of the scaled number
that prior blockjob APIs had used. But there is no point in
rounding this number to MiB/s just to scale it back to bytes/s
for handing to qemu.
In order to make future code sharing possible between the old
virDomainBlockRebase and the new virDomainBlockCopy, this patch
moves the scaling and overflow detection into the driver code.
Several of the block job calls that can set speed are fed
through a common interface, so it was easier to adjust all block
jobs at once, for consistency. This patch is just code motion;
there should be no user-visible change in behavior.
* src/qemu/qemu_monitor.h (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Change
parameter type and scale.
* src/qemu/qemu_monitor.c (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Move scaling
and overflow detection...
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl)
(qemuDomainBlockRebase, qemuDomainBlockCommit): ...here.
(qemuDomainBlockCopy): Use bytes/sec.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-08-29 19:58:45 +00:00
|
|
|
/* Start a block-commit block job. bandwidth is in bytes/sec. */
|
2012-10-03 21:13:21 +00:00
|
|
|
int
|
2018-08-16 16:20:25 +00:00
|
|
|
qemuMonitorBlockCommit(qemuMonitorPtr mon,
|
|
|
|
const char *device,
|
|
|
|
const char *jobname,
|
|
|
|
bool persistjob,
|
|
|
|
const char *top,
|
|
|
|
const char *topNode,
|
|
|
|
const char *base,
|
|
|
|
const char *baseNode,
|
2014-05-13 15:41:33 +00:00
|
|
|
const char *backingName,
|
blockjob: hoist bandwidth scaling out of monitor code
qemu treats blockjob bandwidth as a 64-bit number, in the units
of bytes/second. But we stupidly modeled block job bandwidth
after migration bandwidth, which in turn was an 'unsigned long'
and therefore subject to 32-bit vs. 64-bit interpretations, and
with a scale of MiB/s. Our code already has to convert between
the two scales, and report overflow as appropriate; although
this conversion currently lives in the monitor code. In fact,
our conversion code limited things to 63 bits, because we
checked against LLONG_MAX and reject what would be negative
bandwidth if treated as signed.
On the bright side, our use of MiB/s means that even with a
32-bit unsigned long, we still have no problem representing a
bandwidth of 2GiB/s, which is starting to be more feasible as
10-gigabit or even faster interfaces are used. And once you
get past the physical speeds of existing interfaces, any larger
bandwidth number behaves the same - effectively unlimited.
But on the low side, the granularity of 1MiB/s tuning is rather
coarse. So the new virDomainBlockJob API decided to go with
a direct 64-bit bytes/sec number instead of the scaled number
that prior blockjob APIs had used. But there is no point in
rounding this number to MiB/s just to scale it back to bytes/s
for handing to qemu.
In order to make future code sharing possible between the old
virDomainBlockRebase and the new virDomainBlockCopy, this patch
moves the scaling and overflow detection into the driver code.
Several of the block job calls that can set speed are fed
through a common interface, so it was easier to adjust all block
jobs at once, for consistency. This patch is just code motion;
there should be no user-visible change in behavior.
* src/qemu/qemu_monitor.h (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Change
parameter type and scale.
* src/qemu/qemu_monitor.c (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Move scaling
and overflow detection...
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl)
(qemuDomainBlockRebase, qemuDomainBlockCommit): ...here.
(qemuDomainBlockCopy): Use bytes/sec.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-08-29 19:58:45 +00:00
|
|
|
unsigned long long bandwidth)
|
2012-10-03 21:13:21 +00:00
|
|
|
{
|
2018-08-16 16:20:25 +00:00
|
|
|
VIR_DEBUG("device=%s, jobname=%s, persistjob=%d, top=%s, topNode=%s, "
|
|
|
|
"base=%s, baseNode=%s, backingName=%s, bandwidth=%llu",
|
|
|
|
device, NULLSTR(jobname), persistjob, NULLSTR(top), NULLSTR(topNode),
|
|
|
|
NULLSTR(base), NULLSTR(baseNode), NULLSTR(backingName), bandwidth);
|
2012-10-03 21:13:21 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-04-14 14:19:04 +00:00
|
|
|
|
2018-08-16 16:20:25 +00:00
|
|
|
return qemuMonitorJSONBlockCommit(mon, device, jobname, persistjob, top,
|
|
|
|
topNode, base, baseNode, backingName,
|
|
|
|
bandwidth);
|
2012-10-03 21:13:21 +00:00
|
|
|
}
|
|
|
|
|
blockjob: allow omitted arguments to QMP block-commit
We are about to turn on support for active block commit. Although
qemu 2.0 was the first version to mostly support it, that version
mis-handles 0-length files, and doesn't have anything available for
easy probing. But qemu 2.1 fixed bugs, and made life simpler by
letting the 'top' argument be optional. Unless someone begs for
active commit with qemu 2.0, for now we are just going to enable
it only by probing for qemu 2.1 behavior (anyone backporting active
commit can also backport the optional argument behavior). This
requires qemu.git commit 7676e2c597000eff3a7233b40cca768b358f9bc9.
Although all our actual uses of block-commit supply arguments for
both base and top, we can omit both arguments and use a bogus
device string to trigger an interesting behavior in qemu. All QMP
commands first do argument validation, failing with GenericError
if a mandatory argument is missing. Once that passes, the code
in the specific command gets to do further checking, and the qemu
developers made sure that if device is the only supplied argument,
then the block-commit code will look up the device first, with a
failure of DeviceNotFound, before attempting any further argument
validation (most other validations fail with GenericError). Thus,
the category of error class can reliably be used to decipher
whether the top argument was optional, which in turn implies a
working active commit. Since we expect our bogus device string to
trigger an error either way, the code is written to return a
distinct return value without spamming the logs.
* src/qemu/qemu_monitor.h (qemuMonitorSupportsActiveCommit): New
prototype.
* src/qemu/qemu_monitor.c (qemuMonitorSupportsActiveCommit):
Implement it.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockCommit):
Allow NULL for top and base, for probing purposes.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockCommit):
Likewise, implementing the probe.
* tests/qemumonitorjsontest.c (mymain): Enable...
(testQemuMonitorJSONqemuMonitorSupportsActiveCommit): ...a new test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-17 03:42:49 +00:00
|
|
|
|
|
|
|
/* Probe whether active commits are supported by a given qemu binary. */
|
|
|
|
bool
|
|
|
|
qemuMonitorSupportsActiveCommit(qemuMonitorPtr mon)
|
|
|
|
{
|
2019-06-14 18:06:48 +00:00
|
|
|
if (!mon)
|
blockjob: allow omitted arguments to QMP block-commit
We are about to turn on support for active block commit. Although
qemu 2.0 was the first version to mostly support it, that version
mis-handles 0-length files, and doesn't have anything available for
easy probing. But qemu 2.1 fixed bugs, and made life simpler by
letting the 'top' argument be optional. Unless someone begs for
active commit with qemu 2.0, for now we are just going to enable
it only by probing for qemu 2.1 behavior (anyone backporting active
commit can also backport the optional argument behavior). This
requires qemu.git commit 7676e2c597000eff3a7233b40cca768b358f9bc9.
Although all our actual uses of block-commit supply arguments for
both base and top, we can omit both arguments and use a bogus
device string to trigger an interesting behavior in qemu. All QMP
commands first do argument validation, failing with GenericError
if a mandatory argument is missing. Once that passes, the code
in the specific command gets to do further checking, and the qemu
developers made sure that if device is the only supplied argument,
then the block-commit code will look up the device first, with a
failure of DeviceNotFound, before attempting any further argument
validation (most other validations fail with GenericError). Thus,
the category of error class can reliably be used to decipher
whether the top argument was optional, which in turn implies a
working active commit. Since we expect our bogus device string to
trigger an error either way, the code is written to return a
distinct return value without spamming the logs.
* src/qemu/qemu_monitor.h (qemuMonitorSupportsActiveCommit): New
prototype.
* src/qemu/qemu_monitor.c (qemuMonitorSupportsActiveCommit):
Implement it.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockCommit):
Allow NULL for top and base, for probing purposes.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockCommit):
Likewise, implementing the probe.
* tests/qemumonitorjsontest.c (mymain): Enable...
(testQemuMonitorJSONqemuMonitorSupportsActiveCommit): ...a new test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-17 03:42:49 +00:00
|
|
|
return false;
|
|
|
|
|
2018-08-14 13:52:01 +00:00
|
|
|
return qemuMonitorJSONSupportsActiveCommit(mon);
|
blockjob: allow omitted arguments to QMP block-commit
We are about to turn on support for active block commit. Although
qemu 2.0 was the first version to mostly support it, that version
mis-handles 0-length files, and doesn't have anything available for
easy probing. But qemu 2.1 fixed bugs, and made life simpler by
letting the 'top' argument be optional. Unless someone begs for
active commit with qemu 2.0, for now we are just going to enable
it only by probing for qemu 2.1 behavior (anyone backporting active
commit can also backport the optional argument behavior). This
requires qemu.git commit 7676e2c597000eff3a7233b40cca768b358f9bc9.
Although all our actual uses of block-commit supply arguments for
both base and top, we can omit both arguments and use a bogus
device string to trigger an interesting behavior in qemu. All QMP
commands first do argument validation, failing with GenericError
if a mandatory argument is missing. Once that passes, the code
in the specific command gets to do further checking, and the qemu
developers made sure that if device is the only supplied argument,
then the block-commit code will look up the device first, with a
failure of DeviceNotFound, before attempting any further argument
validation (most other validations fail with GenericError). Thus,
the category of error class can reliably be used to decipher
whether the top argument was optional, which in turn implies a
working active commit. Since we expect our bogus device string to
trigger an error either way, the code is written to return a
distinct return value without spamming the logs.
* src/qemu/qemu_monitor.h (qemuMonitorSupportsActiveCommit): New
prototype.
* src/qemu/qemu_monitor.c (qemuMonitorSupportsActiveCommit):
Implement it.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONBlockCommit):
Allow NULL for top and base, for probing purposes.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockCommit):
Likewise, implementing the probe.
* tests/qemumonitorjsontest.c (mymain): Enable...
(testQemuMonitorJSONqemuMonitorSupportsActiveCommit): ...a new test.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-06-17 03:42:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
qemu: read backing chain names from qemu
https://bugzilla.redhat.com/show_bug.cgi?id=1199182 documents that
after a series of disk snapshots into existing destination images,
followed by active commits of the top image, it is possible for
qemu 2.2 and earlier to end up tracking a different name for the
image than what it would have had when opening the chain afresh.
That is, when starting with the chain 'a <- b <- c', the name
associated with 'b' is how it was spelled in the metadata of 'c',
but when starting with 'a', taking two snapshots into 'a <- b <- c',
then committing 'c' back into 'b', the name associated with 'b' is
now the name used when taking the first snapshot.
Sadly, older qemu doesn't know how to treat different spellings of
the same filename as identical files (it uses strcmp() instead of
checking for the same inode), which means libvirt's attempt to
commit an image using solely the names learned from qcow2 metadata
fails with a cryptic:
error: internal error: unable to execute QEMU command 'block-commit': Top image file /tmp/images/c/../b/b not found
even though the file exists. Trying to teach libvirt the rules on
which name qemu will expect is not worth the effort (besides, we'd
have to remember it across libvirtd restarts, and track whether a
file was opened via metadata or via snapshot creation for a given
qemu process); it is easier to just always directly ask qemu what
string it expects to see in the first place.
As a safety valve, we validate that any name returned by qemu
still maps to the same local file as we have tracked it, so that
a compromised qemu cannot accidentally cause us to act on an
incorrect file.
* src/qemu/qemu_monitor.h (qemuMonitorDiskNameLookup): New
prototype.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDiskNameLookup):
Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorDiskNameLookup): New function.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONDiskNameLookup)
(qemuMonitorJSONDiskNameLookupOne): Likewise.
* src/qemu/qemu_driver.c (qemuDomainBlockCommit)
(qemuDomainBlockJobImpl): Use it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2015-03-11 20:37:04 +00:00
|
|
|
/* Determine the name that qemu is using for tracking the backing
|
|
|
|
* element TARGET within the chain starting at TOP. */
|
|
|
|
char *
|
|
|
|
qemuMonitorDiskNameLookup(qemuMonitorPtr mon,
|
|
|
|
const char *device,
|
|
|
|
virStorageSourcePtr top,
|
|
|
|
virStorageSourcePtr target)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
qemu: read backing chain names from qemu
https://bugzilla.redhat.com/show_bug.cgi?id=1199182 documents that
after a series of disk snapshots into existing destination images,
followed by active commits of the top image, it is possible for
qemu 2.2 and earlier to end up tracking a different name for the
image than what it would have had when opening the chain afresh.
That is, when starting with the chain 'a <- b <- c', the name
associated with 'b' is how it was spelled in the metadata of 'c',
but when starting with 'a', taking two snapshots into 'a <- b <- c',
then committing 'c' back into 'b', the name associated with 'b' is
now the name used when taking the first snapshot.
Sadly, older qemu doesn't know how to treat different spellings of
the same filename as identical files (it uses strcmp() instead of
checking for the same inode), which means libvirt's attempt to
commit an image using solely the names learned from qcow2 metadata
fails with a cryptic:
error: internal error: unable to execute QEMU command 'block-commit': Top image file /tmp/images/c/../b/b not found
even though the file exists. Trying to teach libvirt the rules on
which name qemu will expect is not worth the effort (besides, we'd
have to remember it across libvirtd restarts, and track whether a
file was opened via metadata or via snapshot creation for a given
qemu process); it is easier to just always directly ask qemu what
string it expects to see in the first place.
As a safety valve, we validate that any name returned by qemu
still maps to the same local file as we have tracked it, so that
a compromised qemu cannot accidentally cause us to act on an
incorrect file.
* src/qemu/qemu_monitor.h (qemuMonitorDiskNameLookup): New
prototype.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDiskNameLookup):
Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorDiskNameLookup): New function.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONDiskNameLookup)
(qemuMonitorJSONDiskNameLookupOne): Likewise.
* src/qemu/qemu_driver.c (qemuDomainBlockCommit)
(qemuDomainBlockJobImpl): Use it.
Signed-off-by: Eric Blake <eblake@redhat.com>
2015-03-11 20:37:04 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONDiskNameLookup(mon, device, top, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-01 08:06:55 +00:00
|
|
|
/* Use the block-job-complete monitor command to pivot a block copy job. */
|
blockjob: add qemu capabilities related to block jobs
Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror'
and 'block-job-complete'[1], which can drive live block copy and
storage migration. [Additionally, RHEL 6.3 had backported an earlier
version of most of the same functionality, but under the names
'__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with
slightly different JSON arguments, and has been using patches similar
to these upstream patches for several months now.]
The libvirt API virDomainBlockRebase as already committed for 0.9.12
is flexible enough to expose the basics of block copy, but some
additional features in the 'drive-mirror' qemu command, such as
setting error policy, setting granularity, or using a persistent
bitmap, may later require a new libvirt API virDomainBlockCopy. I
will wait to add that API until we know more about what qemu 1.3
will finally provide.
This patch caters only to the upstream qemu 1.3 interface, although
I have proven that the changes for RHEL 6.3 can be isolated to
just qemu_monitor_json.c, and the rest of this series will
gracefully handle either interface once the JSON differences are
papered over in a downstream patch.
For consistency with other block job commands, libvirt must handle
the bandwidth argument as MiB/sec from the user, even though qemu
exposes the speed argument as bytes/sec; then again, qemu rounds
up to cluster size internally, so using MiB hides the worst effects
of that rounding if you pass small numbers.
[1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html
* src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR)
(QEMU_CAPS_DRIVE_REOPEN): New bits.
* src/qemu/qemu_capabilities.c (qemuCaps): Name them.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set
them.
(qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror)
(qemuMonitorDrivePivot): Declare them.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): New passthroughs.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
|
|
|
int
|
2015-04-01 08:06:55 +00:00
|
|
|
qemuMonitorDrivePivot(qemuMonitorPtr mon,
|
2018-08-14 11:11:05 +00:00
|
|
|
const char *jobname)
|
blockjob: add qemu capabilities related to block jobs
Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror'
and 'block-job-complete'[1], which can drive live block copy and
storage migration. [Additionally, RHEL 6.3 had backported an earlier
version of most of the same functionality, but under the names
'__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with
slightly different JSON arguments, and has been using patches similar
to these upstream patches for several months now.]
The libvirt API virDomainBlockRebase as already committed for 0.9.12
is flexible enough to expose the basics of block copy, but some
additional features in the 'drive-mirror' qemu command, such as
setting error policy, setting granularity, or using a persistent
bitmap, may later require a new libvirt API virDomainBlockCopy. I
will wait to add that API until we know more about what qemu 1.3
will finally provide.
This patch caters only to the upstream qemu 1.3 interface, although
I have proven that the changes for RHEL 6.3 can be isolated to
just qemu_monitor_json.c, and the rest of this series will
gracefully handle either interface once the JSON differences are
papered over in a downstream patch.
For consistency with other block job commands, libvirt must handle
the bandwidth argument as MiB/sec from the user, even though qemu
exposes the speed argument as bytes/sec; then again, qemu rounds
up to cluster size internally, so using MiB hides the worst effects
of that rounding if you pass small numbers.
[1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html
* src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR)
(QEMU_CAPS_DRIVE_REOPEN): New bits.
* src/qemu/qemu_capabilities.c (qemuCaps): Name them.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set
them.
(qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror)
(qemuMonitorDrivePivot): Declare them.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): New passthroughs.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
|
|
|
{
|
2018-08-14 11:11:05 +00:00
|
|
|
VIR_DEBUG("jobname=%s", jobname);
|
blockjob: add qemu capabilities related to block jobs
Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror'
and 'block-job-complete'[1], which can drive live block copy and
storage migration. [Additionally, RHEL 6.3 had backported an earlier
version of most of the same functionality, but under the names
'__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with
slightly different JSON arguments, and has been using patches similar
to these upstream patches for several months now.]
The libvirt API virDomainBlockRebase as already committed for 0.9.12
is flexible enough to expose the basics of block copy, but some
additional features in the 'drive-mirror' qemu command, such as
setting error policy, setting granularity, or using a persistent
bitmap, may later require a new libvirt API virDomainBlockCopy. I
will wait to add that API until we know more about what qemu 1.3
will finally provide.
This patch caters only to the upstream qemu 1.3 interface, although
I have proven that the changes for RHEL 6.3 can be isolated to
just qemu_monitor_json.c, and the rest of this series will
gracefully handle either interface once the JSON differences are
papered over in a downstream patch.
For consistency with other block job commands, libvirt must handle
the bandwidth argument as MiB/sec from the user, even though qemu
exposes the speed argument as bytes/sec; then again, qemu rounds
up to cluster size internally, so using MiB hides the worst effects
of that rounding if you pass small numbers.
[1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html
* src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR)
(QEMU_CAPS_DRIVE_REOPEN): New bits.
* src/qemu/qemu_capabilities.c (qemuCaps): Name them.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set
them.
(qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror)
(qemuMonitorDrivePivot): Declare them.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): New passthroughs.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-04-01 08:06:55 +00:00
|
|
|
|
2018-08-14 11:11:05 +00:00
|
|
|
return qemuMonitorJSONDrivePivot(mon, jobname);
|
blockjob: add qemu capabilities related to block jobs
Upstream qemu 1.3 is adding two new monitor commands, 'drive-mirror'
and 'block-job-complete'[1], which can drive live block copy and
storage migration. [Additionally, RHEL 6.3 had backported an earlier
version of most of the same functionality, but under the names
'__com.redhat_drive-mirror' and '__com.redhat_drive-reopen' and with
slightly different JSON arguments, and has been using patches similar
to these upstream patches for several months now.]
The libvirt API virDomainBlockRebase as already committed for 0.9.12
is flexible enough to expose the basics of block copy, but some
additional features in the 'drive-mirror' qemu command, such as
setting error policy, setting granularity, or using a persistent
bitmap, may later require a new libvirt API virDomainBlockCopy. I
will wait to add that API until we know more about what qemu 1.3
will finally provide.
This patch caters only to the upstream qemu 1.3 interface, although
I have proven that the changes for RHEL 6.3 can be isolated to
just qemu_monitor_json.c, and the rest of this series will
gracefully handle either interface once the JSON differences are
papered over in a downstream patch.
For consistency with other block job commands, libvirt must handle
the bandwidth argument as MiB/sec from the user, even though qemu
exposes the speed argument as bytes/sec; then again, qemu rounds
up to cluster size internally, so using MiB hides the worst effects
of that rounding if you pass small numbers.
[1]https://lists.gnu.org/archive/html/qemu-devel/2012-10/msg04123.html
* src/qemu/qemu_capabilities.h (QEMU_CAPS_DRIVE_MIRROR)
(QEMU_CAPS_DRIVE_REOPEN): New bits.
* src/qemu/qemu_capabilities.c (qemuCaps): Name them.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONCheckCommands): Set
them.
(qemuMonitorJSONDriveMirror, qemuMonitorDrivePivot): New functions.
* src/qemu/qemu_monitor_json.h (qemuMonitorJSONDriveMirror)
(qemuMonitorDrivePivot): Declare them.
* src/qemu/qemu_monitor.c (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): New passthroughs.
* src/qemu/qemu_monitor.h (qemuMonitorDriveMirror)
(qemuMonitorDrivePivot): Declare them.
2012-09-28 23:29:53 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorArbitraryCommand(qemuMonitorPtr mon,
|
|
|
|
const char *cmd,
|
|
|
|
char **reply,
|
|
|
|
bool hmp)
|
2010-04-17 02:12:45 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("cmd=%s, reply=%p, hmp=%d", cmd, reply, hmp);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2010-04-17 02:12:45 +00:00
|
|
|
|
2019-09-19 15:53:45 +00:00
|
|
|
if (hmp)
|
|
|
|
return qemuMonitorJSONHumanCommand(mon, cmd, reply);
|
|
|
|
else
|
|
|
|
return qemuMonitorJSONArbitraryCommand(mon, cmd, reply);
|
2010-04-17 02:12:45 +00:00
|
|
|
}
|
2011-05-10 08:26:06 +00:00
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorInjectNMI(qemuMonitorPtr mon)
|
2011-05-10 08:26:06 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-05-10 08:26:06 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONInjectNMI(mon);
|
2011-05-10 08:26:06 +00:00
|
|
|
}
|
2011-04-01 06:23:58 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorSendKey(qemuMonitorPtr mon,
|
|
|
|
unsigned int holdtime,
|
|
|
|
unsigned int *keycodes,
|
|
|
|
unsigned int nkeycodes)
|
2011-07-21 07:55:56 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("holdtime=%u, nkeycodes=%u", holdtime, nkeycodes);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-07-21 07:55:56 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONSendKey(mon, holdtime, keycodes, nkeycodes);
|
2011-07-21 07:55:56 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorScreendump(qemuMonitorPtr mon,
|
2018-05-17 11:53:34 +00:00
|
|
|
const char *device,
|
|
|
|
unsigned int head,
|
2015-04-14 13:14:23 +00:00
|
|
|
const char *file)
|
2011-04-01 06:23:58 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("file=%s", file);
|
2011-04-01 06:23:58 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-04-01 06:23:58 +00:00
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
return qemuMonitorJSONScreendump(mon, device, head, file);
|
2011-04-01 06:23:58 +00:00
|
|
|
}
|
2011-07-22 05:39:37 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
blockjob: hoist bandwidth scaling out of monitor code
qemu treats blockjob bandwidth as a 64-bit number, in the units
of bytes/second. But we stupidly modeled block job bandwidth
after migration bandwidth, which in turn was an 'unsigned long'
and therefore subject to 32-bit vs. 64-bit interpretations, and
with a scale of MiB/s. Our code already has to convert between
the two scales, and report overflow as appropriate; although
this conversion currently lives in the monitor code. In fact,
our conversion code limited things to 63 bits, because we
checked against LLONG_MAX and reject what would be negative
bandwidth if treated as signed.
On the bright side, our use of MiB/s means that even with a
32-bit unsigned long, we still have no problem representing a
bandwidth of 2GiB/s, which is starting to be more feasible as
10-gigabit or even faster interfaces are used. And once you
get past the physical speeds of existing interfaces, any larger
bandwidth number behaves the same - effectively unlimited.
But on the low side, the granularity of 1MiB/s tuning is rather
coarse. So the new virDomainBlockJob API decided to go with
a direct 64-bit bytes/sec number instead of the scaled number
that prior blockjob APIs had used. But there is no point in
rounding this number to MiB/s just to scale it back to bytes/s
for handing to qemu.
In order to make future code sharing possible between the old
virDomainBlockRebase and the new virDomainBlockCopy, this patch
moves the scaling and overflow detection into the driver code.
Several of the block job calls that can set speed are fed
through a common interface, so it was easier to adjust all block
jobs at once, for consistency. This patch is just code motion;
there should be no user-visible change in behavior.
* src/qemu/qemu_monitor.h (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Change
parameter type and scale.
* src/qemu/qemu_monitor.c (qemuMonitorBlockJob)
(qemuMonitorBlockCommit, qemuMonitorDriveMirror): Move scaling
and overflow detection...
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl)
(qemuDomainBlockRebase, qemuDomainBlockCommit): ...here.
(qemuDomainBlockCopy): Use bytes/sec.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-08-29 19:58:45 +00:00
|
|
|
/* bandwidth is in bytes/sec */
|
2014-08-27 19:29:14 +00:00
|
|
|
int
|
2015-04-01 09:45:35 +00:00
|
|
|
qemuMonitorBlockStream(qemuMonitorPtr mon,
|
|
|
|
const char *device,
|
2018-08-15 11:13:53 +00:00
|
|
|
const char *jobname,
|
|
|
|
bool persistjob,
|
2015-04-01 09:45:35 +00:00
|
|
|
const char *base,
|
2018-08-15 11:13:53 +00:00
|
|
|
const char *baseNode,
|
2015-04-01 09:45:35 +00:00
|
|
|
const char *backingName,
|
2017-09-13 13:40:46 +00:00
|
|
|
unsigned long long bandwidth)
|
2011-07-22 05:39:37 +00:00
|
|
|
{
|
2018-08-15 11:13:53 +00:00
|
|
|
VIR_DEBUG("device=%s, jobname=%s, persistjob=%d, base=%s, baseNode=%s, "
|
|
|
|
"backingName=%s, bandwidth=%lluB",
|
|
|
|
device, NULLSTR(jobname), persistjob, NULLSTR(base),
|
|
|
|
NULLSTR(baseNode), NULLSTR(backingName), bandwidth);
|
blockjob: fix block-stream bandwidth race
With RHEL 6.2, virDomainBlockPull(dom, dev, bandwidth, 0) has a race
with non-zero bandwidth: there is a window between the block_stream
and block_job_set_speed monitor commands where an unlimited amount
of data was let through, defeating the point of a throttle.
This race was first identified in commit a9d3495e, and libvirt was
able to reduce the size of the window for that race. In the meantime,
the qemu developers decided to fix things properly; per this message:
https://lists.gnu.org/archive/html/qemu-devel/2012-04/msg03793.html
the fix will be in qemu 1.1, and changes block-job-set-speed to use
a different parameter name, as well as adding a new optional parameter
to block-stream, which eliminates the race altogether.
Since our documentation already mentioned that we can refuse a non-zero
bandwidth for some hypervisors, I think the best solution is to do
just that for RHEL 6.2 qemu, so that the race is obvious to the user
(anyone using stock RHEL 6.2 binaries won't have this patch, and anyone
building their own libvirt with this patch for RHEL can also rebuild
qemu to get the modern semantics, so it is no real loss in behavior).
Meanwhile the code must be fixed to honor actual qemu 1.1 naming.
Rename the parameter to 'modern', since the naming difference now
covers more than just 'async' block-job-cancel. And while at it,
fix an unchecked integer overflow.
* src/qemu/qemu_monitor.h (enum BLOCK_JOB_CMD): Drop unused value,
rename enum to match conventions.
* src/qemu/qemu_monitor.c (qemuMonitorBlockJob): Reflect enum rename.
* src/qemu_qemu_monitor_json.h (qemuMonitorJSONBlockJob): Likewise.
* src/qemu/qemu_monitor_json.c (qemuMonitorJSONBlockJob): Likewise,
and support difference between RHEL 6.2 and qemu 1.1 block pull.
* src/qemu/qemu_driver.c (qemuDomainBlockJobImpl): Reject
bandwidth during pull with too-old qemu.
* src/libvirt.c (virDomainBlockPull, virDomainBlockRebase):
Document this.
2012-04-25 22:49:44 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-04-01 09:45:35 +00:00
|
|
|
|
2018-08-15 11:13:53 +00:00
|
|
|
if (base && baseNode) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("'base' and 'baseNode' can't be used together"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return qemuMonitorJSONBlockStream(mon, device, jobname, persistjob, base,
|
|
|
|
baseNode, backingName, bandwidth);
|
2011-07-22 05:39:37 +00:00
|
|
|
}
|
2011-09-27 09:42:04 +00:00
|
|
|
|
2014-08-27 19:29:14 +00:00
|
|
|
|
2015-04-01 08:40:06 +00:00
|
|
|
int
|
|
|
|
qemuMonitorBlockJobCancel(qemuMonitorPtr mon,
|
2018-08-14 11:11:05 +00:00
|
|
|
const char *jobname)
|
2015-04-01 08:40:06 +00:00
|
|
|
{
|
2018-08-14 11:11:05 +00:00
|
|
|
VIR_DEBUG("jobname=%s", jobname);
|
2015-04-01 08:40:06 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-04-01 08:40:06 +00:00
|
|
|
|
2018-08-14 11:11:05 +00:00
|
|
|
return qemuMonitorJSONBlockJobCancel(mon, jobname);
|
2015-04-01 08:40:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-01 07:47:04 +00:00
|
|
|
int
|
|
|
|
qemuMonitorBlockJobSetSpeed(qemuMonitorPtr mon,
|
2018-08-14 11:11:05 +00:00
|
|
|
const char *jobname,
|
2017-09-13 13:40:46 +00:00
|
|
|
unsigned long long bandwidth)
|
2015-04-01 07:47:04 +00:00
|
|
|
{
|
2018-08-14 11:11:05 +00:00
|
|
|
VIR_DEBUG("jobname=%s, bandwidth=%lluB", jobname, bandwidth);
|
2015-04-01 07:47:04 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-04-01 07:47:04 +00:00
|
|
|
|
2018-08-14 11:11:05 +00:00
|
|
|
return qemuMonitorJSONBlockJobSetSpeed(mon, jobname, bandwidth);
|
2015-04-01 07:47:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-22 11:33:49 +00:00
|
|
|
virHashTablePtr
|
2019-06-11 14:42:53 +00:00
|
|
|
qemuMonitorGetAllBlockJobInfo(qemuMonitorPtr mon,
|
|
|
|
bool rawjobname)
|
2015-05-22 11:33:49 +00:00
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
2019-06-11 14:42:53 +00:00
|
|
|
return qemuMonitorJSONGetAllBlockJobInfo(mon, rawjobname);
|
2015-05-22 11:33:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* qemuMonitorGetBlockJobInfo:
|
|
|
|
* Parse Block Job information, and populate info for the named device.
|
|
|
|
* Return 1 if info available, 0 if device has no block job, and -1 on error.
|
|
|
|
*/
|
2014-08-27 19:29:14 +00:00
|
|
|
int
|
2015-05-22 11:33:49 +00:00
|
|
|
qemuMonitorGetBlockJobInfo(qemuMonitorPtr mon,
|
|
|
|
const char *alias,
|
|
|
|
qemuMonitorBlockJobInfoPtr info)
|
2014-08-27 19:29:14 +00:00
|
|
|
{
|
2015-05-22 11:33:49 +00:00
|
|
|
virHashTablePtr all;
|
|
|
|
qemuMonitorBlockJobInfoPtr data;
|
|
|
|
int ret = 0;
|
2014-08-27 19:29:14 +00:00
|
|
|
|
2015-05-22 11:33:49 +00:00
|
|
|
VIR_DEBUG("alias=%s, info=%p", alias, info);
|
|
|
|
|
2019-05-31 16:51:05 +00:00
|
|
|
if (!(all = qemuMonitorGetAllBlockJobInfo(mon, true)))
|
2015-05-22 11:33:49 +00:00
|
|
|
return -1;
|
2015-04-14 14:19:04 +00:00
|
|
|
|
2015-05-22 11:33:49 +00:00
|
|
|
if ((data = virHashLookup(all, alias))) {
|
|
|
|
*info = *data;
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
virHashFree(all);
|
|
|
|
return ret;
|
2014-08-27 19:29:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-16 09:48:41 +00:00
|
|
|
int
|
|
|
|
qemuMonitorJobDismiss(qemuMonitorPtr mon,
|
|
|
|
const char *jobname)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("jobname=%s", jobname);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONJobDismiss(mon, jobname);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-16 09:48:41 +00:00
|
|
|
int
|
|
|
|
qemuMonitorJobCancel(qemuMonitorPtr mon,
|
|
|
|
const char *jobname,
|
|
|
|
bool quiet)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("jobname='%s' quiet=%d", jobname, quiet);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONJobCancel(mon, jobname, quiet);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-16 09:48:41 +00:00
|
|
|
int
|
|
|
|
qemuMonitorJobComplete(qemuMonitorPtr mon,
|
|
|
|
const char *jobname)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("jobname=%s", jobname);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONJobComplete(mon, jobname);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
|
2018-07-25 13:14:43 +00:00
|
|
|
const char *drivealias,
|
|
|
|
const char *qomid,
|
2015-04-14 13:14:23 +00:00
|
|
|
virDomainBlockIoTuneInfoPtr info,
|
2016-09-18 16:02:50 +00:00
|
|
|
bool supportMaxOptions,
|
2016-10-31 21:22:59 +00:00
|
|
|
bool supportGroupNameOption,
|
2016-09-18 16:02:50 +00:00
|
|
|
bool supportMaxLengthOptions)
|
2011-11-15 09:02:45 +00:00
|
|
|
{
|
2018-07-25 13:14:43 +00:00
|
|
|
VIR_DEBUG("drivealias=%s, qomid=%s, info=%p",
|
|
|
|
NULLSTR(drivealias), NULLSTR(qomid), info);
|
2015-04-14 15:52:48 +00:00
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-11-15 09:02:45 +00:00
|
|
|
|
2018-07-25 13:14:43 +00:00
|
|
|
return qemuMonitorJSONSetBlockIoThrottle(mon, drivealias, qomid, info,
|
2018-05-22 11:51:36 +00:00
|
|
|
supportMaxOptions,
|
|
|
|
supportGroupNameOption,
|
|
|
|
supportMaxLengthOptions);
|
2011-11-15 09:02:45 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,
|
2018-07-25 13:14:43 +00:00
|
|
|
const char *drivealias,
|
|
|
|
const char *qdevid,
|
2016-05-20 06:30:45 +00:00
|
|
|
virDomainBlockIoTuneInfoPtr reply)
|
2011-11-15 09:02:45 +00:00
|
|
|
{
|
2018-07-25 13:14:43 +00:00
|
|
|
VIR_DEBUG("drivealias=%s, qdevid=%s, reply=%p",
|
|
|
|
NULLSTR(drivealias), NULLSTR(qdevid), reply);
|
2015-04-14 15:52:48 +00:00
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-11-15 09:02:45 +00:00
|
|
|
|
2018-07-25 13:14:43 +00:00
|
|
|
return qemuMonitorJSONGetBlockIoThrottle(mon, drivealias, qdevid, reply);
|
2011-11-15 09:02:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorVMStatusToPausedReason(const char *status)
|
2011-09-27 09:42:04 +00:00
|
|
|
{
|
|
|
|
int st;
|
|
|
|
|
|
|
|
if (!status)
|
|
|
|
return VIR_DOMAIN_PAUSED_UNKNOWN;
|
|
|
|
|
|
|
|
if ((st = qemuMonitorVMStatusTypeFromString(status)) < 0) {
|
2017-03-07 17:09:58 +00:00
|
|
|
VIR_WARN("QEMU reported unknown VM status: '%s'", status);
|
2011-09-27 09:42:04 +00:00
|
|
|
return VIR_DOMAIN_PAUSED_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ((qemuMonitorVMStatus) st) {
|
|
|
|
case QEMU_MONITOR_VM_STATUS_DEBUG:
|
|
|
|
case QEMU_MONITOR_VM_STATUS_INTERNAL_ERROR:
|
|
|
|
case QEMU_MONITOR_VM_STATUS_RESTORE_VM:
|
|
|
|
return VIR_DOMAIN_PAUSED_UNKNOWN;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_VM_STATUS_INMIGRATE:
|
|
|
|
case QEMU_MONITOR_VM_STATUS_POSTMIGRATE:
|
|
|
|
case QEMU_MONITOR_VM_STATUS_FINISH_MIGRATE:
|
|
|
|
return VIR_DOMAIN_PAUSED_MIGRATION;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_VM_STATUS_IO_ERROR:
|
|
|
|
return VIR_DOMAIN_PAUSED_IOERROR;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_VM_STATUS_PAUSED:
|
|
|
|
case QEMU_MONITOR_VM_STATUS_PRELAUNCH:
|
|
|
|
return VIR_DOMAIN_PAUSED_USER;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_VM_STATUS_RUNNING:
|
2017-03-07 17:09:58 +00:00
|
|
|
VIR_WARN("QEMU reports the guest is paused but status is 'running'");
|
2011-09-27 09:42:04 +00:00
|
|
|
return VIR_DOMAIN_PAUSED_UNKNOWN;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_VM_STATUS_SAVE_VM:
|
|
|
|
return VIR_DOMAIN_PAUSED_SAVE;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_VM_STATUS_SHUTDOWN:
|
|
|
|
return VIR_DOMAIN_PAUSED_SHUTTING_DOWN;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_VM_STATUS_WATCHDOG:
|
|
|
|
return VIR_DOMAIN_PAUSED_WATCHDOG;
|
|
|
|
|
2013-06-07 10:23:34 +00:00
|
|
|
case QEMU_MONITOR_VM_STATUS_GUEST_PANICKED:
|
2013-07-29 16:54:57 +00:00
|
|
|
return VIR_DOMAIN_PAUSED_CRASHED;
|
2013-06-07 10:23:34 +00:00
|
|
|
|
2011-09-27 09:42:04 +00:00
|
|
|
/* unreachable from this point on */
|
|
|
|
case QEMU_MONITOR_VM_STATUS_LAST:
|
|
|
|
;
|
|
|
|
}
|
|
|
|
return VIR_DOMAIN_PAUSED_UNKNOWN;
|
|
|
|
}
|
2011-10-21 08:00:13 +00:00
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorOpenGraphics(qemuMonitorPtr mon,
|
|
|
|
const char *protocol,
|
|
|
|
int fd,
|
|
|
|
const char *fdname,
|
|
|
|
bool skipauth)
|
2011-10-21 08:00:13 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("protocol=%s fd=%d fdname=%s skipauth=%d",
|
|
|
|
protocol, fd, NULLSTR(fdname), skipauth);
|
2011-10-21 08:00:13 +00:00
|
|
|
int ret;
|
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2011-10-21 08:00:13 +00:00
|
|
|
|
|
|
|
if (qemuMonitorSendFileHandle(mon, fdname, fd) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2018-05-22 11:51:36 +00:00
|
|
|
ret = qemuMonitorJSONOpenGraphics(mon, protocol, fdname, skipauth);
|
2011-10-21 08:00:13 +00:00
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
if (qemuMonitorCloseFileHandle(mon, fdname) < 0)
|
|
|
|
VIR_WARN("failed to close device handle '%s'", fdname);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2012-02-10 12:33:52 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorSystemWakeup(qemuMonitorPtr mon)
|
2012-02-10 12:33:52 +00:00
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-02-10 12:33:52 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONSystemWakeup(mon);
|
|
|
|
}
|
2012-08-15 14:04:09 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorGetVersion(qemuMonitorPtr mon,
|
|
|
|
int *major,
|
|
|
|
int *minor,
|
|
|
|
int *micro,
|
|
|
|
char **package)
|
2012-08-15 14:04:09 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("major=%p minor=%p micro=%p package=%p",
|
|
|
|
major, minor, micro, package);
|
2012-08-15 14:04:09 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-08-15 14:04:09 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetVersion(mon, major, minor, micro, package);
|
|
|
|
}
|
2012-08-15 15:18:41 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorGetMachines(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorMachineInfoPtr **machines)
|
2012-08-15 15:18:41 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("machines=%p", machines);
|
2012-08-15 15:18:41 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-08-15 15:18:41 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetMachines(mon, machines);
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
qemuMonitorMachineInfoFree(qemuMonitorMachineInfoPtr machine)
|
2012-08-15 15:18:41 +00:00
|
|
|
{
|
|
|
|
if (!machine)
|
|
|
|
return;
|
|
|
|
VIR_FREE(machine->name);
|
|
|
|
VIR_FREE(machine->alias);
|
2019-07-18 17:21:55 +00:00
|
|
|
VIR_FREE(machine->defaultCPU);
|
2012-08-15 15:18:41 +00:00
|
|
|
VIR_FREE(machine);
|
|
|
|
}
|
2012-08-20 14:58:20 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon,
|
2019-09-24 11:42:00 +00:00
|
|
|
qemuMonitorCPUDefsPtr *cpuDefs)
|
2012-08-20 14:58:20 +00:00
|
|
|
{
|
2019-09-24 11:42:00 +00:00
|
|
|
VIR_DEBUG("cpuDefs=%p", cpuDefs);
|
2012-08-20 14:58:20 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-08-20 14:58:20 +00:00
|
|
|
|
2019-09-24 11:42:00 +00:00
|
|
|
return qemuMonitorJSONGetCPUDefinitions(mon, cpuDefs);
|
2012-08-20 14:58:20 +00:00
|
|
|
}
|
2012-08-22 09:25:20 +00:00
|
|
|
|
|
|
|
|
2016-04-21 10:51:01 +00:00
|
|
|
void
|
2019-09-24 11:42:00 +00:00
|
|
|
qemuMonitorCPUDefsFree(qemuMonitorCPUDefsPtr defs)
|
2016-04-21 10:51:01 +00:00
|
|
|
{
|
2019-09-24 11:42:00 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!defs)
|
2016-04-21 10:51:01 +00:00
|
|
|
return;
|
2017-09-20 08:45:49 +00:00
|
|
|
|
2019-09-24 11:42:00 +00:00
|
|
|
for (i = 0; i < defs->ncpus; i++) {
|
2019-09-24 11:45:37 +00:00
|
|
|
g_strfreev(defs->cpus[i].blockers);
|
|
|
|
g_free(defs->cpus[i].name);
|
2019-09-19 18:47:37 +00:00
|
|
|
g_free(defs->cpus[i].type);
|
2019-09-24 11:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free(defs->cpus);
|
|
|
|
g_free(defs);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
qemuMonitorCPUDefsPtr
|
|
|
|
qemuMonitorCPUDefsNew(size_t count)
|
|
|
|
{
|
|
|
|
g_autoptr(qemuMonitorCPUDefs) defs = NULL;
|
|
|
|
|
|
|
|
defs = g_new0(qemuMonitorCPUDefs, 1);
|
2019-09-24 11:45:37 +00:00
|
|
|
defs->cpus = g_new0(qemuMonitorCPUDefInfo, count);
|
2019-09-24 11:42:00 +00:00
|
|
|
defs->ncpus = count;
|
|
|
|
|
|
|
|
return g_steal_pointer(&defs);
|
2016-04-21 10:51:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-24 15:12:34 +00:00
|
|
|
qemuMonitorCPUDefsPtr
|
|
|
|
qemuMonitorCPUDefsCopy(qemuMonitorCPUDefsPtr src)
|
|
|
|
{
|
|
|
|
g_autoptr(qemuMonitorCPUDefs) defs = NULL;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!src)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
defs = qemuMonitorCPUDefsNew(src->ncpus);
|
|
|
|
for (i = 0; i < src->ncpus; i++) {
|
|
|
|
qemuMonitorCPUDefInfoPtr cpuDst = defs->cpus + i;
|
|
|
|
qemuMonitorCPUDefInfoPtr cpuSrc = src->cpus + i;
|
|
|
|
|
|
|
|
cpuDst->usable = cpuSrc->usable;
|
|
|
|
cpuDst->name = g_strdup(cpuSrc->name);
|
2019-09-19 18:47:37 +00:00
|
|
|
cpuDst->type = g_strdup(cpuSrc->type);
|
2019-09-24 15:12:34 +00:00
|
|
|
cpuDst->blockers = g_strdupv(cpuSrc->blockers);
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_steal_pointer(&defs);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-18 19:22:26 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon,
|
2017-01-31 12:44:00 +00:00
|
|
|
qemuMonitorCPUModelExpansionType type,
|
2019-09-19 20:24:54 +00:00
|
|
|
virCPUDefPtr cpu,
|
2017-03-29 08:58:41 +00:00
|
|
|
bool migratable,
|
2019-09-19 20:24:56 +00:00
|
|
|
bool fail_no_props,
|
2016-12-18 19:22:26 +00:00
|
|
|
qemuMonitorCPUModelInfoPtr *model_info)
|
|
|
|
{
|
2019-09-19 20:24:54 +00:00
|
|
|
VIR_DEBUG("type=%d cpu=%p migratable=%d", type, cpu, migratable);
|
2016-12-18 19:22:26 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2016-12-18 19:22:26 +00:00
|
|
|
|
2019-09-19 20:24:54 +00:00
|
|
|
return qemuMonitorJSONGetCPUModelExpansion(mon, type, cpu,
|
2019-09-19 20:24:56 +00:00
|
|
|
migratable, fail_no_props,
|
|
|
|
model_info);
|
2016-12-18 19:22:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-19 20:24:58 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetCPUModelBaseline(qemuMonitorPtr mon,
|
|
|
|
virCPUDefPtr cpu_a,
|
|
|
|
virCPUDefPtr cpu_b,
|
|
|
|
qemuMonitorCPUModelInfoPtr *baseline)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("cpu_a=%p cpu_b=%p", cpu_a, cpu_b);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONGetCPUModelBaseline(mon, cpu_a, cpu_b, baseline);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-19 20:25:02 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetCPUModelComparison(qemuMonitorPtr mon,
|
|
|
|
virCPUDefPtr cpu_a,
|
|
|
|
virCPUDefPtr cpu_b,
|
|
|
|
char **result)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("cpu_a=%p cpu_b=%p", cpu_a, cpu_b);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONGetCPUModelComparison(mon, cpu_a, cpu_b, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-12-18 19:22:26 +00:00
|
|
|
void
|
|
|
|
qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfoPtr model_info)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!model_info)
|
|
|
|
return;
|
|
|
|
|
2017-02-22 15:01:30 +00:00
|
|
|
for (i = 0; i < model_info->nprops; i++) {
|
2016-12-18 19:22:26 +00:00
|
|
|
VIR_FREE(model_info->props[i].name);
|
2017-02-22 15:01:30 +00:00
|
|
|
if (model_info->props[i].type == QEMU_MONITOR_CPU_PROPERTY_STRING)
|
|
|
|
VIR_FREE(model_info->props[i].value.string);
|
|
|
|
}
|
2016-12-18 19:22:26 +00:00
|
|
|
|
2017-02-06 08:09:12 +00:00
|
|
|
VIR_FREE(model_info->props);
|
2016-12-18 19:22:26 +00:00
|
|
|
VIR_FREE(model_info->name);
|
|
|
|
VIR_FREE(model_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
qemuMonitorCPUModelInfoPtr
|
|
|
|
qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig)
|
|
|
|
{
|
|
|
|
qemuMonitorCPUModelInfoPtr copy;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(copy) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(copy->props, orig->nprops) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
copy->name = g_strdup(orig->name);
|
2016-12-18 19:22:26 +00:00
|
|
|
|
2017-03-29 08:33:08 +00:00
|
|
|
copy->migratability = orig->migratability;
|
2016-12-18 19:22:26 +00:00
|
|
|
copy->nprops = orig->nprops;
|
|
|
|
|
|
|
|
for (i = 0; i < orig->nprops; i++) {
|
2019-10-20 11:49:46 +00:00
|
|
|
copy->props[i].name = g_strdup(orig->props[i].name);
|
2016-12-18 19:22:26 +00:00
|
|
|
|
2017-03-29 08:33:08 +00:00
|
|
|
copy->props[i].migratable = orig->props[i].migratable;
|
2017-02-22 15:01:30 +00:00
|
|
|
copy->props[i].type = orig->props[i].type;
|
|
|
|
switch (orig->props[i].type) {
|
|
|
|
case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
|
|
|
|
copy->props[i].value.boolean = orig->props[i].value.boolean;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_CPU_PROPERTY_STRING:
|
2019-10-20 11:49:46 +00:00
|
|
|
copy->props[i].value.string = g_strdup(orig->props[i].value.string);
|
2017-02-22 15:01:30 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
|
|
|
|
copy->props[i].value.number = orig->props[i].value.number;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QEMU_MONITOR_CPU_PROPERTY_LAST:
|
|
|
|
break;
|
|
|
|
}
|
2016-12-18 19:22:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return copy;
|
|
|
|
|
|
|
|
error:
|
|
|
|
qemuMonitorCPUModelInfoFree(copy);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetCommands(qemuMonitorPtr mon,
|
|
|
|
char ***commands)
|
2012-08-22 09:25:20 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("commands=%p", commands);
|
2012-08-22 09:25:20 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-08-22 09:25:20 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetCommands(mon, commands);
|
|
|
|
}
|
2012-08-22 09:48:41 +00:00
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetEvents(qemuMonitorPtr mon,
|
|
|
|
char ***events)
|
2012-08-22 09:48:41 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("events=%p", events);
|
2012-08-22 09:48:41 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-08-22 09:48:41 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetEvents(mon, events);
|
|
|
|
}
|
2012-08-22 09:48:41 +00:00
|
|
|
|
|
|
|
|
2013-04-26 17:13:45 +00:00
|
|
|
/* Collect the parameters associated with a given command line option.
|
|
|
|
* Return count of known parameters or -1 on error. */
|
|
|
|
int
|
|
|
|
qemuMonitorGetCommandLineOptionParameters(qemuMonitorPtr mon,
|
|
|
|
const char *option,
|
2014-06-17 11:41:16 +00:00
|
|
|
char ***params,
|
|
|
|
bool *found)
|
2013-04-26 17:13:45 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("option=%s params=%p", option, params);
|
2013-04-26 17:13:45 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-04-26 17:13:45 +00:00
|
|
|
|
2014-06-17 11:41:16 +00:00
|
|
|
return qemuMonitorJSONGetCommandLineOptionParameters(mon, option,
|
|
|
|
params, found);
|
2013-04-26 17:13:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetKVMState(qemuMonitorPtr mon,
|
|
|
|
bool *enabled,
|
|
|
|
bool *present)
|
Make non-KVM machines work with QMP probing
When there is no 'qemu-kvm' binary and the emulator used for a machine
is, for example, 'qemu-system-x86_64' that, by default, runs without
kvm enabled, libvirt still supplies '-no-kvm' option to this process,
even though it does not recognize such option (making the start of a
domain fail in that case).
This patch fixes building a command-line for QEMU machines without KVM
acceleration and is based on following assumptions:
- QEMU_CAPS_KVM flag means that QEMU is running KVM accelerated
machines by default (without explicitly requesting that using a
command-line option). It is the closest to the truth according to
the code with the only exception being the comment next to the
flag, so it's fixed in this patch as well.
- QEMU_CAPS_ENABLE_KVM flag means that QEMU is, by default, running
without KVM acceleration and in case we need KVM acceleration it
needs to be explicitly instructed to do so. This is partially
true for the past (this option essentially means that QEMU
recognizes the '-enable-kvm' option, even though it's almost the
same).
2012-10-31 07:31:49 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("enabled=%p present=%p", enabled, present);
|
Make non-KVM machines work with QMP probing
When there is no 'qemu-kvm' binary and the emulator used for a machine
is, for example, 'qemu-system-x86_64' that, by default, runs without
kvm enabled, libvirt still supplies '-no-kvm' option to this process,
even though it does not recognize such option (making the start of a
domain fail in that case).
This patch fixes building a command-line for QEMU machines without KVM
acceleration and is based on following assumptions:
- QEMU_CAPS_KVM flag means that QEMU is running KVM accelerated
machines by default (without explicitly requesting that using a
command-line option). It is the closest to the truth according to
the code with the only exception being the comment next to the
flag, so it's fixed in this patch as well.
- QEMU_CAPS_ENABLE_KVM flag means that QEMU is, by default, running
without KVM acceleration and in case we need KVM acceleration it
needs to be explicitly instructed to do so. This is partially
true for the past (this option essentially means that QEMU
recognizes the '-enable-kvm' option, even though it's almost the
same).
2012-10-31 07:31:49 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
Make non-KVM machines work with QMP probing
When there is no 'qemu-kvm' binary and the emulator used for a machine
is, for example, 'qemu-system-x86_64' that, by default, runs without
kvm enabled, libvirt still supplies '-no-kvm' option to this process,
even though it does not recognize such option (making the start of a
domain fail in that case).
This patch fixes building a command-line for QEMU machines without KVM
acceleration and is based on following assumptions:
- QEMU_CAPS_KVM flag means that QEMU is running KVM accelerated
machines by default (without explicitly requesting that using a
command-line option). It is the closest to the truth according to
the code with the only exception being the comment next to the
flag, so it's fixed in this patch as well.
- QEMU_CAPS_ENABLE_KVM flag means that QEMU is, by default, running
without KVM acceleration and in case we need KVM acceleration it
needs to be explicitly instructed to do so. This is partially
true for the past (this option essentially means that QEMU
recognizes the '-enable-kvm' option, even though it's almost the
same).
2012-10-31 07:31:49 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetKVMState(mon, enabled, present);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetObjectTypes(qemuMonitorPtr mon,
|
|
|
|
char ***types)
|
2012-08-22 09:48:41 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("types=%p", types);
|
2012-08-22 09:48:41 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-08-22 09:48:41 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetObjectTypes(mon, types);
|
|
|
|
}
|
2012-08-22 09:48:41 +00:00
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
2018-04-12 11:27:54 +00:00
|
|
|
qemuMonitorGetDeviceProps(qemuMonitorPtr mon,
|
|
|
|
const char *device,
|
2015-04-14 13:14:23 +00:00
|
|
|
char ***props)
|
2012-08-22 09:48:41 +00:00
|
|
|
{
|
2018-04-12 11:27:54 +00:00
|
|
|
VIR_DEBUG("device=%s props=%p", device, props);
|
2012-08-22 09:48:41 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-08-22 09:48:41 +00:00
|
|
|
|
2018-04-12 11:27:54 +00:00
|
|
|
return qemuMonitorJSONGetDeviceProps(mon, device, props);
|
2012-08-22 09:48:41 +00:00
|
|
|
}
|
2012-08-22 09:48:41 +00:00
|
|
|
|
|
|
|
|
2018-04-12 13:04:07 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetObjectProps(qemuMonitorPtr mon,
|
|
|
|
const char *object,
|
|
|
|
char ***props)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("object=%s props=%p", object, props);
|
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2018-04-12 13:04:07 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetObjectProps(mon, object, props);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
char *
|
|
|
|
qemuMonitorGetTargetArch(qemuMonitorPtr mon)
|
2012-08-22 09:48:41 +00:00
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
2012-08-22 09:48:41 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetTargetArch(mon);
|
|
|
|
}
|
2013-01-14 11:45:20 +00:00
|
|
|
|
|
|
|
|
2014-09-11 12:11:54 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetMigrationCapabilities(qemuMonitorPtr mon,
|
|
|
|
char ***capabilities)
|
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2014-09-11 12:11:54 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetMigrationCapabilities(mon, capabilities);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-05 18:59:07 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorSetMigrationCapabilities:
|
|
|
|
* @mon: Pointer to the monitor object.
|
|
|
|
* @caps: Migration capabilities.
|
|
|
|
*
|
|
|
|
* The @caps object is consumed and should not be referenced by the caller
|
|
|
|
* after this function returns.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
|
|
|
*/
|
2018-03-01 08:26:07 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetMigrationCapabilities(qemuMonitorPtr mon,
|
2018-04-05 18:59:07 +00:00
|
|
|
virJSONValuePtr caps)
|
2018-03-01 08:26:07 +00:00
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_GOTO(mon, error);
|
2018-03-01 08:26:07 +00:00
|
|
|
|
2018-04-05 18:59:07 +00:00
|
|
|
return qemuMonitorJSONSetMigrationCapabilities(mon, caps);
|
2018-03-01 08:26:07 +00:00
|
|
|
|
2018-04-05 18:59:07 +00:00
|
|
|
error:
|
|
|
|
virJSONValueFree(caps);
|
|
|
|
return -1;
|
2018-03-01 08:26:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-03-08 17:24:18 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorGetGICCapabilities:
|
|
|
|
* @mon: QEMU monitor
|
|
|
|
* @capabilities: where to store the GIC capabilities
|
|
|
|
*
|
|
|
|
* See qemuMonitorJSONGetGICCapabilities().
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
|
|
|
|
virGICCapability **capabilities)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2016-03-08 17:24:18 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetGICCapabilities(mon, capabilities);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-08 14:40:51 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
|
|
|
|
virSEVCapability **capabilities)
|
|
|
|
{
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONGetSEVCapabilities(mon, capabilities);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorNBDServerStart(qemuMonitorPtr mon,
|
2019-04-09 21:21:38 +00:00
|
|
|
const virStorageNetHostDef *server,
|
2018-02-21 13:18:15 +00:00
|
|
|
const char *tls_alias)
|
2012-11-22 15:08:52 +00:00
|
|
|
{
|
2019-04-09 21:21:38 +00:00
|
|
|
/* Peek inside the struct for nicer logging */
|
|
|
|
if (server->transport == VIR_STORAGE_NET_HOST_TRANS_TCP)
|
|
|
|
VIR_DEBUG("server={tcp host=%s port=%u} tls_alias=%s",
|
|
|
|
NULLSTR(server->name), server->port, NULLSTR(tls_alias));
|
|
|
|
else
|
|
|
|
VIR_DEBUG("server={unix socket=%s} tls_alias=%s",
|
|
|
|
NULLSTR(server->socket), NULLSTR(tls_alias));
|
2012-11-22 15:08:52 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-11-22 15:08:52 +00:00
|
|
|
|
2019-04-09 21:21:38 +00:00
|
|
|
return qemuMonitorJSONNBDServerStart(mon, server, tls_alias);
|
2012-11-22 15:08:52 +00:00
|
|
|
}
|
2012-11-22 15:17:13 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorNBDServerAdd(qemuMonitorPtr mon,
|
|
|
|
const char *deviceID,
|
2019-06-06 02:25:05 +00:00
|
|
|
const char *export,
|
|
|
|
bool writable,
|
|
|
|
const char *bitmap)
|
2012-11-22 15:17:13 +00:00
|
|
|
{
|
2019-06-06 02:25:05 +00:00
|
|
|
VIR_DEBUG("deviceID=%s, export=%s, bitmap=%s", deviceID, NULLSTR(export),
|
|
|
|
NULLSTR(bitmap));
|
2012-11-22 15:17:13 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2012-11-22 15:17:13 +00:00
|
|
|
|
2019-06-06 02:25:05 +00:00
|
|
|
return qemuMonitorJSONNBDServerAdd(mon, deviceID, export, writable,
|
|
|
|
bitmap);
|
2012-11-22 15:17:13 +00:00
|
|
|
}
|
2013-01-31 13:47:49 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorNBDServerStop(qemuMonitorPtr mon)
|
2013-01-31 13:47:49 +00:00
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-01-31 13:47:49 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONNBDServerStop(mon);
|
|
|
|
}
|
2013-04-12 20:55:45 +00:00
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetTPMModels(qemuMonitorPtr mon,
|
2013-04-12 20:55:45 +00:00
|
|
|
char ***tpmmodels)
|
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("tpmmodels=%p", tpmmodels);
|
2013-04-12 20:55:45 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-04-12 20:55:45 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetTPMModels(mon, tpmmodels);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetTPMTypes(qemuMonitorPtr mon,
|
|
|
|
char ***tpmtypes)
|
2013-04-12 20:55:45 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("tpmtypes=%p", tpmtypes);
|
2013-04-12 20:55:45 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-04-12 20:55:45 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetTPMTypes(mon, tpmtypes);
|
|
|
|
}
|
2013-03-12 18:48:04 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorAttachCharDev(qemuMonitorPtr mon,
|
|
|
|
const char *chrID,
|
|
|
|
virDomainChrSourceDefPtr chr)
|
2013-03-12 18:48:04 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("chrID=%s chr=%p", chrID, chr);
|
2013-03-12 18:48:04 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-03-12 18:48:04 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONAttachCharDev(mon, chrID, chr);
|
|
|
|
}
|
2013-03-12 18:57:48 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorDetachCharDev(qemuMonitorPtr mon,
|
|
|
|
const char *chrID)
|
2013-03-12 18:57:48 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("chrID=%s", chrID);
|
2013-03-12 18:57:48 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-03-12 18:57:48 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONDetachCharDev(mon, chrID);
|
|
|
|
}
|
2013-07-19 13:01:38 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2013-07-19 13:01:38 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetDeviceAliases(qemuMonitorPtr mon,
|
|
|
|
char ***aliases)
|
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("aliases=%p", aliases);
|
2013-07-19 13:01:38 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-07-19 13:01:38 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetDeviceAliases(mon, aliases);
|
|
|
|
}
|
2013-09-18 14:12:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
qemu: Fix two use-after-free situations
There were multiple race conditions that could lead to segmentation
faults. The first precondition for this is qemuProcessLaunch must fail
sometime shortly after starting the new QEMU process. The second
precondition for the segmentation faults is that the new QEMU process
dies - or to be more precise the QEMU monitor has to be closed
irregularly. If both happens during qemuProcessStart (starting a
domain) there are race windows between the thread with the event
loop (T1) and the thread that is starting the domain (T2).
First segmentation fault scenario:
If qemuProcessLaunch fails during qemuProcessStart the code branches
to the 'stop' path where 'qemuMonitorSetDomainLog(priv->mon, NULL,
NULL, NULL)' will set the log function of the monitor to NULL (done in
T2). In the meantime the event loop of T1 will wake up with an EOF
event for the QEMU monitor because the QEMU process has died. The
crash occurs if T1 has checked 'mon->logFunc != NULL' in qemuMonitorIO
just before the logFunc was set to NULL by T2. If this situation
occurs T1 will try to call mon->logFunc which leads to the
segmentation fault.
Solution:
Require the monitor lock for setting the log function.
Backtrace:
0 0x0000000000000000 in ?? ()
1 0x000003ffe9e45316 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe08aa860) at
../../src/qemu/qemu_monitor.c:727
2 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
3 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
4 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
5 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
6 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Second segmentation fault scenario:
If qemuProcessLaunch fails it will unref the log context and with
invoking qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL)
qemuDomainLogContextFree() will be invoked. qemuDomainLogContextFree()
invokes virNetClientClose() to close the client and cleans everything
up (including unref of _virLogManager.client) when virNetClientClose()
returns. When T1 is now trying to report 'qemu unexpectedly closed the
monitor' libvirtd will crash because the client has already been
freed.
Solution:
As the critical section in qemuMonitorIO is protected with the monitor
lock we can use the same solution as proposed for the first
segmentation fault.
Backtrace:
0 virClassIsDerivedFrom (klass=0x3100979797979797,
parent=0x2aa000d92f0) at ../../src/util/virobject.c:169
1 0x000003fffda659e6 in virObjectIsClass (anyobj=<optimized out>,
klass=<optimized out>) at ../../src/util/virobject.c:365
2 0x000003fffda65a24 in virObjectLock (anyobj=0x3ffe08c1db0) at
../../src/util/virobject.c:317
3 0x000003fffdba4688 in
virNetClientIOEventLoop (client=client@entry=0x3ffe08c1db0,
thiscall=thiscall@entry=0x2aa000fbfa0) at
../../src/rpc/virnetclient.c:1668
4 0x000003fffdba4b4c in
virNetClientIO (client=client@entry=0x3ffe08c1db0,
thiscall=0x2aa000fbfa0) at ../../src/rpc/virnetclient.c:1944
5 0x000003fffdba4d42 in
virNetClientSendInternal (client=client@entry=0x3ffe08c1db0,
msg=msg@entry=0x2aa000cc710, expectReply=expectReply@entry=true,
nonBlock=nonBlock@entry=false) at ../../src/rpc/virnetclient.c:2116
6 0x000003fffdba6268 in
virNetClientSendWithReply (client=0x3ffe08c1db0, msg=0x2aa000cc710) at
../../src/rpc/virnetclient.c:2144
7 0x000003fffdba6e8e in virNetClientProgramCall (prog=0x3ffe08c1120,
client=<optimized out>, serial=<optimized out>, proc=<optimized out>,
noutfds=<optimized out>, outfds=0x0, ninfds=0x0, infds=0x0,
args_filter=0x3fffdb64440
<xdr_virLogManagerProtocolDomainReadLogFileArgs>, args=0x3ffffffe010,
ret_filter=0x3fffdb644c0
<xdr_virLogManagerProtocolDomainReadLogFileRet>, ret=0x3ffffffe008) at
../../src/rpc/virnetclientprogram.c:329
8 0x000003fffdb64042 in
virLogManagerDomainReadLogFile (mgr=<optimized out>, path=<optimized
out>, inode=<optimized out>, offset=<optimized out>, maxlen=<optimized
out>, flags=0) at ../../src/logging/log_manager.c:272
9 0x000003ffe9e0315c in qemuDomainLogContextRead (ctxt=0x3ffe08c2980,
msg=0x3ffffffe1c0) at ../../src/qemu/qemu_domain.c:4422
10 0x000003ffe9e280a8 in qemuProcessReadLog (logCtxt=<optimized out>,
msg=msg@entry=0x3ffffffe288) at ../../src/qemu/qemu_process.c:1800
11 0x000003ffe9e28206 in qemuProcessReportLogError (logCtxt=<optimized
out>, msgprefix=0x3ffe9ec276a "qemu unexpectedly closed the monitor")
at ../../src/qemu/qemu_process.c:1836
12 0x000003ffe9e28306 in
qemuProcessMonitorReportLogError (mon=mon@entry=0x3ffe085cf10,
msg=<optimized out>, opaque=<optimized out>) at
../../src/qemu/qemu_process.c:1856
13 0x000003ffe9e452b6 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe085cf10) at
../../src/qemu/qemu_monitor.c:726
14 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
15 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
16 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
17 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
18 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Other code parts where the same problem was possible to occur are
fixed as well (qemuMigrationFinish, qemuProcessStart, and
qemuDomainSaveImageStartVM).
Signed-off-by: Marc Hartmayer <mhartmay@linux.vnet.ibm.com>
Reported-by: Sascha Silbe <silbe@linux.vnet.ibm.com>
2017-04-03 08:24:35 +00:00
|
|
|
* qemuMonitorSetDomainLogLocked:
|
|
|
|
* @mon: Locked monitor object to set the log file reading on
|
2015-11-12 13:54:04 +00:00
|
|
|
* @func: the callback to report errors
|
|
|
|
* @opaque: data to pass to @func
|
|
|
|
* @destroy: optional callback to free @opaque
|
qemu: Fix two use-after-free situations
There were multiple race conditions that could lead to segmentation
faults. The first precondition for this is qemuProcessLaunch must fail
sometime shortly after starting the new QEMU process. The second
precondition for the segmentation faults is that the new QEMU process
dies - or to be more precise the QEMU monitor has to be closed
irregularly. If both happens during qemuProcessStart (starting a
domain) there are race windows between the thread with the event
loop (T1) and the thread that is starting the domain (T2).
First segmentation fault scenario:
If qemuProcessLaunch fails during qemuProcessStart the code branches
to the 'stop' path where 'qemuMonitorSetDomainLog(priv->mon, NULL,
NULL, NULL)' will set the log function of the monitor to NULL (done in
T2). In the meantime the event loop of T1 will wake up with an EOF
event for the QEMU monitor because the QEMU process has died. The
crash occurs if T1 has checked 'mon->logFunc != NULL' in qemuMonitorIO
just before the logFunc was set to NULL by T2. If this situation
occurs T1 will try to call mon->logFunc which leads to the
segmentation fault.
Solution:
Require the monitor lock for setting the log function.
Backtrace:
0 0x0000000000000000 in ?? ()
1 0x000003ffe9e45316 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe08aa860) at
../../src/qemu/qemu_monitor.c:727
2 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
3 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
4 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
5 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
6 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Second segmentation fault scenario:
If qemuProcessLaunch fails it will unref the log context and with
invoking qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL)
qemuDomainLogContextFree() will be invoked. qemuDomainLogContextFree()
invokes virNetClientClose() to close the client and cleans everything
up (including unref of _virLogManager.client) when virNetClientClose()
returns. When T1 is now trying to report 'qemu unexpectedly closed the
monitor' libvirtd will crash because the client has already been
freed.
Solution:
As the critical section in qemuMonitorIO is protected with the monitor
lock we can use the same solution as proposed for the first
segmentation fault.
Backtrace:
0 virClassIsDerivedFrom (klass=0x3100979797979797,
parent=0x2aa000d92f0) at ../../src/util/virobject.c:169
1 0x000003fffda659e6 in virObjectIsClass (anyobj=<optimized out>,
klass=<optimized out>) at ../../src/util/virobject.c:365
2 0x000003fffda65a24 in virObjectLock (anyobj=0x3ffe08c1db0) at
../../src/util/virobject.c:317
3 0x000003fffdba4688 in
virNetClientIOEventLoop (client=client@entry=0x3ffe08c1db0,
thiscall=thiscall@entry=0x2aa000fbfa0) at
../../src/rpc/virnetclient.c:1668
4 0x000003fffdba4b4c in
virNetClientIO (client=client@entry=0x3ffe08c1db0,
thiscall=0x2aa000fbfa0) at ../../src/rpc/virnetclient.c:1944
5 0x000003fffdba4d42 in
virNetClientSendInternal (client=client@entry=0x3ffe08c1db0,
msg=msg@entry=0x2aa000cc710, expectReply=expectReply@entry=true,
nonBlock=nonBlock@entry=false) at ../../src/rpc/virnetclient.c:2116
6 0x000003fffdba6268 in
virNetClientSendWithReply (client=0x3ffe08c1db0, msg=0x2aa000cc710) at
../../src/rpc/virnetclient.c:2144
7 0x000003fffdba6e8e in virNetClientProgramCall (prog=0x3ffe08c1120,
client=<optimized out>, serial=<optimized out>, proc=<optimized out>,
noutfds=<optimized out>, outfds=0x0, ninfds=0x0, infds=0x0,
args_filter=0x3fffdb64440
<xdr_virLogManagerProtocolDomainReadLogFileArgs>, args=0x3ffffffe010,
ret_filter=0x3fffdb644c0
<xdr_virLogManagerProtocolDomainReadLogFileRet>, ret=0x3ffffffe008) at
../../src/rpc/virnetclientprogram.c:329
8 0x000003fffdb64042 in
virLogManagerDomainReadLogFile (mgr=<optimized out>, path=<optimized
out>, inode=<optimized out>, offset=<optimized out>, maxlen=<optimized
out>, flags=0) at ../../src/logging/log_manager.c:272
9 0x000003ffe9e0315c in qemuDomainLogContextRead (ctxt=0x3ffe08c2980,
msg=0x3ffffffe1c0) at ../../src/qemu/qemu_domain.c:4422
10 0x000003ffe9e280a8 in qemuProcessReadLog (logCtxt=<optimized out>,
msg=msg@entry=0x3ffffffe288) at ../../src/qemu/qemu_process.c:1800
11 0x000003ffe9e28206 in qemuProcessReportLogError (logCtxt=<optimized
out>, msgprefix=0x3ffe9ec276a "qemu unexpectedly closed the monitor")
at ../../src/qemu/qemu_process.c:1836
12 0x000003ffe9e28306 in
qemuProcessMonitorReportLogError (mon=mon@entry=0x3ffe085cf10,
msg=<optimized out>, opaque=<optimized out>) at
../../src/qemu/qemu_process.c:1856
13 0x000003ffe9e452b6 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe085cf10) at
../../src/qemu/qemu_monitor.c:726
14 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
15 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
16 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
17 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
18 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Other code parts where the same problem was possible to occur are
fixed as well (qemuMigrationFinish, qemuProcessStart, and
qemuDomainSaveImageStartVM).
Signed-off-by: Marc Hartmayer <mhartmay@linux.vnet.ibm.com>
Reported-by: Sascha Silbe <silbe@linux.vnet.ibm.com>
2017-04-03 08:24:35 +00:00
|
|
|
*
|
|
|
|
* Set the file descriptor of the open VM log file to report potential
|
|
|
|
* early startup errors of qemu. This function requires @mon to be
|
|
|
|
* locked already!
|
2013-09-18 14:12:17 +00:00
|
|
|
*/
|
2015-11-12 13:54:04 +00:00
|
|
|
void
|
qemu: Fix two use-after-free situations
There were multiple race conditions that could lead to segmentation
faults. The first precondition for this is qemuProcessLaunch must fail
sometime shortly after starting the new QEMU process. The second
precondition for the segmentation faults is that the new QEMU process
dies - or to be more precise the QEMU monitor has to be closed
irregularly. If both happens during qemuProcessStart (starting a
domain) there are race windows between the thread with the event
loop (T1) and the thread that is starting the domain (T2).
First segmentation fault scenario:
If qemuProcessLaunch fails during qemuProcessStart the code branches
to the 'stop' path where 'qemuMonitorSetDomainLog(priv->mon, NULL,
NULL, NULL)' will set the log function of the monitor to NULL (done in
T2). In the meantime the event loop of T1 will wake up with an EOF
event for the QEMU monitor because the QEMU process has died. The
crash occurs if T1 has checked 'mon->logFunc != NULL' in qemuMonitorIO
just before the logFunc was set to NULL by T2. If this situation
occurs T1 will try to call mon->logFunc which leads to the
segmentation fault.
Solution:
Require the monitor lock for setting the log function.
Backtrace:
0 0x0000000000000000 in ?? ()
1 0x000003ffe9e45316 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe08aa860) at
../../src/qemu/qemu_monitor.c:727
2 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
3 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
4 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
5 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
6 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Second segmentation fault scenario:
If qemuProcessLaunch fails it will unref the log context and with
invoking qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL)
qemuDomainLogContextFree() will be invoked. qemuDomainLogContextFree()
invokes virNetClientClose() to close the client and cleans everything
up (including unref of _virLogManager.client) when virNetClientClose()
returns. When T1 is now trying to report 'qemu unexpectedly closed the
monitor' libvirtd will crash because the client has already been
freed.
Solution:
As the critical section in qemuMonitorIO is protected with the monitor
lock we can use the same solution as proposed for the first
segmentation fault.
Backtrace:
0 virClassIsDerivedFrom (klass=0x3100979797979797,
parent=0x2aa000d92f0) at ../../src/util/virobject.c:169
1 0x000003fffda659e6 in virObjectIsClass (anyobj=<optimized out>,
klass=<optimized out>) at ../../src/util/virobject.c:365
2 0x000003fffda65a24 in virObjectLock (anyobj=0x3ffe08c1db0) at
../../src/util/virobject.c:317
3 0x000003fffdba4688 in
virNetClientIOEventLoop (client=client@entry=0x3ffe08c1db0,
thiscall=thiscall@entry=0x2aa000fbfa0) at
../../src/rpc/virnetclient.c:1668
4 0x000003fffdba4b4c in
virNetClientIO (client=client@entry=0x3ffe08c1db0,
thiscall=0x2aa000fbfa0) at ../../src/rpc/virnetclient.c:1944
5 0x000003fffdba4d42 in
virNetClientSendInternal (client=client@entry=0x3ffe08c1db0,
msg=msg@entry=0x2aa000cc710, expectReply=expectReply@entry=true,
nonBlock=nonBlock@entry=false) at ../../src/rpc/virnetclient.c:2116
6 0x000003fffdba6268 in
virNetClientSendWithReply (client=0x3ffe08c1db0, msg=0x2aa000cc710) at
../../src/rpc/virnetclient.c:2144
7 0x000003fffdba6e8e in virNetClientProgramCall (prog=0x3ffe08c1120,
client=<optimized out>, serial=<optimized out>, proc=<optimized out>,
noutfds=<optimized out>, outfds=0x0, ninfds=0x0, infds=0x0,
args_filter=0x3fffdb64440
<xdr_virLogManagerProtocolDomainReadLogFileArgs>, args=0x3ffffffe010,
ret_filter=0x3fffdb644c0
<xdr_virLogManagerProtocolDomainReadLogFileRet>, ret=0x3ffffffe008) at
../../src/rpc/virnetclientprogram.c:329
8 0x000003fffdb64042 in
virLogManagerDomainReadLogFile (mgr=<optimized out>, path=<optimized
out>, inode=<optimized out>, offset=<optimized out>, maxlen=<optimized
out>, flags=0) at ../../src/logging/log_manager.c:272
9 0x000003ffe9e0315c in qemuDomainLogContextRead (ctxt=0x3ffe08c2980,
msg=0x3ffffffe1c0) at ../../src/qemu/qemu_domain.c:4422
10 0x000003ffe9e280a8 in qemuProcessReadLog (logCtxt=<optimized out>,
msg=msg@entry=0x3ffffffe288) at ../../src/qemu/qemu_process.c:1800
11 0x000003ffe9e28206 in qemuProcessReportLogError (logCtxt=<optimized
out>, msgprefix=0x3ffe9ec276a "qemu unexpectedly closed the monitor")
at ../../src/qemu/qemu_process.c:1836
12 0x000003ffe9e28306 in
qemuProcessMonitorReportLogError (mon=mon@entry=0x3ffe085cf10,
msg=<optimized out>, opaque=<optimized out>) at
../../src/qemu/qemu_process.c:1856
13 0x000003ffe9e452b6 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe085cf10) at
../../src/qemu/qemu_monitor.c:726
14 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
15 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
16 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
17 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
18 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Other code parts where the same problem was possible to occur are
fixed as well (qemuMigrationFinish, qemuProcessStart, and
qemuDomainSaveImageStartVM).
Signed-off-by: Marc Hartmayer <mhartmay@linux.vnet.ibm.com>
Reported-by: Sascha Silbe <silbe@linux.vnet.ibm.com>
2017-04-03 08:24:35 +00:00
|
|
|
qemuMonitorSetDomainLogLocked(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorReportDomainLogError func,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback destroy)
|
2013-09-18 14:12:17 +00:00
|
|
|
{
|
2015-11-12 13:54:04 +00:00
|
|
|
if (mon->logDestroy && mon->logOpaque)
|
|
|
|
mon->logDestroy(mon->logOpaque);
|
2013-09-18 14:12:17 +00:00
|
|
|
|
2015-11-12 13:54:04 +00:00
|
|
|
mon->logFunc = func;
|
|
|
|
mon->logOpaque = opaque;
|
|
|
|
mon->logDestroy = destroy;
|
2013-09-18 14:12:17 +00:00
|
|
|
}
|
2013-07-22 11:07:23 +00:00
|
|
|
|
|
|
|
|
qemu: Fix two use-after-free situations
There were multiple race conditions that could lead to segmentation
faults. The first precondition for this is qemuProcessLaunch must fail
sometime shortly after starting the new QEMU process. The second
precondition for the segmentation faults is that the new QEMU process
dies - or to be more precise the QEMU monitor has to be closed
irregularly. If both happens during qemuProcessStart (starting a
domain) there are race windows between the thread with the event
loop (T1) and the thread that is starting the domain (T2).
First segmentation fault scenario:
If qemuProcessLaunch fails during qemuProcessStart the code branches
to the 'stop' path where 'qemuMonitorSetDomainLog(priv->mon, NULL,
NULL, NULL)' will set the log function of the monitor to NULL (done in
T2). In the meantime the event loop of T1 will wake up with an EOF
event for the QEMU monitor because the QEMU process has died. The
crash occurs if T1 has checked 'mon->logFunc != NULL' in qemuMonitorIO
just before the logFunc was set to NULL by T2. If this situation
occurs T1 will try to call mon->logFunc which leads to the
segmentation fault.
Solution:
Require the monitor lock for setting the log function.
Backtrace:
0 0x0000000000000000 in ?? ()
1 0x000003ffe9e45316 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe08aa860) at
../../src/qemu/qemu_monitor.c:727
2 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
3 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
4 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
5 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
6 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Second segmentation fault scenario:
If qemuProcessLaunch fails it will unref the log context and with
invoking qemuMonitorSetDomainLog(priv->mon, NULL, NULL, NULL)
qemuDomainLogContextFree() will be invoked. qemuDomainLogContextFree()
invokes virNetClientClose() to close the client and cleans everything
up (including unref of _virLogManager.client) when virNetClientClose()
returns. When T1 is now trying to report 'qemu unexpectedly closed the
monitor' libvirtd will crash because the client has already been
freed.
Solution:
As the critical section in qemuMonitorIO is protected with the monitor
lock we can use the same solution as proposed for the first
segmentation fault.
Backtrace:
0 virClassIsDerivedFrom (klass=0x3100979797979797,
parent=0x2aa000d92f0) at ../../src/util/virobject.c:169
1 0x000003fffda659e6 in virObjectIsClass (anyobj=<optimized out>,
klass=<optimized out>) at ../../src/util/virobject.c:365
2 0x000003fffda65a24 in virObjectLock (anyobj=0x3ffe08c1db0) at
../../src/util/virobject.c:317
3 0x000003fffdba4688 in
virNetClientIOEventLoop (client=client@entry=0x3ffe08c1db0,
thiscall=thiscall@entry=0x2aa000fbfa0) at
../../src/rpc/virnetclient.c:1668
4 0x000003fffdba4b4c in
virNetClientIO (client=client@entry=0x3ffe08c1db0,
thiscall=0x2aa000fbfa0) at ../../src/rpc/virnetclient.c:1944
5 0x000003fffdba4d42 in
virNetClientSendInternal (client=client@entry=0x3ffe08c1db0,
msg=msg@entry=0x2aa000cc710, expectReply=expectReply@entry=true,
nonBlock=nonBlock@entry=false) at ../../src/rpc/virnetclient.c:2116
6 0x000003fffdba6268 in
virNetClientSendWithReply (client=0x3ffe08c1db0, msg=0x2aa000cc710) at
../../src/rpc/virnetclient.c:2144
7 0x000003fffdba6e8e in virNetClientProgramCall (prog=0x3ffe08c1120,
client=<optimized out>, serial=<optimized out>, proc=<optimized out>,
noutfds=<optimized out>, outfds=0x0, ninfds=0x0, infds=0x0,
args_filter=0x3fffdb64440
<xdr_virLogManagerProtocolDomainReadLogFileArgs>, args=0x3ffffffe010,
ret_filter=0x3fffdb644c0
<xdr_virLogManagerProtocolDomainReadLogFileRet>, ret=0x3ffffffe008) at
../../src/rpc/virnetclientprogram.c:329
8 0x000003fffdb64042 in
virLogManagerDomainReadLogFile (mgr=<optimized out>, path=<optimized
out>, inode=<optimized out>, offset=<optimized out>, maxlen=<optimized
out>, flags=0) at ../../src/logging/log_manager.c:272
9 0x000003ffe9e0315c in qemuDomainLogContextRead (ctxt=0x3ffe08c2980,
msg=0x3ffffffe1c0) at ../../src/qemu/qemu_domain.c:4422
10 0x000003ffe9e280a8 in qemuProcessReadLog (logCtxt=<optimized out>,
msg=msg@entry=0x3ffffffe288) at ../../src/qemu/qemu_process.c:1800
11 0x000003ffe9e28206 in qemuProcessReportLogError (logCtxt=<optimized
out>, msgprefix=0x3ffe9ec276a "qemu unexpectedly closed the monitor")
at ../../src/qemu/qemu_process.c:1836
12 0x000003ffe9e28306 in
qemuProcessMonitorReportLogError (mon=mon@entry=0x3ffe085cf10,
msg=<optimized out>, opaque=<optimized out>) at
../../src/qemu/qemu_process.c:1856
13 0x000003ffe9e452b6 in qemuMonitorIO (watch=<optimized out>,
fd=<optimized out>, events=<optimized out>, opaque=0x3ffe085cf10) at
../../src/qemu/qemu_monitor.c:726
14 0x000003fffda2e1a4 in virEventPollDispatchHandles (nfds=<optimized
out>, fds=0x2aa000fd980) at ../../src/util/vireventpoll.c:508
15 0x000003fffda2e398 in virEventPollRunOnce () at
../../src/util/vireventpoll.c:657
16 0x000003fffda2ca10 in virEventRunDefaultImpl () at
../../src/util/virevent.c:314
17 0x000003fffdba9366 in virNetDaemonRun (dmn=0x2aa000cc550) at
../../src/rpc/virnetdaemon.c:818
18 0x000002aa00024668 in main (argc=<optimized out>, argv=<optimized
out>) at ../../daemon/libvirtd.c:1541
Other code parts where the same problem was possible to occur are
fixed as well (qemuMigrationFinish, qemuProcessStart, and
qemuDomainSaveImageStartVM).
Signed-off-by: Marc Hartmayer <mhartmay@linux.vnet.ibm.com>
Reported-by: Sascha Silbe <silbe@linux.vnet.ibm.com>
2017-04-03 08:24:35 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorSetDomainLog:
|
|
|
|
* @mon: Unlocked monitor object to set the log file reading on
|
|
|
|
* @func: the callback to report errors
|
|
|
|
* @opaque: data to pass to @func
|
|
|
|
* @destroy: optional callback to free @opaque
|
|
|
|
*
|
|
|
|
* Set the file descriptor of the open VM log file to report potential
|
|
|
|
* early startup errors of qemu. This functions requires @mon to be
|
|
|
|
* unlocked.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
qemuMonitorSetDomainLog(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorReportDomainLogError func,
|
|
|
|
void *opaque,
|
|
|
|
virFreeCallback destroy)
|
|
|
|
{
|
|
|
|
virObjectLock(mon);
|
|
|
|
qemuMonitorSetDomainLogLocked(mon, func, opaque, destroy);
|
|
|
|
virObjectUnlock(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-22 11:07:23 +00:00
|
|
|
/**
|
2019-06-17 14:56:32 +00:00
|
|
|
* qemuMonitorJSONGetGuestCPUx86:
|
2013-07-22 11:07:23 +00:00
|
|
|
* @mon: Pointer to the monitor
|
2013-11-11 13:47:08 +00:00
|
|
|
* @data: returns the cpu data
|
2017-03-13 10:00:48 +00:00
|
|
|
* @disabled: returns the CPU data for features which were disabled by QEMU
|
2013-07-22 11:07:23 +00:00
|
|
|
*
|
|
|
|
* Retrieve the definition of the guest CPU from a running qemu instance.
|
|
|
|
*
|
2013-11-11 13:47:08 +00:00
|
|
|
* Returns 0 on success, -2 if the operation is not supported by the guest,
|
|
|
|
* -1 on other errors.
|
2013-07-22 11:07:23 +00:00
|
|
|
*/
|
2013-11-11 13:47:08 +00:00
|
|
|
int
|
2019-06-17 14:56:32 +00:00
|
|
|
qemuMonitorGetGuestCPUx86(qemuMonitorPtr mon,
|
|
|
|
virCPUDataPtr *data,
|
|
|
|
virCPUDataPtr *disabled)
|
2013-07-22 11:07:23 +00:00
|
|
|
{
|
2019-06-17 14:56:32 +00:00
|
|
|
VIR_DEBUG("data=%p disabled=%p", data, disabled);
|
2013-07-22 11:07:23 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2013-07-22 11:07:23 +00:00
|
|
|
|
2013-11-11 13:47:08 +00:00
|
|
|
*data = NULL;
|
2017-03-13 10:00:48 +00:00
|
|
|
if (disabled)
|
|
|
|
*disabled = NULL;
|
2013-11-11 13:47:08 +00:00
|
|
|
|
2019-06-17 14:56:32 +00:00
|
|
|
return qemuMonitorJSONGetGuestCPUx86(mon, data, disabled);
|
2013-07-22 11:07:23 +00:00
|
|
|
}
|
2014-08-13 12:28:24 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2019-06-17 21:36:53 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorGetGuestCPU:
|
|
|
|
* @mon: Pointer to the monitor
|
|
|
|
* @arch: CPU architecture
|
|
|
|
* @translate: callback for translating CPU feature names from QEMU to libvirt
|
|
|
|
* @opaque: data for @translate callback
|
|
|
|
* @enabled: returns the CPU data for all enabled features
|
|
|
|
* @disabled: returns the CPU data for features which we asked for
|
|
|
|
* (either explicitly or via a named CPU model) but QEMU disabled them
|
|
|
|
*
|
|
|
|
* Retrieve the definition of the guest CPU from a running QEMU instance.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
|
|
|
|
virArch arch,
|
|
|
|
qemuMonitorCPUFeatureTranslationCallback translate,
|
|
|
|
void *opaque,
|
|
|
|
virCPUDataPtr *enabled,
|
|
|
|
virCPUDataPtr *disabled)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("arch=%s translate=%p opaque=%p enabled=%p disabled=%p",
|
|
|
|
virArchToString(arch), translate, opaque, enabled, disabled);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
*enabled = NULL;
|
|
|
|
if (disabled)
|
|
|
|
*disabled = NULL;
|
|
|
|
|
|
|
|
return qemuMonitorJSONGetGuestCPU(mon, arch, translate, opaque,
|
|
|
|
enabled, disabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-13 12:28:24 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorRTCResetReinjection:
|
|
|
|
* @mon: Pointer to the monitor
|
|
|
|
*
|
|
|
|
* Issue rtc-reset-reinjection command.
|
|
|
|
* This should be used in cases where guest time is restored via
|
|
|
|
* guest agent, so RTC injection is not needed (in fact it would
|
|
|
|
* confuse guest's RTC).
|
|
|
|
*
|
|
|
|
* Returns 0 on success
|
|
|
|
* -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorRTCResetReinjection(qemuMonitorPtr mon)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2014-08-13 12:28:24 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONRTCResetReinjection(mon);
|
|
|
|
}
|
2014-08-29 20:23:11 +00:00
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2014-08-29 20:23:11 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorGetIOThreads:
|
|
|
|
* @mon: Pointer to the monitor
|
|
|
|
* @iothreads: Location to return array of IOThreadInfo data
|
|
|
|
*
|
|
|
|
* Issue query-iothreads command.
|
|
|
|
* Retrieve the list of iothreads defined/running for the machine
|
|
|
|
*
|
|
|
|
* Returns count of IOThreadInfo structures on success
|
|
|
|
* -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorGetIOThreads(qemuMonitorPtr mon,
|
2015-03-25 15:59:37 +00:00
|
|
|
qemuMonitorIOThreadInfoPtr **iothreads)
|
2014-08-29 20:23:11 +00:00
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("iothreads=%p", iothreads);
|
2014-08-29 20:23:11 +00:00
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2014-08-29 20:23:11 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetIOThreads(mon, iothreads);
|
|
|
|
}
|
|
|
|
|
2015-04-14 13:14:23 +00:00
|
|
|
|
2018-10-03 22:13:14 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorSetIOThread:
|
|
|
|
* @mon: Pointer to the monitor
|
|
|
|
* @iothreadInfo: filled IOThread info with data
|
|
|
|
*
|
|
|
|
* Alter the specified IOThread's IOThreadInfo values.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorSetIOThread(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorIOThreadInfoPtr iothreadInfo)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("iothread=%p", iothreadInfo);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONSetIOThread(mon, iothreadInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-01-19 12:21:09 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorGetMemoryDeviceInfo:
|
|
|
|
* @mon: pointer to the monitor
|
|
|
|
* @info: Location to return the hash of qemuMonitorMemoryDeviceInfo
|
|
|
|
*
|
|
|
|
* Retrieve state and addresses of frontend memory devices present in
|
|
|
|
* the guest.
|
|
|
|
*
|
|
|
|
* Returns 0 on success and fills @info with a newly allocated struct; if the
|
|
|
|
* data can't be retrieved due to lack of support in qemu, returns -2. On
|
|
|
|
* other errors returns -1.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorGetMemoryDeviceInfo(qemuMonitorPtr mon,
|
|
|
|
virHashTablePtr *info)
|
|
|
|
{
|
2015-04-14 15:52:48 +00:00
|
|
|
VIR_DEBUG("info=%p", info);
|
2015-01-19 12:21:09 +00:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
*info = NULL;
|
|
|
|
|
2015-04-14 15:52:48 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-01-19 12:21:09 +00:00
|
|
|
|
|
|
|
if (!(*info = virHashCreate(10, virHashValueFree)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((ret = qemuMonitorJSONGetMemoryDeviceInfo(mon, *info)) < 0) {
|
|
|
|
virHashFree(*info);
|
|
|
|
*info = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2015-10-20 20:51:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorMigrateIncoming(qemuMonitorPtr mon,
|
|
|
|
const char *uri)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("uri=%s", uri);
|
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2015-10-20 20:51:48 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONMigrateIncoming(mon, uri);
|
|
|
|
}
|
2014-12-01 15:59:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorMigrateStartPostCopy(qemuMonitorPtr mon)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2014-12-01 15:59:54 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONMigrateStartPostCopy(mon);
|
|
|
|
}
|
2016-04-29 14:01:47 +00:00
|
|
|
|
2017-10-20 07:17:09 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorMigrateContinue(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorMigrationStatus status)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("status=%s", qemuMonitorMigrationStatusTypeToString(status));
|
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2017-10-20 07:17:09 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONMigrateContinue(mon, status);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-04-29 14:01:47 +00:00
|
|
|
int
|
|
|
|
qemuMonitorGetRTCTime(qemuMonitorPtr mon,
|
|
|
|
struct tm *tm)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2016-04-29 14:01:47 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONGetRTCTime(mon, tm);
|
|
|
|
}
|
2016-10-17 12:20:42 +00:00
|
|
|
|
|
|
|
|
2018-03-20 08:29:30 +00:00
|
|
|
virJSONValuePtr
|
2016-10-17 12:20:42 +00:00
|
|
|
qemuMonitorQueryQMPSchema(qemuMonitorPtr mon)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
2016-10-17 12:20:42 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONQueryQMPSchema(mon);
|
|
|
|
}
|
2017-02-23 12:50:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorSetBlockThreshold(qemuMonitorPtr mon,
|
|
|
|
const char *nodename,
|
|
|
|
unsigned long long threshold)
|
|
|
|
{
|
2017-04-05 12:01:46 +00:00
|
|
|
VIR_DEBUG("node='%s', threshold=%llu", nodename, threshold);
|
2017-02-23 12:50:24 +00:00
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2017-02-23 12:50:24 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONSetBlockThreshold(mon, nodename, threshold);
|
|
|
|
}
|
2017-02-24 13:59:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
virJSONValuePtr
|
|
|
|
qemuMonitorQueryNamedBlockNodes(qemuMonitorPtr mon)
|
|
|
|
{
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
2017-02-24 13:59:40 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONQueryNamedBlockNodes(mon);
|
|
|
|
}
|
2017-03-20 13:35:33 +00:00
|
|
|
|
|
|
|
|
2017-03-20 16:55:56 +00:00
|
|
|
char *
|
|
|
|
qemuMonitorGuestPanicEventInfoFormatMsg(qemuMonitorEventPanicInfoPtr info)
|
|
|
|
{
|
|
|
|
char *ret = NULL;
|
|
|
|
|
|
|
|
switch (info->type) {
|
|
|
|
case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_HYPERV:
|
2019-10-22 13:26:14 +00:00
|
|
|
ret = g_strdup_printf("hyper-v: arg1='0x%llx', arg2='0x%llx', "
|
|
|
|
"arg3='0x%llx', arg4='0x%llx', arg5='0x%llx'",
|
|
|
|
info->data.hyperv.arg1, info->data.hyperv.arg2,
|
|
|
|
info->data.hyperv.arg3, info->data.hyperv.arg4,
|
|
|
|
info->data.hyperv.arg5);
|
2017-03-20 16:55:56 +00:00
|
|
|
break;
|
qemu: log the crash information for S390
Since QEMU 2.12 commit id '4ada99ade' guest crash information for
S390 is available in the QEMU monitor, e.g.:
{
"timestamp": {
"seconds": 1518004739,
"microseconds": 552563
},
"event": "GUEST_PANICKED",
"data": {
"action": "pause",
"info": {
"core": 0,
"psw-addr": 1102832,
"reason": "disabled-wait",
"psw-mask": 562956395872256,
"type": "s390"
}
}
}
Let's log this information into the domain log file, e.g.:
2018-02-08 13:11:26.075+0000: panic s390: core='0' psw-mask='0x0002000180000000' psw-addr='0x000000000010f146' reason='disabled-wait'
Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com>
Signed-off-by: Bjoern Walk <bwalk@linux.vnet.ibm.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
2018-02-27 09:32:56 +00:00
|
|
|
case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_S390:
|
2019-10-22 13:26:14 +00:00
|
|
|
ret = g_strdup_printf("s390: core='%d' psw-mask='0x%016llx' "
|
|
|
|
"psw-addr='0x%016llx' reason='%s'",
|
|
|
|
info->data.s390.core,
|
|
|
|
info->data.s390.psw_mask,
|
|
|
|
info->data.s390.psw_addr,
|
|
|
|
info->data.s390.reason);
|
qemu: log the crash information for S390
Since QEMU 2.12 commit id '4ada99ade' guest crash information for
S390 is available in the QEMU monitor, e.g.:
{
"timestamp": {
"seconds": 1518004739,
"microseconds": 552563
},
"event": "GUEST_PANICKED",
"data": {
"action": "pause",
"info": {
"core": 0,
"psw-addr": 1102832,
"reason": "disabled-wait",
"psw-mask": 562956395872256,
"type": "s390"
}
}
}
Let's log this information into the domain log file, e.g.:
2018-02-08 13:11:26.075+0000: panic s390: core='0' psw-mask='0x0002000180000000' psw-addr='0x000000000010f146' reason='disabled-wait'
Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com>
Signed-off-by: Bjoern Walk <bwalk@linux.vnet.ibm.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
2018-02-27 09:32:56 +00:00
|
|
|
break;
|
2017-03-20 16:55:56 +00:00
|
|
|
case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_NONE:
|
|
|
|
case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-03-20 13:35:33 +00:00
|
|
|
void
|
|
|
|
qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfoPtr info)
|
|
|
|
{
|
|
|
|
if (!info)
|
|
|
|
return;
|
|
|
|
|
qemu: log the crash information for S390
Since QEMU 2.12 commit id '4ada99ade' guest crash information for
S390 is available in the QEMU monitor, e.g.:
{
"timestamp": {
"seconds": 1518004739,
"microseconds": 552563
},
"event": "GUEST_PANICKED",
"data": {
"action": "pause",
"info": {
"core": 0,
"psw-addr": 1102832,
"reason": "disabled-wait",
"psw-mask": 562956395872256,
"type": "s390"
}
}
}
Let's log this information into the domain log file, e.g.:
2018-02-08 13:11:26.075+0000: panic s390: core='0' psw-mask='0x0002000180000000' psw-addr='0x000000000010f146' reason='disabled-wait'
Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com>
Signed-off-by: Bjoern Walk <bwalk@linux.vnet.ibm.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
2018-02-27 09:32:56 +00:00
|
|
|
switch (info->type) {
|
|
|
|
case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_S390:
|
|
|
|
VIR_FREE(info->data.s390.reason);
|
|
|
|
break;
|
|
|
|
case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_NONE:
|
|
|
|
case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_HYPERV:
|
|
|
|
case QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-03-20 13:35:33 +00:00
|
|
|
VIR_FREE(info);
|
|
|
|
}
|
2017-09-01 11:39:15 +00:00
|
|
|
|
|
|
|
|
2018-12-24 10:15:12 +00:00
|
|
|
void
|
|
|
|
qemuMonitorEventRdmaGidStatusFree(qemuMonitorRdmaGidStatusPtr info)
|
|
|
|
{
|
|
|
|
if (!info)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(info->netdev);
|
|
|
|
VIR_FREE(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-09-01 11:39:15 +00:00
|
|
|
int
|
|
|
|
qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
|
|
|
|
const char *action)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("watchdogAction=%s", action);
|
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2017-09-01 11:39:15 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONSetWatchdogAction(mon, action);
|
|
|
|
}
|
2018-02-20 17:04:47 +00:00
|
|
|
|
|
|
|
|
2018-09-03 12:45:16 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorBlockdevCreate:
|
|
|
|
* @mon: monitor object
|
|
|
|
* @jobname: name of the job
|
|
|
|
* @props: JSON object describing the blockdev to add
|
|
|
|
*
|
|
|
|
* Instructs qemu to create/format a new stroage or format layer. Note that
|
|
|
|
* the job does not add the created/formatted image into qemu and
|
|
|
|
* qemuMonitorBlockdevAdd needs to be called separately with corresponding
|
|
|
|
* arguments. Note that the arguments for creating and adding are different.
|
|
|
|
*
|
|
|
|
* Note that @props is always consumed by this function and should not be
|
|
|
|
* accessed after calling this function.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorBlockdevCreate(qemuMonitorPtr mon,
|
|
|
|
const char *jobname,
|
|
|
|
virJSONValuePtr props)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("jobname=%s props=%p", jobname, props);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR_GOTO(mon, error);
|
|
|
|
|
|
|
|
return qemuMonitorJSONBlockdevCreate(mon, jobname, props);
|
|
|
|
|
|
|
|
error:
|
|
|
|
virJSONValueFree(props);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-02-20 17:04:47 +00:00
|
|
|
/**
|
|
|
|
* qemuMonitorBlockdevAdd:
|
|
|
|
* @mon: monitor object
|
|
|
|
* @props: JSON object describing the blockdev to add
|
|
|
|
*
|
|
|
|
* Adds a new block device (BDS) to qemu. Note that @props is always consumed
|
|
|
|
* by this function and should not be accessed after calling this function.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
qemuMonitorBlockdevAdd(qemuMonitorPtr mon,
|
|
|
|
virJSONValuePtr props)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("props=%p (node-name=%s)", props,
|
|
|
|
NULLSTR(virJSONValueObjectGetString(props, "node-name")));
|
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR_GOTO(mon, error);
|
2018-02-20 17:04:47 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONBlockdevAdd(mon, props);
|
|
|
|
|
|
|
|
error:
|
|
|
|
virJSONValueFree(props);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorBlockdevDel(qemuMonitorPtr mon,
|
|
|
|
const char *nodename)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("nodename=%s", nodename);
|
|
|
|
|
2018-05-22 11:23:34 +00:00
|
|
|
QEMU_CHECK_MONITOR(mon);
|
2018-02-20 17:04:47 +00:00
|
|
|
|
|
|
|
return qemuMonitorJSONBlockdevDel(mon, nodename);
|
|
|
|
}
|
2018-06-08 14:41:01 +00:00
|
|
|
|
2018-07-12 10:11:31 +00:00
|
|
|
int
|
|
|
|
qemuMonitorBlockdevTrayOpen(qemuMonitorPtr mon,
|
|
|
|
const char *id,
|
|
|
|
bool force)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("id=%s force=%d", id, force);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONBlockdevTrayOpen(mon, id, force);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorBlockdevTrayClose(qemuMonitorPtr mon,
|
|
|
|
const char *id)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("id=%s", id);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONBlockdevTrayClose(mon, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorBlockdevMediumRemove(qemuMonitorPtr mon,
|
|
|
|
const char *id)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("id=%s", id);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONBlockdevMediumRemove(mon, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorBlockdevMediumInsert(qemuMonitorPtr mon,
|
|
|
|
const char *id,
|
|
|
|
const char *nodename)
|
|
|
|
{
|
|
|
|
VIR_DEBUG("id=%s nodename=%s", id, nodename);
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONBlockdevMediumInsert(mon, id, nodename);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-08 14:41:01 +00:00
|
|
|
char *
|
|
|
|
qemuMonitorGetSEVMeasurement(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
QEMU_CHECK_MONITOR_NULL(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONGetSEVMeasurement(mon);
|
|
|
|
}
|
2018-07-03 10:07:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorGetPRManagerInfo(qemuMonitorPtr mon,
|
|
|
|
virHashTablePtr *retinfo)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
virHashTablePtr info = NULL;
|
|
|
|
|
|
|
|
*retinfo = NULL;
|
|
|
|
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
if (!(info = virHashCreate(10, virHashValueFree)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (qemuMonitorJSONGetPRManagerInfo(mon, info) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2019-10-16 11:43:18 +00:00
|
|
|
*retinfo = g_steal_pointer(&info);
|
2018-07-03 10:07:30 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virHashFree(info);
|
|
|
|
return ret;
|
|
|
|
}
|
2019-04-24 21:16:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorGetCurrentMachineInfo(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorCurrentMachineInfoPtr info)
|
|
|
|
{
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONGetCurrentMachineInfo(mon, info);
|
|
|
|
}
|
2019-06-06 02:25:05 +00:00
|
|
|
|
|
|
|
|
2018-12-04 16:58:38 +00:00
|
|
|
void
|
|
|
|
qemuMonitorJobInfoFree(qemuMonitorJobInfoPtr job)
|
|
|
|
{
|
|
|
|
if (!job)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(job->id);
|
|
|
|
VIR_FREE(job->error);
|
|
|
|
VIR_FREE(job);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorGetJobInfo(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorJobInfoPtr **jobs,
|
|
|
|
size_t *njobs)
|
|
|
|
{
|
|
|
|
QEMU_CHECK_MONITOR(mon);
|
|
|
|
|
|
|
|
return qemuMonitorJSONGetJobInfo(mon, jobs, njobs);
|
|
|
|
}
|
2019-09-26 13:53:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorTransactionBitmapAdd(virJSONValuePtr actions,
|
|
|
|
const char *node,
|
|
|
|
const char *name,
|
|
|
|
bool persistent,
|
|
|
|
bool disabled)
|
|
|
|
{
|
|
|
|
return qemuMonitorJSONTransactionBitmapAdd(actions, node, name, persistent, disabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorTransactionBitmapRemove(virJSONValuePtr actions,
|
|
|
|
const char *node,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
return qemuMonitorJSONTransactionBitmapRemove(actions, node, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorTransactionBitmapEnable(virJSONValuePtr actions,
|
|
|
|
const char *node,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
return qemuMonitorJSONTransactionBitmapEnable(actions, node, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorTransactionBitmapDisable(virJSONValuePtr actions,
|
|
|
|
const char *node,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
return qemuMonitorJSONTransactionBitmapDisable(actions, node, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorTransactionBitmapMerge(virJSONValuePtr actions,
|
|
|
|
const char *node,
|
|
|
|
const char *target,
|
|
|
|
virJSONValuePtr *sources)
|
|
|
|
{
|
|
|
|
return qemuMonitorJSONTransactionBitmapMerge(actions, node, target, sources);
|
|
|
|
}
|
2019-09-26 14:03:46 +00:00
|
|
|
|
|
|
|
|
2019-10-07 14:19:34 +00:00
|
|
|
int
|
|
|
|
qemuMonitorTransactionBitmapMergeSourceAddBitmap(virJSONValuePtr sources,
|
|
|
|
const char *sourcenode,
|
|
|
|
const char *sourcebitmap)
|
|
|
|
{
|
|
|
|
return qemuMonitorJSONTransactionBitmapMergeSourceAddBitmap(sources, sourcenode, sourcebitmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-26 14:03:46 +00:00
|
|
|
int
|
|
|
|
qemuMonitorTransactionSnapshotLegacy(virJSONValuePtr actions,
|
|
|
|
const char *device,
|
|
|
|
const char *path,
|
|
|
|
const char *format,
|
|
|
|
bool existing)
|
|
|
|
{
|
|
|
|
return qemuMonitorJSONTransactionSnapshotLegacy(actions, device, path,
|
|
|
|
format, existing);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorTransactionSnapshotBlockdev(virJSONValuePtr actions,
|
|
|
|
const char *node,
|
|
|
|
const char *overlay)
|
|
|
|
{
|
|
|
|
return qemuMonitorJSONTransactionSnapshotBlockdev(actions, node, overlay);
|
|
|
|
}
|
2019-09-27 15:28:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorTransactionBackup(virJSONValuePtr actions,
|
|
|
|
const char *device,
|
|
|
|
const char *jobname,
|
|
|
|
const char *target,
|
|
|
|
const char *bitmap,
|
|
|
|
qemuMonitorTransactionBackupSyncMode syncmode)
|
|
|
|
{
|
|
|
|
return qemuMonitorJSONTransactionBackup(actions, device, jobname, target,
|
|
|
|
bitmap, syncmode);
|
|
|
|
}
|