[libvirt] [PATCH] qemu: Fix shutdown regression
by Jiri Denemark
The commit that prevents disk corruption on domain shutdown
(96fc4784177ecb70357518fa863442455e45ad0e) causes regression with QEMU
0.14.* and 0.15.* because of a regression bug in QEMU that was fixed
only recently in QEMU git. With affected QEMU binaries, domains cannot
be shutdown properly and stay in a paused state. This patch tries to
avoid this by sending SIGKILL to 0.1[45].* QEMU processes. Though we
wait a bit more between sending SIGTERM and SIGKILL to reduce the
possibility of virtual disk corruption.
---
src/qemu/qemu_capabilities.c | 7 +++++++
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_process.c | 19 +++++++++++++------
3 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 36f47a9..823c500 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -136,6 +136,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"pci-ohci",
"usb-redir",
"usb-hub",
+ "no-shutdown-bug",
);
struct qemu_feature_flags {
@@ -1049,6 +1050,12 @@ qemuCapsComputeCmdFlags(const char *help,
if (version >= 13000)
qemuCapsSet(flags, QEMU_CAPS_PCI_MULTIFUNCTION);
+
+ /* QEMU version 0.14.* and 0.15.* are known not to handle SIGTERM
+ * properly when started with -no-shutdown
+ */
+ if (version >= 14000 && version <= 15999)
+ qemuCapsSet(flags, QEMU_CAPS_NO_SHUTDOWN_BUG);
}
/* We parse the output of 'qemu -help' to get the QEMU
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 96b7a3b..53d5ace 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -110,6 +110,7 @@ enum qemuCapsFlags {
QEMU_CAPS_PCI_OHCI = 71, /* -device pci-ohci */
QEMU_CAPS_USB_REDIR = 72, /* -device usb-redir */
QEMU_CAPS_USB_HUB = 73, /* -device usb-hub */
+ QEMU_CAPS_NO_SHUTDOWN_BUG = 74, /* -no-shutdown doesn't exit on SIGTERM */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 3baaa19..3311699 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -434,6 +434,7 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
virDomainObjPtr vm)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
+ bool gracefully = true;
VIR_DEBUG("vm=%p", vm);
virDomainObjLock(vm);
@@ -443,6 +444,12 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
goto cleanup;
}
+ if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_NO_SHUTDOWN_BUG)) {
+ VIR_DEBUG("Emulator is likely affected by -no-shutdown bug;"
+ " we will not avoid sending SIGKILL to it");
+ gracefully = false;
+ }
+
priv->gotShutdown = true;
if (priv->fakeReboot) {
virDomainObjRef(vm);
@@ -452,12 +459,12 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
qemuProcessFakeReboot,
vm) < 0) {
VIR_ERROR(_("Failed to create reboot thread, killing domain"));
- qemuProcessKill(vm, true);
+ qemuProcessKill(vm, gracefully);
if (virDomainObjUnref(vm) == 0)
vm = NULL;
}
} else {
- qemuProcessKill(vm, true);
+ qemuProcessKill(vm, gracefully);
}
cleanup:
@@ -3227,15 +3234,15 @@ void qemuProcessKill(virDomainObjPtr vm, bool gracefully)
}
/* This loop sends SIGTERM, then waits a few iterations
- * (1.6 seconds) to see if it dies. If still alive then
+ * (3 seconds) to see if it dies. If still alive then
* it does SIGKILL, and waits a few more iterations (1.6
* seconds more) to confirm that it has really gone.
*/
- for (i = 0 ; i < 15 ; i++) {
+ for (i = 0 ; i < 23 ; i++) {
int signum;
if (i == 0)
signum = SIGTERM;
- else if (i == 8)
+ else if (i == 15)
signum = SIGKILL;
else
signum = 0; /* Just check for existence */
@@ -3249,7 +3256,7 @@ void qemuProcessKill(virDomainObjPtr vm, bool gracefully)
break;
}
- if (i == 0 && gracefully)
+ if (gracefully)
break;
usleep(200 * 1000);
--
1.7.6.1
13 years, 2 months
[libvirt] [PATCH] daemon: Modify init script to check for libvirtd managed with upstart
by Peter Krempa
On some systems init scripts are installed along with upstart . This may
cause trouble if user tries to restart/stop a instance of libvirtd
managed with upstart with init script.
This patch adds check for a started libvirtd managed by upstart and
fails the init script.
[root@localhost ~]# initctl status libvirtd
libvirtd start/running, process 3001
[root@localhost ~]# service libvirtd restart
Stopping libvirtd daemon: error: libvirtd is managed by upstart and
started, use initctl instead
If libvirtd is not managed by upstart or is stopped, init script works
normaly and allows the user to manage the service.
https://bugzilla.redhat.com/show_bug.cgi?id=728153
---
daemon/libvirtd.init.in | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/daemon/libvirtd.init.in b/daemon/libvirtd.init.in
index 0697a2b..823fa77 100644
--- a/daemon/libvirtd.init.in
+++ b/daemon/libvirtd.init.in
@@ -43,6 +43,8 @@ LIBVIRTD_CONFIG=
LIBVIRTD_ARGS=
KRB5_KTNAME=/etc/libvirt/krb5.tab
+INITCTL_PATH=/sbin/initctl
+
test -f @sysconfdir@/sysconfig/libvirtd && . @sysconfdir@/sysconfig/libvirtd
export QEMU_AUDIO_DRV
@@ -56,8 +58,22 @@ fi
RETVAL=0
+# Check if libvirt is managed by upstart and fail if it's the case
+initctl_check() {
+ if [ -x $INITCTL_PATH ]; then
+ #extract status from upstart
+ LIBVIRTD_UPSTART_STATUS=`$INITCTL_PATH status libvirtd | tr "/" " " | cut -d " " -f 2`
+ if [ $LIBVIRTD_UPSTART_STATUS = "start" ]; then
+ echo "error: libvirtd is managed by upstart and started, use initctl instead"
+ exit 1
+ fi
+ fi
+}
+
start() {
echo -n $"Starting $SERVICE daemon: "
+ initctl_check
+
mkdir -p @localstatedir@/cache/libvirt
rm -rf @localstatedir@/cache/libvirt/*
KRB5_KTNAME=$KRB5_KTNAME daemon --pidfile $PIDFILE --check $SERVICE $PROCESS --daemon $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS
@@ -68,6 +84,7 @@ start() {
stop() {
echo -n $"Stopping $SERVICE daemon: "
+ initctl_check
killproc -p $PIDFILE $PROCESS
RETVAL=$?
@@ -88,6 +105,7 @@ restart() {
reload() {
echo -n $"Reloading $SERVICE configuration: "
+ initctl_check
killproc -p $PIDFILE $PROCESS -HUP
RETVAL=$?
--
1.7.3.4
13 years, 2 months
[libvirt] [PATCH] Revert "Ensure async packets never get marked for sync replies"
by Michal Privoznik
This partially reverts commit 984840a2c292402926ad100aeea33f8859ff31a9.
Without this patch, client don't finish a stream which makes any
API involving virStream block indefinitely.
---
src/rpc/virnetclient.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
index 055361d..50f46ea 100644
--- a/src/rpc/virnetclient.c
+++ b/src/rpc/virnetclient.c
@@ -627,6 +627,11 @@ static int virNetClientCallDispatchStream(virNetClientPtr client)
case VIR_NET_CONTINUE: {
if (virNetClientStreamQueuePacket(st, &client->msg) < 0)
return -1;
+
+ if (thecall && thecall->expectReply) {
+ VIR_DEBUG("Got sync data packet completion");
+ thecall->mode = VIR_NET_CLIENT_MODE_COMPLETE;
+ }
return 0;
}
--
1.7.3.4
13 years, 2 months
[libvirt] [RFC v1] API to invoke S3/S4 on a KVM host and also resume from within libvirt
by Srivatsa S. Bhat
This patch adds a new API to put a KVM host to a suspended state
(either Suspend-to-RAM or Suspend-to-Disk) and also resume the host
back from within libvirt. This uses the RTC wakeup mechanism to set
up a timer alarm before suspending the host, so that in-band resume
is facilitated since the firing of the RTC alarm wakes up the host.
The decision to use the RTC Wakeup mechanism to resume the host from
sleep was taken in [1]. An initial API was discussed in [2].
Some design ideas for the asynchronous mechanism implementation was
discussed in [3].
Todo:
1. During libvirtd init time check if S3/S4 is supported by the host.
2. Add synchronization/locking to ensure that only one suspend operation
is active at a time.
References:
[1]. http://www.redhat.com/archives/libvir-list/2011-August/msg00327.html
[2]. http://www.redhat.com/archives/libvir-list/2011-August/msg00248.html
[3]. http://www.redhat.com/archives/libvir-list/2011-September/msg00438.html
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat(a)linux.vnet.ibm.com>
---
include/libvirt/libvirt.h.in | 9 +++
src/driver.h | 5 ++
src/libvirt.c | 45 ++++++++++++++
src/libvirt_private.syms | 4 +
src/libvirt_public.syms | 1
src/nodeinfo.c | 139 ++++++++++++++++++++++++++++++++++++++++++
src/nodeinfo.h | 10 +++
src/qemu/qemu_driver.c | 1
src/remote/remote_driver.c | 1
src/remote/remote_protocol.x | 12 +++-
10 files changed, 224 insertions(+), 3 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 39155a6..aca55e6 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -988,6 +988,10 @@ unsigned long long virNodeGetFreeMemory (virConnectPtr conn);
int virNodeGetSecurityModel (virConnectPtr conn,
virSecurityModelPtr secmodel);
+int virNodeSuspendForDuration (virConnectPtr conn,
+ int state,
+ unsigned long long duration);
+
/*
* Gather list of running domains
*/
@@ -3210,6 +3214,11 @@ typedef struct _virTypedParameter virMemoryParameter;
*/
typedef virMemoryParameter *virMemoryParameterPtr;
+typedef enum {
+ VIR_S3, /* Suspend-to-RAM */
+ VIR_S4 /* Suspend-to-disk */
+} virSuspendState;
+
#ifdef __cplusplus
}
#endif
diff --git a/src/driver.h b/src/driver.h
index 3792003..658af5f 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -718,6 +718,10 @@ typedef int
(*virDrvDomainBlockPull)(virDomainPtr dom, const char *path,
unsigned long bandwidth, unsigned int flags);
+typedef int
+ (*virDrvNodeSuspendForDuration)(virConnectPtr conn, int state,
+ unsigned long long duration);
+
/**
* _virDriver:
@@ -872,6 +876,7 @@ struct _virDriver {
virDrvDomainGetBlockJobInfo domainGetBlockJobInfo;
virDrvDomainBlockJobSetSpeed domainBlockJobSetSpeed;
virDrvDomainBlockPull domainBlockPull;
+ virDrvNodeSuspendForDuration nodeSuspendForDuration;
};
typedef int
diff --git a/src/libvirt.c b/src/libvirt.c
index 05c0a87..688c982 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -6103,6 +6103,51 @@ error:
}
/**
+ * virNodeSuspendForDuration:
+ * @conn: pointer to the hypervisor connection
+ * @state: the state to which the host must be suspended to
+ * @duration: the time duration in seconds, for which the host
+ * has to be suspended
+ *
+ * Suspend the node (host machine) for the given duration of time
+ * in the specified state (such as S3 or S4). Resume the node
+ * after the time duration is complete.
+ *
+ * Returns 0 on success (i.e., the node will be suspended after a
+ * short delay), -1 on failure (the operation is not supported).
+ */
+int
+virNodeSuspendForDuration(virConnectPtr conn,
+ int state,
+ unsigned long long duration)
+{
+ VIR_DEBUG("conn=%p, state=%d, duration=%lld", conn, state, duration);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECT(conn)) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ if (conn->driver->nodeSuspendForDuration) {
+ int ret;
+ ret = conn->driver->nodeSuspendForDuration(conn, state, duration);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(conn);
+ return -1;
+}
+
+
+/**
* virDomainGetSchedulerType:
* @domain: pointer to domain object
* @nparams: pointer to number of scheduler parameters, can be NULL
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4f33567..3d2870a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -828,7 +828,9 @@ nodeGetCellsFreeMemory;
nodeGetFreeMemory;
nodeGetInfo;
nodeGetMemoryStats;
-
+nodeSuspendForDuration;
+setNodeWakeup;
+nodeSuspend;
# nwfilter_conf.h
virNWFilterCallbackDriversLock;
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 8a6d55a..14466f9 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -478,6 +478,7 @@ LIBVIRT_0.9.4 {
virDomainGetBlockJobInfo;
virDomainBlockJobSetSpeed;
virDomainBlockPull;
+ virNodeSuspendForDuration;
} LIBVIRT_0.9.3;
LIBVIRT_0.9.5 {
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 6448b79..34e9ff8 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -46,7 +46,8 @@
#include "count-one-bits.h"
#include "intprops.h"
#include "virfile.h"
-
+#include "command.h"
+#include "threads.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -897,3 +898,139 @@ unsigned long long nodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED)
return 0;
}
#endif
+
+
+static bool aboutToSuspend = false;
+
+/**
+ * nodeSuspendForDuration:
+ * @conn: pointer to the hypervisor connection
+ * @state: the state to which the host must be suspended to -
+ * VIR_HOST_PM_S3 (Suspend-to-RAM)
+ * or VIR_HOST_PM_S4 (Suspend-to-disk)
+ * @duration: the time duration in seconds, for which the host
+ * must be suspended
+ *
+ * Suspend the node (host machine) for the given duration of time
+ * in the specified state (such as S3 or S4). Resume the node
+ * after the time duration is complete.
+ *
+ * An RTC alarm is set appropriately to wake up the node from
+ * its sleep state. Then the actual node suspend is carried out
+ * asynchronously in another thread, after a short time delay
+ * so as to give enough time for this function to return status
+ * to its caller through the connection.
+ *
+ * Returns 0 in case the node is going to be suspended after a short
+ * delay, -1 if suspending the node is not supported.
+ */
+
+int nodeSuspendForDuration(virConnectPtr conn ATTRIBUTE_UNUSED,
+ int state,
+ unsigned long long duration)
+{
+ virThread thread;
+ static char * suspendCmdString;
+ int ret = -1;
+
+ /* Check if we have already started suspending
+ * and this is a duplicate request.
+ */
+ if(aboutToSuspend == true) {
+ /* This is a duplicate request to suspend.
+ * So we need not do anything.
+ */
+ return 0;
+ } else {
+ /* This is not a duplicate request to suspend. */
+ aboutToSuspend = true;
+ }
+
+ /* Just set the RTC alarm. Don't suspend yet. */
+ if(setNodeWakeup(duration) < 0) {
+ nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to set up the RTC alarm for node wakeup\n"));
+ goto cleanup;
+ }
+
+ if (state == VIR_S4) {
+ suspendCmdString = "pm-hibernate";
+ } else {
+ suspendCmdString = "pm-suspend";
+ }
+
+ if(virThreadCreate(&thread, false, nodeSuspend, suspendCmdString) < 0) {
+ nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to create thread to suspend the host\n"));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ return ret;
+}
+
+/**
+ * setNodeWakeup:
+ * @alarmTime : time in seconds from now, at which the RTC alarm has to be set.
+ *
+ * Set up the RTC alarm to the specified time.
+ * Return 0 on success, -1 on failure.
+ */
+
+int setNodeWakeup(unsigned long long alarmTime)
+{
+ virCommandPtr setAlarmCmd;
+ int ret = -1;
+
+ setAlarmCmd = virCommandNewArgList("rtcwake", "-m", "no", "-s", NULL);
+ virCommandAddArgFormat(setAlarmCmd, "%lld", alarmTime);
+
+ if (virCommandRun(setAlarmCmd, NULL) < 0) {
+ nodeReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Failed to set up the RTC alarm\n"));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ virCommandFree(setAlarmCmd);
+ return ret;
+}
+
+/**
+ * nodeSuspend:
+ * @cmdString: string containing the command to invoke
+ *
+ * Actually perform the suspend operation by invoking the
+ * command. Give a short delay before executing the command
+ * so as to give a chance to virNodeSuspendForDuration() to
+ * return the status to the caller. If we don't give this delay,
+ * that function will not be able to return the status since the
+ * suspend operation would have begun and hence no data can be
+ * sent through the connection to the caller.
+ */
+
+void nodeSuspend(void *cmdString)
+{
+ virCommandPtr suspendCmd = virCommandNew((char *)cmdString);
+
+ /* Delay for sometime so that the function nodeSuspendForDuration
+ * can return the status to the caller.
+ */
+ sleep(SUSPEND_DELAY);
+ if (virCommandRun(suspendCmd, NULL) < 0) {
+ nodeReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Failed to suspend the node\n"));
+ }
+
+ virCommandFree(suspendCmd);
+
+ /* Now that we have resumed from our sleep state, reset the flag
+ * that formerly indicated that we were about to suspend the node.
+ */
+ aboutToSuspend = false;
+}
+
diff --git a/src/nodeinfo.h b/src/nodeinfo.h
index 4766152..f0c2271 100644
--- a/src/nodeinfo.h
+++ b/src/nodeinfo.h
@@ -46,4 +46,14 @@ int nodeGetCellsFreeMemory(virConnectPtr conn,
int maxCells);
unsigned long long nodeGetFreeMemory(virConnectPtr conn);
+int nodeSuspendForDuration(virConnectPtr conn,
+ int state,
+ unsigned long long duration);
+
+int setNodeWakeup(unsigned long long alarmTime);
+
+# define SUSPEND_DELAY 10 /* in seconds */
+
+void nodeSuspend(void *cmdString);
+
#endif /* __VIR_NODEINFO_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e2f428f..c2c72d2 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10695,6 +10695,7 @@ static virDriver qemuDriver = {
.domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */
.domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */
.domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */
+ .nodeSuspendForDuration = nodeSuspendForDuration, /* 0.9.4 */
};
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 9d34b7e..02cd122 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -4429,6 +4429,7 @@ static virDriver remote_driver = {
.domainGetBlockJobInfo = remoteDomainGetBlockJobInfo, /* 0.9.4 */
.domainBlockJobSetSpeed = remoteDomainBlockJobSetSpeed, /* 0.9.4 */
.domainBlockPull = remoteDomainBlockPull, /* 0.9.4 */
+ .nodeSuspendForDuration = remoteNodeSuspendForDuration, /* 0.9.4 */
};
static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 4ec1c57..c1b1d94 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2220,6 +2220,15 @@ struct remote_domain_get_control_info_ret { /* insert@1 */
unsigned hyper stateTime;
};
+struct remote_node_suspend_for_duration_args {
+ int state;
+ unsigned hyper duration;
+};
+
+struct remote_node_suspend_for_duration_ret {
+ int status;
+};
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
@@ -2509,7 +2518,8 @@ enum remote_procedure {
REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB = 241, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_MIGRATE_GET_MAX_SPEED = 242, /* autogen autogen */
- REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS = 243 /* skipgen skipgen */
+ REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS = 243, /* skipgen skipgen */
+ REMOTE_PROC_NODE_SUSPEND_FOR_DURATION = 244 /* autogen autogen priority:high */
/*
* Notice how the entries are grouped in sets of 10 ?
13 years, 2 months
[libvirt] [PATCH 1/2] qemu: using correct function to reboot guest.
by xuhj@linux.vnet.ibm.com
From: Xu He Jie <xuhj(a)linux.vnet.ibm.com>
Signed-off-by: Xu He Jie <xuhj(a)linux.vnet.ibm.com>
---
src/qemu/qemu_driver.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f4ee4c3..b0c9c02 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1567,7 +1567,7 @@ static int qemuDomainReboot(virDomainPtr dom, unsigned int flags) {
}
qemuDomainObjEnterMonitor(driver, vm);
- ret = qemuMonitorSystemPowerdown(priv->mon);
+ ret = qemuMonitorSystemReset(priv->mon);
qemuDomainObjExitMonitor(driver, vm);
priv->fakeReboot = true;
--
1.7.4.1
13 years, 2 months
[libvirt] [PATCH] qemu: Allow domain reboot after core dump
by Michal Privoznik
This patch introduces possibility to reboot domain after core dump
finishes. The new flag VIR_DUMP_REBOOT was added to
virDomainCoreDumpFlags. The new functionality is accessible via virsh
too: virsh dump --reboot <domain>
---
include/libvirt/libvirt.h.in | 1 +
src/qemu/qemu_driver.c | 8 +++++++-
tools/virsh.c | 3 +++
3 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 39155a6..8c41f5a 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -748,6 +748,7 @@ typedef enum {
VIR_DUMP_CRASH = (1 << 0), /* crash after dump */
VIR_DUMP_LIVE = (1 << 1), /* live dump */
VIR_DUMP_BYPASS_CACHE = (1 << 2), /* avoid file system cache pollution */
+ VIR_DUMP_REBOOT = (1 << 3), /* reboot domain after dump finishes */
} virDomainCoreDumpFlags;
/* Domain migration flags. */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e2f428f..22576a8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3104,7 +3104,8 @@ static int qemudDomainCoreDump(virDomainPtr dom,
int ret = -1;
virDomainEventPtr event = NULL;
- virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH | VIR_DUMP_BYPASS_CACHE, -1);
+ virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH |
+ VIR_DUMP_BYPASS_CACHE | VIR_DUMP_REBOOT, -1);
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -3189,6 +3190,11 @@ cleanup:
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver);
+
+ if ((ret == 0) && (flags & VIR_DUMP_REBOOT)) {
+ qemuDomainReboot(dom, 0);
+ }
+
return ret;
}
diff --git a/tools/virsh.c b/tools/virsh.c
index d575425..74f6a79 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -2840,6 +2840,7 @@ static const vshCmdOptDef opts_dump[] = {
{"crash", VSH_OT_BOOL, 0, N_("crash the domain after core dump")},
{"bypass-cache", VSH_OT_BOOL, 0,
N_("avoid file system cache when saving")},
+ {"reboot", VSH_OT_BOOL, 0, N_("reboot the domain after core dump")},
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("where to dump the core")},
{NULL, 0, 0, NULL}
@@ -2869,6 +2870,8 @@ cmdDump(vshControl *ctl, const vshCmd *cmd)
flags |= VIR_DUMP_CRASH;
if (vshCommandOptBool(cmd, "bypass-cache"))
flags |= VIR_DUMP_BYPASS_CACHE;
+ if (vshCommandOptBool(cmd, "reboot"))
+ flags |= VIR_DUMP_REBOOT;
if (virDomainCoreDump(dom, to, flags) < 0) {
vshError(ctl, _("Failed to core dump domain %s to %s"), name, to);
--
1.7.3.4
13 years, 2 months
[libvirt] [PATCH] API: prefer to use NULLSTR macro
by Osier Yang
---
src/libvirt.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c
index 05c0a87..8f94b11 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -10300,7 +10300,7 @@ virConnectFindStoragePoolSources(virConnectPtr conn,
unsigned int flags)
{
VIR_DEBUG("conn=%p, type=%s, src=%s, flags=%x",
- conn, type ? type : "", srcSpec ? srcSpec : "", flags);
+ conn, NULLSTR(type), NULLSTR(srcSpec), flags);
virResetLastError();
--
1.7.6
13 years, 2 months
[libvirt] [PATCH 1/2] xen: use typical allocations
by Eric Blake
The next patch will add a syntax check that flags this usage in xen
as awkward - while it was valid memory management, it was very hard
to maintain. Swapping to a more traditional allocation may be a bit
slower, but easier to understand.
* src/xen/xend_internal.c (xenDaemonListDomainsOld): Use two-level
allocation, rather than abusing allocation function.
(xenDaemonLookupByUUID): Update caller.
---
src/xen/xend_internal.c | 42 +++++++++++++++++++-----------------------
1 files changed, 19 insertions(+), 23 deletions(-)
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 81ff325..fa39e8b 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -753,12 +753,10 @@ xend_wait_for_devices(virConnectPtr xend, const char *name)
char **
xenDaemonListDomainsOld(virConnectPtr xend)
{
- size_t extra = 0;
struct sexpr *root = NULL;
char **ret = NULL;
int count = 0;
int i;
- char *ptr;
struct sexpr *_for_i, *node;
root = sexpr_get(xend, "/xend/domain");
@@ -769,32 +767,22 @@ xenDaemonListDomainsOld(virConnectPtr xend)
_for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
if (node->kind != SEXPR_VALUE)
continue;
- extra += strlen(node->u.value) + 1;
count++;
}
- /*
- * We can'tuse the normal allocation routines as we are mixing
- * an array of char * at the beginning followed by an array of char
- * ret points to the NULL terminated array of char *
- * ptr points to the current string after that array but in the same
- * allocated block
- */
- if (virAlloc((void *)&ptr,
- (count + 1) * sizeof(char *) + extra * sizeof(char)) < 0)
+ if (VIR_ALLOC_N(ret, count + 1) < 0) {
+ virReportOOMError();
goto error;
-
- ret = (char **) ptr;
- ptr += sizeof(char *) * (count + 1);
+ }
i = 0;
for (_for_i = root, node = root->u.s.car; _for_i->kind == SEXPR_CONS;
_for_i = _for_i->u.s.cdr, node = _for_i->u.s.car) {
if (node->kind != SEXPR_VALUE)
continue;
- ret[i] = ptr;
- strcpy(ptr, node->u.value);
- ptr += strlen(node->u.value) + 1;
+ ret[i] = strdup(node->u.value);
+ if (!ret[i])
+ goto no_memory;
i++;
}
@@ -803,6 +791,12 @@ xenDaemonListDomainsOld(virConnectPtr xend)
error:
sexpr_free(root);
return ret;
+
+no_memory:
+ for (i = 0; i < count; i++)
+ VIR_FREE(ret[i]);
+ VIR_FREE(ret);
+ goto error;
}
@@ -2493,16 +2487,18 @@ xenDaemonLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
id = xenDaemonDomainLookupByName_ids(conn, *tmp, &ident[0]);
if (id >= 0) {
if (!memcmp(uuid, ident, VIR_UUID_BUFLEN)) {
- name = strdup(*tmp);
-
- if (name == NULL)
- virReportOOMError();
-
+ name = *tmp;
break;
}
}
tmp++;
}
+ tmp = names;
+ while (*tmp) {
+ if (*tmp != name)
+ VIR_FREE(*tmp);
+ tmp++;
+ }
VIR_FREE(names);
} else { /* New approach for xen >= 3.0.4 */
char *domname = NULL;
--
1.7.4.4
13 years, 2 months
[libvirt] [PATCH] storage: Inherit permissions of parent pool if they are not specified
by Osier Yang
If permissions (mode, uid, gid) are not specified, a new created vol
will get the permissions like:
mode = 0600
uid = -1
gid = -1
This will be a bit surprised if the user define the pool with a
non-root uid/gid, but the new created vol is still defined as
root/root.
This patch changes the behaviour so that the new created vol will
inherit the permissions of parent pool if permission are not
specified.
---
src/conf/storage_conf.c | 32 ++++++++++++++++++++------------
1 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index e893b2d..18675ad 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -539,6 +539,7 @@ static int
virStorageDefParsePerms(xmlXPathContextPtr ctxt,
virStoragePermsPtr perms,
const char *permxpath,
+ virStoragePermsPtr pool_perms,
int defaultmode) {
char *mode;
long v;
@@ -560,9 +561,8 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt,
ctxt->node = node;
mode = virXPathString("string(./mode)", ctxt);
- if (!mode) {
- perms->mode = defaultmode;
- } else {
+
+ if (mode) {
char *end = NULL;
perms->mode = strtol(mode, &end, 8);
if (*end || perms->mode < 0 || perms->mode > 0777) {
@@ -572,28 +572,32 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt,
goto error;
}
VIR_FREE(mode);
+ } else if (pool_perms) {
+ perms->mode = pool_perms->mode;
+ } else {
+ perms->mode = defaultmode;
}
- if (virXPathNode("./owner", ctxt) == NULL) {
- perms->uid = -1;
- } else {
+ if (virXPathNode("./owner", ctxt)) {
if (virXPathLong("number(./owner)", ctxt, &v) < 0) {
virStorageReportError(VIR_ERR_XML_ERROR,
"%s", _("malformed owner element"));
goto error;
}
perms->uid = (int)v;
+ } else if (pool_perms) {
+ perms->uid = pool_perms->uid;
}
- if (virXPathNode("./group", ctxt) == NULL) {
- perms->gid = -1;
- } else {
+ if (virXPathNode("./group", ctxt)) {
if (virXPathLong("number(./group)", ctxt, &v) < 0) {
virStorageReportError(VIR_ERR_XML_ERROR,
"%s", _("malformed group element"));
goto error;
}
perms->gid = (int)v;
+ } else if (pool_perms) {
+ perms->gid = pool_perms->gid;
}
/* NB, we're ignoring missing labels here - they'll simply inherit */
@@ -722,7 +726,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) {
if (virStorageDefParsePerms(ctxt, &ret->target.perms,
- "./target/permissions", 0700) < 0)
+ "./target/permissions", NULL, 0700) < 0)
goto cleanup;
return ret;
@@ -1069,7 +1073,9 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
}
if (virStorageDefParsePerms(ctxt, &ret->target.perms,
- "./target/permissions", 0600) < 0)
+ "./target/permissions",
+ &pool->target.perms,
+ 0600) < 0)
goto cleanup;
node = virXPathNode("./target/encryption", ctxt);
@@ -1100,7 +1106,9 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
}
if (virStorageDefParsePerms(ctxt, &ret->backingStore.perms,
- "./backingStore/permissions", 0600) < 0)
+ "./backingStore/permissions",
+ &pool->target.perms,
+ 0600) < 0)
goto cleanup;
return ret;
--
1.7.6
13 years, 2 months