2009-10-09 18:07:55 +00:00
|
|
|
/*
|
|
|
|
* qemu_monitor.c: interaction with QEMU monitor console
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006-2009 Red Hat, Inc.
|
|
|
|
* 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
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <poll.h>
|
|
|
|
#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-10-09 18:07:55 +00:00
|
|
|
#include "qemu_conf.h"
|
|
|
|
#include "event.h"
|
|
|
|
#include "virterror_internal.h"
|
2009-10-09 19:13:29 +00:00
|
|
|
#include "memory.h"
|
|
|
|
#include "logging.h"
|
2009-10-09 18:07:55 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_QEMU
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
struct _qemuMonitor {
|
2009-10-13 14:27:58 +00:00
|
|
|
virMutex 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
|
|
|
virCond notify;
|
|
|
|
|
|
|
|
virDomainObjPtr dom;
|
2009-10-13 14:27:58 +00:00
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
int fd;
|
|
|
|
int watch;
|
|
|
|
int hasSendFD;
|
|
|
|
|
|
|
|
virDomainObjPtr vm;
|
|
|
|
|
|
|
|
qemuMonitorEOFNotify eofCB;
|
2009-10-09 19:34:24 +00:00
|
|
|
qemuMonitorDiskSecretLookup secretCB;
|
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 */
|
|
|
|
int lastErrno;
|
|
|
|
|
|
|
|
/* If the monitor callback is currently active */
|
|
|
|
unsigned eofcb: 1;
|
|
|
|
/* If the monitor callback should free the closed monitor */
|
|
|
|
unsigned closed: 1;
|
2009-10-09 19:13:29 +00:00
|
|
|
};
|
|
|
|
|
2009-10-13 14:27:58 +00:00
|
|
|
void qemuMonitorLock(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
virMutexLock(&mon->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void qemuMonitorUnlock(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
virMutexUnlock(&mon->lock);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
static void qemuMonitorFree(qemuMonitorPtr mon, int lockDomain)
|
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
|
|
|
VIR_DEBUG("mon=%p, lockDomain=%d", mon, lockDomain);
|
|
|
|
if (mon->vm) {
|
|
|
|
if (lockDomain)
|
|
|
|
virDomainObjLock(mon->vm);
|
|
|
|
if (!virDomainObjUnref(mon->vm) && lockDomain)
|
|
|
|
virDomainObjUnlock(mon->vm);
|
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
|
|
|
if (virCondDestroy(&mon->notify) < 0)
|
|
|
|
{}
|
|
|
|
virMutexDestroy(&mon->lock);
|
|
|
|
VIR_FREE(mon);
|
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
|
|
|
qemuMonitorOpenUnix(const char *monitor)
|
2009-10-09 18:07:55 +00:00
|
|
|
{
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
int monfd;
|
|
|
|
int timeout = 3; /* In seconds */
|
|
|
|
int ret, i = 0;
|
|
|
|
|
|
|
|
if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
|
|
virReportSystemError(NULL, errno,
|
|
|
|
"%s", _("failed to create socket"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
|
|
addr.sun_family = AF_UNIX;
|
|
|
|
if (virStrcpyStatic(addr.sun_path, monitor) == NULL) {
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Monitor path %s too big for destination"), monitor);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
ret = connect(monfd, (struct sockaddr *) &addr, sizeof(addr));
|
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (errno == ENOENT || errno == ECONNREFUSED) {
|
|
|
|
/* ENOENT : Socket may not have shown up yet
|
|
|
|
* ECONNREFUSED : Leftover socket hasn't been removed yet */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
virReportSystemError(NULL, errno, "%s",
|
|
|
|
_("failed to connect to monitor socket"));
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
} while ((++i <= timeout*5) && (usleep(.2 * 1000000) <= 0));
|
|
|
|
|
|
|
|
if (ret != 0) {
|
|
|
|
virReportSystemError(NULL, errno, "%s",
|
|
|
|
_("monitor socket did not show up."));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
return monfd;
|
2009-10-09 18:07:55 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
close(monfd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unable to open monitor path %s"), monitor);
|
|
|
|
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
|
|
|
|
|
|
|
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;
|
|
|
|
|
2009-11-11 10:30:01 +00:00
|
|
|
VIR_DEBUG("Process %d", (int)mon->bufferOffset);
|
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
|
|
|
len = qemuMonitorTextIOProcess(mon,
|
|
|
|
mon->buffer, mon->bufferOffset,
|
|
|
|
msg);
|
|
|
|
|
|
|
|
if (len < 0) {
|
|
|
|
mon->lastErrno = errno;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2009-11-11 10:30:01 +00:00
|
|
|
VIR_DEBUG("Process done %d used %d", (int)mon->bufferOffset, 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 (msg && msg->finished)
|
|
|
|
virCondBroadcast(&mon->notify);
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (!mon->hasSendFD) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
|
|
|
|
|
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);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Called when the monitor is able to write data */
|
|
|
|
static int
|
|
|
|
qemuMonitorIOWrite(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
int done;
|
|
|
|
|
|
|
|
/* If no active message, or fully transmitted, the no-op */
|
|
|
|
if (!mon->msg || mon->msg->txOffset == mon->msg->txLength)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (mon->msg->txFD == -1)
|
|
|
|
done = write(mon->fd,
|
|
|
|
mon->msg->txBuffer + mon->msg->txOffset,
|
|
|
|
mon->msg->txLength - mon->msg->txOffset);
|
|
|
|
else
|
|
|
|
done = qemuMonitorIOWriteWithFD(mon,
|
|
|
|
mon->msg->txBuffer + mon->msg->txOffset,
|
|
|
|
mon->msg->txLength - mon->msg->txOffset,
|
|
|
|
mon->msg->txFD);
|
|
|
|
|
|
|
|
if (done < 0) {
|
|
|
|
if (errno == EAGAIN)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
mon->lastErrno = errno;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
mon->msg->txOffset += done;
|
|
|
|
return done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called when the monitor has incoming data to read
|
|
|
|
*
|
|
|
|
* 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) {
|
|
|
|
if (VIR_REALLOC_N(mon->buffer,
|
|
|
|
mon->bufferLength + 1024) < 0) {
|
|
|
|
errno = ENOMEM;
|
|
|
|
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;
|
|
|
|
mon->lastErrno = errno;
|
|
|
|
ret = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (got == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ret += got;
|
|
|
|
avail -= got;
|
|
|
|
mon->bufferOffset += got;
|
|
|
|
mon->buffer[mon->bufferOffset] = '\0';
|
|
|
|
}
|
|
|
|
|
2009-11-11 10:30:01 +00:00
|
|
|
VIR_DEBUG("Now read %d bytes of data", (int)mon->bufferOffset);
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void qemuMonitorUpdateWatch(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
int events =
|
|
|
|
VIR_EVENT_HANDLE_HANGUP |
|
|
|
|
VIR_EVENT_HANDLE_ERROR;
|
|
|
|
|
|
|
|
if (!mon->lastErrno) {
|
|
|
|
events |= VIR_EVENT_HANDLE_READABLE;
|
|
|
|
|
|
|
|
if (mon->msg && mon->msg->txOffset < mon->msg->txLength)
|
|
|
|
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
|
|
|
|
qemuMonitorIO(int watch, int fd, int events, void *opaque) {
|
|
|
|
qemuMonitorPtr mon = opaque;
|
|
|
|
int quit = 0, failed = 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
|
|
|
qemuMonitorLock(mon);
|
|
|
|
VIR_DEBUG("Monitor %p I/O on watch %d fd %d events %d", mon, watch, fd, events);
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
if (mon->fd != fd || mon->watch != watch) {
|
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_ERROR("event from unexpected fd %d!=%d / watch %d!=%d", mon->fd, fd, mon->watch, watch);
|
2009-10-09 19:13:29 +00:00
|
|
|
failed = 1;
|
|
|
|
} else {
|
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->lastErrno &&
|
|
|
|
events & VIR_EVENT_HANDLE_WRITABLE) {
|
|
|
|
int done = qemuMonitorIOWrite(mon);
|
|
|
|
if (done < 0)
|
|
|
|
failed = 1;
|
|
|
|
events &= ~VIR_EVENT_HANDLE_WRITABLE;
|
|
|
|
}
|
|
|
|
if (!mon->lastErrno &&
|
|
|
|
events & VIR_EVENT_HANDLE_READABLE) {
|
|
|
|
int got = qemuMonitorIORead(mon);
|
|
|
|
if (got < 0)
|
|
|
|
failed = 1;
|
|
|
|
/* Ignore hangup/error events if we read some data, to
|
|
|
|
* give time for that data to be consumed */
|
|
|
|
if (got > 0) {
|
|
|
|
events = 0;
|
|
|
|
|
|
|
|
if (qemuMonitorIOProcess(mon) < 0)
|
|
|
|
failed = 1;
|
|
|
|
} else
|
|
|
|
events &= ~VIR_EVENT_HANDLE_READABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If IO process resulted in an error & we have a message,
|
|
|
|
* then wakeup that waiter */
|
|
|
|
if (mon->lastErrno && mon->msg && !mon->msg->finished) {
|
|
|
|
mon->msg->lastErrno = mon->lastErrno;
|
|
|
|
mon->msg->finished = 1;
|
|
|
|
virCondSignal(&mon->notify);
|
|
|
|
}
|
|
|
|
|
|
|
|
qemuMonitorUpdateWatch(mon);
|
|
|
|
|
|
|
|
if (events & VIR_EVENT_HANDLE_HANGUP) {
|
|
|
|
/* If IO process resulted in EOF & we have a message,
|
|
|
|
* then wakeup that waiter */
|
|
|
|
if (mon->msg && !mon->msg->finished) {
|
|
|
|
mon->msg->finished = 1;
|
|
|
|
mon->msg->lastErrno = EIO;
|
|
|
|
virCondSignal(&mon->notify);
|
|
|
|
}
|
2009-10-09 19:13:29 +00:00
|
|
|
quit = 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
|
|
|
} else if (events) {
|
2009-10-09 19:13:29 +00:00
|
|
|
VIR_ERROR(_("unhandled fd event %d for monitor fd %d"),
|
|
|
|
events, mon->fd);
|
|
|
|
failed = 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
|
|
|
/* 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 */
|
|
|
|
if (failed || quit) {
|
|
|
|
/* Make sure anyone waiting wakes up now */
|
|
|
|
virCondSignal(&mon->notify);
|
|
|
|
mon->eofcb = 1;
|
|
|
|
qemuMonitorUnlock(mon);
|
|
|
|
VIR_DEBUG("Triggering EOF callback error? %d", failed);
|
|
|
|
mon->eofCB(mon, mon->vm, failed);
|
|
|
|
|
|
|
|
qemuMonitorLock(mon);
|
|
|
|
if (mon->closed) {
|
|
|
|
qemuMonitorUnlock(mon);
|
|
|
|
VIR_DEBUG("Delayed free of monitor %p", mon);
|
|
|
|
qemuMonitorFree(mon, 1);
|
|
|
|
} else {
|
|
|
|
qemuMonitorUnlock(mon);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
qemuMonitorUnlock(mon);
|
|
|
|
}
|
2009-10-09 19:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
qemuMonitorPtr
|
2009-10-09 18:07:55 +00:00
|
|
|
qemuMonitorOpen(virDomainObjPtr vm,
|
2009-10-09 19:13:29 +00:00
|
|
|
qemuMonitorEOFNotify eofCB)
|
2009-10-09 18:07:55 +00:00
|
|
|
{
|
2009-10-09 19:13:29 +00:00
|
|
|
qemuMonitorPtr mon;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(mon) < 0) {
|
|
|
|
virReportOOMError(NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-10-13 14:27:58 +00:00
|
|
|
if (virMutexInit(&mon->lock) < 0) {
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("cannot initialize monitor mutex"));
|
|
|
|
VIR_FREE(mon);
|
|
|
|
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) {
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("cannot initialize monitor condition"));
|
|
|
|
virMutexDestroy(&mon->lock);
|
|
|
|
VIR_FREE(mon);
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-10-09 19:13:29 +00:00
|
|
|
mon->fd = -1;
|
|
|
|
mon->vm = vm;
|
|
|
|
mon->eofCB = eofCB;
|
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
|
|
|
qemuMonitorLock(mon);
|
2009-10-09 19:13:29 +00:00
|
|
|
|
2009-10-09 18:07:55 +00:00
|
|
|
switch (vm->monitor_chr->type) {
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
2009-10-09 19:13:29 +00:00
|
|
|
mon->hasSendFD = 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->fd = qemuMonitorOpenUnix(vm->monitor_chr->data.nix.path);
|
2009-10-09 19:13:29 +00:00
|
|
|
break;
|
|
|
|
|
2009-10-09 18:07:55 +00:00
|
|
|
case VIR_DOMAIN_CHR_TYPE_PTY:
|
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->fd = qemuMonitorOpenPty(vm->monitor_chr->data.file.path);
|
2009-10-09 19:13:29 +00:00
|
|
|
break;
|
|
|
|
|
2009-10-09 18:07:55 +00:00
|
|
|
default:
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unable to handle monitor type: %s"),
|
|
|
|
virDomainChrTypeToString(vm->monitor_chr->type));
|
2009-10-09 19:13:29 +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
|
|
|
if (virSetCloseExec(mon->fd) < 0) {
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("Unable to set monitor close-on-exec flag"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virSetNonBlock(mon->fd) < 0) {
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("Unable to put monitor into non-blocking mode"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
if ((mon->watch = virEventAddHandle(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
|
|
|
VIR_EVENT_HANDLE_HANGUP |
|
|
|
|
VIR_EVENT_HANDLE_ERROR |
|
|
|
|
VIR_EVENT_HANDLE_READABLE,
|
2009-10-09 19:13:29 +00:00
|
|
|
qemuMonitorIO,
|
|
|
|
mon, NULL)) < 0) {
|
|
|
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("unable to register monitor events"));
|
|
|
|
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
|
|
|
virDomainObjRef(vm);
|
|
|
|
|
|
|
|
VIR_DEBUG("New mon %p fd =%d watch=%d", mon, mon->fd, mon->watch);
|
|
|
|
qemuMonitorUnlock(mon);
|
2009-10-09 19:34:24 +00:00
|
|
|
|
2009-10-09 19:13:29 +00:00
|
|
|
return mon;
|
|
|
|
|
|
|
|
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
|
|
|
qemuMonitorUnlock(mon);
|
2009-10-09 19:13:29 +00:00
|
|
|
qemuMonitorClose(mon);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void qemuMonitorClose(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
if (!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
|
|
|
qemuMonitorLock(mon);
|
|
|
|
if (!mon->closed) {
|
|
|
|
if (mon->watch)
|
|
|
|
virEventRemoveHandle(mon->watch);
|
|
|
|
if (mon->fd != -1)
|
|
|
|
close(mon->fd);
|
|
|
|
/* NB: don't reset fd / watch fields, since active
|
|
|
|
* callback may still want them */
|
|
|
|
mon->closed = 1;
|
|
|
|
}
|
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 (mon->eofcb) {
|
|
|
|
VIR_DEBUG("Mark monitor to be deleted %p", mon);
|
|
|
|
qemuMonitorUnlock(mon);
|
|
|
|
} else {
|
|
|
|
VIR_DEBUG("Delete monitor now %p", mon);
|
|
|
|
qemuMonitorFree(mon, 0);
|
|
|
|
}
|
2009-10-09 19:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-09 19:34:24 +00:00
|
|
|
void qemuMonitorRegisterDiskSecretLookup(qemuMonitorPtr mon,
|
|
|
|
qemuMonitorDiskSecretLookup secretCB)
|
|
|
|
{
|
|
|
|
mon->secretCB = secretCB;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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 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
|
|
|
|
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->eofcb) {
|
|
|
|
msg->lastErrno = EIO;
|
|
|
|
qemuMonitorUnlock(mon);
|
2009-10-09 18:07:55 +00:00
|
|
|
return -1;
|
|
|
|
}
|
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
|
|
|
mon->msg = msg;
|
|
|
|
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
|
|
|
while (!mon->msg->finished) {
|
|
|
|
if (virCondWait(&mon->notify, &mon->lock) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
}
|
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 (mon->lastErrno == 0)
|
|
|
|
ret = 0;
|
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
|
|
|
cleanup:
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorGetDiskSecret(qemuMonitorPtr mon,
|
|
|
|
virConnectPtr conn,
|
|
|
|
const char *path,
|
|
|
|
char **secret,
|
|
|
|
size_t *secretLen)
|
|
|
|
{
|
|
|
|
*secret = NULL;
|
|
|
|
*secretLen = 0;
|
|
|
|
|
|
|
|
return mon->secretCB(mon, conn, mon->vm, path, secret, secretLen);
|
|
|
|
}
|
2009-10-09 20:13:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorStartCPUs(qemuMonitorPtr mon,
|
|
|
|
virConnectPtr conn)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d", mon, mon->fd);
|
|
|
|
|
|
|
|
return qemuMonitorTextStartCPUs(mon, conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
qemuMonitorStopCPUs(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d", mon, mon->fd);
|
|
|
|
|
|
|
|
return qemuMonitorTextStopCPUs(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorSystemPowerdown(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d", mon, mon->fd);
|
|
|
|
|
|
|
|
return qemuMonitorTextSystemPowerdown(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
|
|
|
|
int **pids)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d", mon, mon->fd);
|
|
|
|
|
|
|
|
return qemuMonitorTextGetCPUInfo(mon, pids);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qemuMonitorGetBalloonInfo(qemuMonitorPtr mon,
|
|
|
|
unsigned long *currmem)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d", mon, mon->fd);
|
|
|
|
|
|
|
|
return qemuMonitorTextGetBalloonInfo(mon, currmem);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
|
const char *devname,
|
|
|
|
long long *rd_req,
|
|
|
|
long long *rd_bytes,
|
|
|
|
long long *wr_req,
|
|
|
|
long long *wr_bytes,
|
|
|
|
long long *errs)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d dev=%s", mon, mon->fd, devname);
|
|
|
|
|
|
|
|
return qemuMonitorTextGetBlockStatsInfo(mon, devname,
|
|
|
|
rd_req, rd_bytes,
|
|
|
|
wr_req, wr_bytes,
|
|
|
|
errs);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorSetVNCPassword(qemuMonitorPtr mon,
|
|
|
|
const char *password)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d", mon, mon->fd);
|
|
|
|
|
|
|
|
return qemuMonitorTextSetVNCPassword(mon, password);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorSetBalloon(qemuMonitorPtr mon,
|
|
|
|
unsigned long newmem)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d newmem=%lu", mon, mon->fd, newmem);
|
|
|
|
|
|
|
|
return qemuMonitorTextSetBalloon(mon, newmem);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qemuMonitorEjectMedia(qemuMonitorPtr mon,
|
|
|
|
const char *devname)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d devname=%s", mon, mon->fd, devname);
|
|
|
|
|
|
|
|
return qemuMonitorTextEjectMedia(mon, devname);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorChangeMedia(qemuMonitorPtr mon,
|
|
|
|
const char *devname,
|
|
|
|
const char *newmedia)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d devname=%s newmedia=%s",
|
|
|
|
mon, mon->fd, devname, newmedia);
|
|
|
|
|
|
|
|
return qemuMonitorTextChangeMedia(mon, devname, newmedia);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorSaveVirtualMemory(qemuMonitorPtr mon,
|
|
|
|
unsigned long long offset,
|
|
|
|
size_t length,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d offset=%llu length=%zu path=%s",
|
|
|
|
mon, mon->fd, offset, length, path);
|
|
|
|
|
|
|
|
return qemuMonitorTextSaveVirtualMemory(mon, offset, length, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qemuMonitorSavePhysicalMemory(qemuMonitorPtr mon,
|
|
|
|
unsigned long long offset,
|
|
|
|
size_t length,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d offset=%llu length=%zu path=%s",
|
|
|
|
mon, mon->fd, offset, length, path);
|
|
|
|
|
|
|
|
return qemuMonitorTextSavePhysicalMemory(mon, offset, length, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorSetMigrationSpeed(qemuMonitorPtr mon,
|
|
|
|
unsigned long bandwidth)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d bandwidth=%lu", mon, mon->fd, bandwidth);
|
|
|
|
|
|
|
|
return qemuMonitorTextSetMigrationSpeed(mon, bandwidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
|
|
|
|
int *status,
|
|
|
|
unsigned long long *transferred,
|
|
|
|
unsigned long long *remaining,
|
|
|
|
unsigned long long *total)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d", mon, mon->fd);
|
|
|
|
|
|
|
|
return qemuMonitorTextGetMigrationStatus(mon, status,
|
|
|
|
transferred,
|
|
|
|
remaining,
|
|
|
|
total);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorMigrateToHost(qemuMonitorPtr mon,
|
|
|
|
int background,
|
|
|
|
const char *hostname,
|
|
|
|
int port)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d hostname=%s port=%d",
|
|
|
|
mon, mon->fd, hostname, port);
|
|
|
|
|
|
|
|
return qemuMonitorTextMigrateToHost(mon, background, hostname, port);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorMigrateToCommand(qemuMonitorPtr mon,
|
|
|
|
int background,
|
|
|
|
const char * const *argv,
|
|
|
|
const char *target)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d argv=%p target=%s",
|
|
|
|
mon, mon->fd, argv, target);
|
|
|
|
|
|
|
|
return qemuMonitorTextMigrateToCommand(mon, background, argv, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qemuMonitorMigrateToUnix(qemuMonitorPtr mon,
|
|
|
|
int background,
|
|
|
|
const char *unixfile)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p fd=%d unixfile=%s",
|
|
|
|
mon, mon->fd, unixfile);
|
|
|
|
|
|
|
|
return qemuMonitorTextMigrateToUnix(mon, background, unixfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qemuMonitorMigrateCancel(qemuMonitorPtr mon)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p fd=%d", mon, mon->fd);
|
|
|
|
|
|
|
|
return qemuMonitorTextMigrateCancel(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qemuMonitorAddUSBDisk(qemuMonitorPtr mon,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d path=%s", mon, mon->fd, path);
|
|
|
|
|
|
|
|
return qemuMonitorTextAddUSBDisk(mon, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorAddUSBDeviceExact(qemuMonitorPtr mon,
|
|
|
|
int bus,
|
|
|
|
int dev)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d bus=%d dev=%d", mon, mon->fd, bus, dev);
|
|
|
|
|
|
|
|
return qemuMonitorTextAddUSBDeviceExact(mon, bus, dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
int qemuMonitorAddUSBDeviceMatch(qemuMonitorPtr mon,
|
|
|
|
int vendor,
|
|
|
|
int product)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d vendor=%d product=%d",
|
|
|
|
mon, mon->fd, vendor, product);
|
|
|
|
|
|
|
|
return qemuMonitorTextAddUSBDeviceMatch(mon, vendor, product);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorAddPCIHostDevice(qemuMonitorPtr mon,
|
|
|
|
unsigned hostDomain,
|
|
|
|
unsigned hostBus,
|
|
|
|
unsigned hostSlot,
|
|
|
|
unsigned hostFunction,
|
|
|
|
unsigned *guestDomain,
|
|
|
|
unsigned *guestBus,
|
|
|
|
unsigned *guestSlot)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d domain=%d bus=%d slot=%d function=%d",
|
|
|
|
mon, mon->fd,
|
|
|
|
hostDomain, hostBus, hostSlot, hostFunction);
|
|
|
|
|
|
|
|
return qemuMonitorTextAddPCIHostDevice(mon, hostDomain,
|
|
|
|
hostBus, hostSlot,
|
|
|
|
hostFunction,
|
|
|
|
guestDomain,
|
|
|
|
guestBus,
|
|
|
|
guestSlot);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorAddPCIDisk(qemuMonitorPtr mon,
|
|
|
|
const char *path,
|
|
|
|
const char *bus,
|
|
|
|
unsigned *guestDomain,
|
|
|
|
unsigned *guestBus,
|
|
|
|
unsigned *guestSlot)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d path=%s bus=%s",
|
|
|
|
mon, mon->fd, path, bus);
|
|
|
|
|
|
|
|
return qemuMonitorTextAddPCIDisk(mon, path, bus,
|
|
|
|
guestDomain, guestBus, guestSlot);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorAddPCINetwork(qemuMonitorPtr mon,
|
|
|
|
const char *nicstr,
|
|
|
|
unsigned *guestDomain,
|
|
|
|
unsigned *guestBus,
|
|
|
|
unsigned *guestSlot)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d nicstr=%s", mon, mon->fd, nicstr);
|
|
|
|
|
|
|
|
return qemuMonitorTextAddPCINetwork(mon, nicstr, guestDomain,
|
|
|
|
guestBus, guestSlot);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorRemovePCIDevice(qemuMonitorPtr mon,
|
|
|
|
unsigned guestDomain,
|
|
|
|
unsigned guestBus,
|
|
|
|
unsigned guestSlot)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d domain=%d bus=%d slot=%d",
|
|
|
|
mon, mon->fd, guestDomain, guestBus, guestSlot);
|
|
|
|
|
|
|
|
return qemuMonitorTextRemovePCIDevice(mon, guestDomain,
|
|
|
|
guestBus, guestSlot);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorSendFileHandle(qemuMonitorPtr mon,
|
|
|
|
const char *fdname,
|
|
|
|
int fd)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d fdname=%s fd=%d",
|
|
|
|
mon, mon->fd, fdname, fd);
|
|
|
|
|
|
|
|
return qemuMonitorTextSendFileHandle(mon, fdname, fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorCloseFileHandle(qemuMonitorPtr mon,
|
|
|
|
const char *fdname)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d fdname=%s",
|
|
|
|
mon, mon->fd, fdname);
|
|
|
|
|
|
|
|
return qemuMonitorTextCloseFileHandle(mon, fdname);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorAddHostNetwork(qemuMonitorPtr mon,
|
|
|
|
const char *netstr)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d netstr=%s",
|
|
|
|
mon, mon->fd, netstr);
|
|
|
|
|
|
|
|
return qemuMonitorTextAddHostNetwork(mon, netstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int qemuMonitorRemoveHostNetwork(qemuMonitorPtr mon,
|
|
|
|
int vlan,
|
|
|
|
const char *netname)
|
|
|
|
{
|
|
|
|
DEBUG("mon=%p, fd=%d netname=%s",
|
|
|
|
mon, mon->fd, netname);
|
|
|
|
|
|
|
|
return qemuMonitorTextRemoveHostNetwork(mon, vlan, netname);
|
|
|
|
}
|