From: "Daniel P. Berrange" <berrange(a)redhat.com>
Currently to deal with auto-shutdown libvirtd must periodically
poll all stateful drivers. Thus sucks because it requires
acquiring both the driver lock and locks on every single virtual
machine. Instead pass in a "inhibit" callback to virStateInitialize
which drivers can invoke whenever they want to inhibit shutdown
due to existance of active VMs.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
daemon/libvirtd.c | 30 ++++++++++++++++--------------
src/Makefile.am | 2 ++
src/driver.h | 7 ++++---
src/libvirt.c | 29 +++++++++--------------------
src/libvirt_internal.h | 8 ++++++--
src/libvirt_private.syms | 2 ++
src/libxl/libxl_conf.h | 5 +++++
src/libxl/libxl_driver.c | 26 ++++++++++++++++----------
src/lxc/lxc_conf.h | 5 +++++
src/lxc/lxc_driver.c | 29 ++++++-----------------------
src/lxc/lxc_process.c | 12 ++++++++++++
src/network/bridge_driver.c | 33 ++++-----------------------------
src/node_device/node_device_hal.c | 14 +++-----------
src/node_device/node_device_udev.c | 12 +++---------
src/nwfilter/nwfilter_driver.c | 26 +++-----------------------
src/qemu/qemu_conf.h | 4 ++++
src/qemu/qemu_driver.c | 30 ++++++------------------------
src/qemu/qemu_process.c | 16 ++++++++++++++++
src/remote/remote_driver.c | 4 +++-
src/rpc/virnetserver.c | 29 +++++++++++++++++++++--------
src/rpc/virnetserver.h | 7 ++++---
src/secret/secret_driver.c | 5 +++--
src/storage/storage_driver.c | 32 +++-----------------------------
src/uml/uml_conf.h | 3 +++
src/uml/uml_driver.c | 37 ++++++++++++++-----------------------
src/xen/xen_driver.c | 4 +++-
26 files changed, 176 insertions(+), 235 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 624831a..b1b3ef7 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -584,16 +584,6 @@ error:
}
-static int daemonShutdownCheck(virNetServerPtr srv ATTRIBUTE_UNUSED,
- void *opaque ATTRIBUTE_UNUSED)
-{
- if (virStateActive())
- return 0;
-
- return 1;
-}
-
-
/*
* Set up the logging environment
* By default if daemonized all errors go to the logfile libvirtd.log,
@@ -772,6 +762,18 @@ static int daemonSetupSignals(virNetServerPtr srv)
return 0;
}
+
+static void daemonInhibitCallback(bool inhibit, void *opaque)
+{
+ virNetServerPtr srv = opaque;
+
+ if (inhibit)
+ virNetServerAddShutdownInhibition(srv);
+ else
+ virNetServerRemoveShutdownInhibition(srv);
+}
+
+
static void daemonRunStateInit(void *opaque)
{
virNetServerPtr srv = opaque;
@@ -780,7 +782,9 @@ static void daemonRunStateInit(void *opaque)
* This is deliberately done after telling the parent process
* we're ready, since it can take a long time and this will
* seriously delay OS bootup process */
- if (virStateInitialize(virNetServerIsPrivileged(srv)) < 0) {
+ if (virStateInitialize(virNetServerIsPrivileged(srv),
+ daemonInhibitCallback,
+ srv) < 0) {
VIR_ERROR(_("Driver state initialization failed"));
/* Ensure the main event loop quits */
kill(getpid(), SIGTERM);
@@ -1269,9 +1273,7 @@ int main(int argc, char **argv) {
if (timeout != -1) {
VIR_DEBUG("Registering shutdown timeout %d", timeout);
virNetServerAutoShutdown(srv,
- timeout,
- daemonShutdownCheck,
- NULL);
+ timeout);
}
if ((daemonSetupSignals(srv)) < 0) {
diff --git a/src/Makefile.am b/src/Makefile.am
index 1f32263..9ebd6e0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1596,12 +1596,14 @@ libvirt_net_rpc_server_la_SOURCES = \
rpc/virnetserver.h rpc/virnetserver.c
libvirt_net_rpc_server_la_CFLAGS = \
$(AVAHI_CFLAGS) \
+ $(DBUS_CFLAGS) \
$(XDR_CFLAGS) \
$(AM_CFLAGS) \
$(POLKIT_CFLAGS)
libvirt_net_rpc_server_la_LDFLAGS = \
$(AM_LDFLAGS) \
$(AVAHI_LIBS) \
+ $(DBUS_LIBS) \
$(POLKIT_LIBS) \
$(CYGWIN_EXTRA_LDFLAGS) \
$(MINGW_EXTRA_LDFLAGS)
diff --git a/src/driver.h b/src/driver.h
index 622ed87..632f80e 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -1487,10 +1487,12 @@ struct _virStorageDriver {
};
# ifdef WITH_LIBVIRTD
-typedef int (*virDrvStateInitialize) (bool privileged);
+
+typedef int (*virDrvStateInitialize) (bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque);
typedef int (*virDrvStateCleanup) (void);
typedef int (*virDrvStateReload) (void);
-typedef int (*virDrvStateActive) (void);
typedef int (*virDrvStateStop) (void);
typedef struct _virStateDriver virStateDriver;
@@ -1501,7 +1503,6 @@ struct _virStateDriver {
virDrvStateInitialize initialize;
virDrvStateCleanup cleanup;
virDrvStateReload reload;
- virDrvStateActive active;
virDrvStateStop stop;
};
# endif
diff --git a/src/libvirt.c b/src/libvirt.c
index 0847f5f..a2f1296 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -790,12 +790,17 @@ virRegisterStateDriver(virStateDriverPtr driver)
/**
* virStateInitialize:
* @privileged: set to true if running with root privilege, false otherwise
+ * @callback: callback to invoke to inhibit shutdown of the daemon
+ * @opaque: data to pass to @callback
*
* Initialize all virtualization drivers.
*
* Returns 0 if all succeed, -1 upon any failure.
*/
-int virStateInitialize(bool privileged) {
+int virStateInitialize(bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque)
+{
int i;
if (virInitialize() < 0)
@@ -805,7 +810,9 @@ int virStateInitialize(bool privileged) {
if (virStateDriverTab[i]->initialize) {
VIR_DEBUG("Running global init for %s state driver",
virStateDriverTab[i]->name);
- if (virStateDriverTab[i]->initialize(privileged) < 0) {
+ if (virStateDriverTab[i]->initialize(privileged,
+ callback,
+ opaque) < 0) {
VIR_ERROR(_("Initialization of %s state driver failed"),
virStateDriverTab[i]->name);
return -1;
@@ -852,24 +859,6 @@ int virStateReload(void) {
}
/**
- * virStateActive:
- *
- * Run each virtualization driver's "active" method.
- *
- * Returns 0 if none are active, 1 if at least one is.
- */
-int virStateActive(void) {
- int i, ret = 0;
-
- for (i = 0 ; i < virStateDriverTabCount ; i++) {
- if (virStateDriverTab[i]->active &&
- virStateDriverTab[i]->active())
- ret = 1;
- }
- return ret;
-}
-
-/**
* virStateStop:
*
* Run each virtualization driver's "stop" method.
diff --git a/src/libvirt_internal.h b/src/libvirt_internal.h
index b85a29d..2eda156 100644
--- a/src/libvirt_internal.h
+++ b/src/libvirt_internal.h
@@ -28,10 +28,14 @@
# include "internal.h"
# ifdef WITH_LIBVIRTD
-int virStateInitialize(bool privileged);
+typedef void (*virStateInhibitCallback)(bool inhibit,
+ void *opaque);
+
+int virStateInitialize(bool privileged,
+ virStateInhibitCallback inhibit,
+ void *opaque);
int virStateCleanup(void);
int virStateReload(void);
-int virStateActive(void);
int virStateStop(void);
# endif
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cc1aaf5..5029baa 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1573,6 +1573,7 @@ xdr_virNetMessageError;
# virnetserver.h
virNetServerAddProgram;
virNetServerAddService;
+virNetServerAddShutdownInhibition;
virNetServerAddSignalHandler;
virNetServerAutoShutdown;
virNetServerClose;
@@ -1582,6 +1583,7 @@ virNetServerNew;
virNetServerNewPostExecRestart;
virNetServerPreExecRestart;
virNetServerQuit;
+virNetServerRemoveShutdownInhibition;
virNetServerRun;
virNetServerSetTLSContext;
virNetServerUpdateServices;
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index 56bf85c..189a4e9 100644
--- a/src/libxl/libxl_conf.h
+++ b/src/libxl/libxl_conf.h
@@ -61,6 +61,11 @@ struct _libxlDriverPrivate {
libxl_ctx ctx;
virBitmapPtr reservedVNCPorts;
+
+ size_t nactive;
+ virStateInhibitCallback inhibitCallback;
+ void *inhibitOpaque;
+
virDomainObjList domains;
virDomainEventStatePtr domainEventState;
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 6e59d9f..2513d94 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -312,6 +312,10 @@ libxlVmCleanup(libxlDriverPrivatePtr driver,
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
}
+ driver->nactive--;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(false, driver->inhibitOpaque);
+
if ((vm->def->ngraphics == 1) &&
vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
vm->def->graphics[0]->data.vnc.autoport) {
@@ -717,6 +721,10 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
goto error;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
restore_fd < 0 ?
VIR_DOMAIN_EVENT_STARTED_BOOTED :
@@ -782,6 +790,10 @@ libxlReconnectDomain(void *payload,
vm->def->id = d_info.domid;
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN);
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
/* Recreate domain death et. al. events */
libxlCreateDomEvents(vm);
virDomainObjUnlock(vm);
@@ -834,7 +846,10 @@ libxlShutdown(void)
}
static int
-libxlStartup(bool privileged) {
+libxlStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
const libxl_version_info *ver_info;
char *log_file = NULL;
virCommandPtr cmd;
@@ -1030,14 +1045,6 @@ libxlReload(void)
return 0;
}
-static int
-libxlActive(void)
-{
- if (!libxl_driver)
- return 0;
-
- return 1;
-}
static virDrvOpenStatus
libxlOpen(virConnectPtr conn,
@@ -3969,7 +3976,6 @@ static virStateDriver libxlStateDriver = {
.initialize = libxlStartup,
.cleanup = libxlShutdown,
.reload = libxlReload,
- .active = libxlActive,
};
diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
index 4ae0c5e..ea345be 100644
--- a/src/lxc/lxc_conf.h
+++ b/src/lxc/lxc_conf.h
@@ -52,6 +52,11 @@ struct _virLXCDriver {
virCapsPtr caps;
virCgroupPtr cgroup;
+
+ size_t nactive;
+ virStateInhibitCallback inhibitCallback;
+ void *inhibitOpaque;
+
virDomainObjList domains;
char *configDir;
char *autostartDir;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 1b5e642..9c81167 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -69,7 +69,9 @@
#define LXC_NB_MEM_PARAM 3
-static int lxcStartup(bool privileged);
+static int lxcStartup(bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque);
static int lxcShutdown(void);
virLXCDriverPtr lxc_driver = NULL;
@@ -1397,7 +1399,9 @@ error:
}
-static int lxcStartup(bool privileged)
+static int lxcStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
char *ld;
int rc;
@@ -1563,26 +1567,6 @@ static int lxcShutdown(void)
return 0;
}
-/**
- * lxcActive:
- *
- * Checks if the LXC daemon is active, i.e. has an active domain
- *
- * Returns 1 if active, 0 otherwise
- */
-static int
-lxcActive(void) {
- int active;
-
- if (lxc_driver == NULL)
- return 0;
-
- lxcDriverLock(lxc_driver);
- active = virDomainObjListNumOfDomains(&lxc_driver->domains, 1);
- lxcDriverUnlock(lxc_driver);
-
- return active;
-}
static int lxcVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *version)
{
@@ -2757,7 +2741,6 @@ static virStateDriver lxcStateDriver = {
.name = LXC_DRIVER_NAME,
.initialize = lxcStartup,
.cleanup = lxcShutdown,
- .active = lxcActive,
.reload = lxcReload,
};
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 079bc3a..2e3d10a 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -251,6 +251,10 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
vm->pid = -1;
vm->def->id = -1;
+ driver->nactive--;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(false, driver->inhibitOpaque);
+
for (i = 0 ; i < vm->def->nnets ; i++) {
virDomainNetDefPtr iface = vm->def->nets[i];
vport = virDomainNetGetActualVirtPortProfile(iface);
@@ -1123,6 +1127,10 @@ int virLXCProcessStart(virConnectPtr conn,
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
priv->doneStopEvent = false;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
if (lxcContainerWaitForContinue(handshakefds[0]) < 0) {
char out[1024];
@@ -1293,6 +1301,10 @@ virLXCProcessReconnectDomain(void *payload, const void *name
ATTRIBUTE_UNUSED, v
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_UNKNOWN);
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
goto error;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 326665e..1cedf27 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -279,7 +279,10 @@ firewalld_dbus_filter_bridge(DBusConnection *connection
ATTRIBUTE_UNUSED,
* Initialization function for the QEmu daemon
*/
static int
-networkStartup(bool privileged) {
+networkStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
char *base = NULL;
#ifdef HAVE_FIREWALLD
DBusConnection *sysbus = NULL;
@@ -413,33 +416,6 @@ networkReload(void) {
return 0;
}
-/**
- * networkActive:
- *
- * Checks if the QEmu daemon is active, i.e. has an active domain or
- * an active network
- *
- * Returns 1 if active, 0 otherwise
- */
-static int
-networkActive(void) {
- unsigned int i;
- int active = 0;
-
- if (!driverState)
- return 0;
-
- networkDriverLock(driverState);
- for (i = 0 ; i < driverState->networks.count ; i++) {
- virNetworkObjPtr net = driverState->networks.objs[i];
- virNetworkObjLock(net);
- if (virNetworkObjIsActive(net))
- active = 1;
- virNetworkObjUnlock(net);
- }
- networkDriverUnlock(driverState);
- return active;
-}
/**
* networkShutdown:
@@ -3299,7 +3275,6 @@ static virStateDriver networkStateDriver = {
.initialize = networkStartup,
.cleanup = networkShutdown,
.reload = networkReload,
- .active = networkActive,
};
int networkRegister(void) {
diff --git a/src/node_device/node_device_hal.c b/src/node_device/node_device_hal.c
index 953e1d3..080aaed 100644
--- a/src/node_device/node_device_hal.c
+++ b/src/node_device/node_device_hal.c
@@ -586,9 +586,9 @@ static void device_prop_modified(LibHalContext *ctx ATTRIBUTE_UNUSED,
}
-
-
-static int halDeviceMonitorStartup(bool privileged ATTRIBUTE_UNUSED)
+static int halDeviceMonitorStartup(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
LibHalContext *hal_ctx = NULL;
char **udi = NULL;
@@ -736,13 +736,6 @@ static int halDeviceMonitorReload(void)
}
-static int halDeviceMonitorActive(void)
-{
- /* Always ready to deal with a shutdown */
- return 0;
-}
-
-
static virDrvOpenStatus halNodeDrvOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
unsigned int flags)
@@ -786,7 +779,6 @@ static virStateDriver halStateDriver = {
.initialize = halDeviceMonitorStartup, /* 0.5.0 */
.cleanup = halDeviceMonitorShutdown, /* 0.5.0 */
.reload = halDeviceMonitorReload, /* 0.5.0 */
- .active = halDeviceMonitorActive, /* 0.5.0 */
};
int halNodeRegister(void)
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 1f2efa9..482038c 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1604,7 +1604,9 @@ out:
return ret;
}
-static int udevDeviceMonitorStartup(bool privileged ATTRIBUTE_UNUSED)
+static int udevDeviceMonitorStartup(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
udevPrivate *priv = NULL;
struct udev *udev = NULL;
@@ -1723,13 +1725,6 @@ static int udevDeviceMonitorReload(void)
}
-static int udevDeviceMonitorActive(void)
-{
- /* Always ready to deal with a shutdown */
- return 0;
-}
-
-
static virDrvOpenStatus udevNodeDrvOpen(virConnectPtr conn,
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
unsigned int flags)
@@ -1772,7 +1767,6 @@ static virStateDriver udevStateDriver = {
.initialize = udevDeviceMonitorStartup, /* 0.7.3 */
.cleanup = udevDeviceMonitorShutdown, /* 0.7.3 */
.reload = udevDeviceMonitorReload, /* 0.7.3 */
- .active = udevDeviceMonitorActive, /* 0.7.3 */
};
int udevNodeRegister(void)
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
index b1b2c77..1f2871e 100644
--- a/src/nwfilter/nwfilter_driver.c
+++ b/src/nwfilter/nwfilter_driver.c
@@ -165,7 +165,9 @@ nwfilterDriverInstallDBusMatches(DBusConnection *sysbus
ATTRIBUTE_UNUSED)
* Initialization function for the QEmu daemon
*/
static int
-nwfilterDriverStartup(bool privileged)
+nwfilterDriverStartup(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
char *base = NULL;
DBusConnection *sysbus = NULL;
@@ -305,27 +307,6 @@ nwfilterDriverReload(void) {
return 0;
}
-/**
- * virNWFilterActive:
- *
- * Checks if the nwfilter driver is active, i.e. has an active nwfilter
- *
- * Returns 1 if active, 0 otherwise
- */
-static int
-nwfilterDriverActive(void) {
- int ret;
-
- if (!driverState)
- return 0;
-
- nwfilterDriverLock(driverState);
- ret = driverState->nwfilters.count ? 1 : 0;
- ret |= driverState->watchingFirewallD;
- nwfilterDriverUnlock(driverState);
-
- return ret;
-}
/**
* virNWFilterIsWatchingFirewallD:
@@ -696,7 +677,6 @@ static virStateDriver stateDriver = {
.initialize = nwfilterDriverStartup,
.cleanup = nwfilterDriverShutdown,
.reload = nwfilterDriverReload,
- .active = nwfilterDriverActive,
};
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index b7378a7..c55a0c0 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -70,6 +70,10 @@ struct qemud_driver {
int cgroupControllers;
char **cgroupDeviceACL;
+ size_t nactive;
+ virStateInhibitCallback inhibitCallback;
+ void *inhibitOpaque;
+
virDomainObjList domains;
/* These four directories are ones libvirtd uses (so must be root:root
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 80ab619..308539f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -593,7 +593,10 @@ static void qemuDomainNetsRestart(void *payload,
* Initialization function for the QEmu daemon
*/
static int
-qemuStartup(bool privileged) {
+qemuStartup(bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque)
+{
char *base = NULL;
char *driverConf = NULL;
int rc;
@@ -614,6 +617,8 @@ qemuStartup(bool privileged) {
qemu_driver->privileged = privileged;
qemu_driver->uri = privileged ? "qemu:///system" :
"qemu:///session";
+ qemu_driver->inhibitCallback = callback;
+ qemu_driver->inhibitOpaque = opaque;
/* Don't have a dom0 so start from 1 */
qemu_driver->nextvmid = 1;
@@ -948,28 +953,6 @@ qemuReload(void) {
return 0;
}
-/**
- * qemuActive:
- *
- * Checks if the QEmu daemon is active, i.e. has an active domain or
- * an active network
- *
- * Returns 1 if active, 0 otherwise
- */
-static int
-qemuActive(void) {
- int active = 0;
-
- if (!qemu_driver)
- return 0;
-
- /* XXX having to iterate here is not great because it requires many locks */
- qemuDriverLock(qemu_driver);
- active = virDomainObjListNumOfDomains(&qemu_driver->domains, 1);
- qemuDriverUnlock(qemu_driver);
- return active;
-}
-
/*
* qemuStop:
@@ -14680,7 +14663,6 @@ static virStateDriver qemuStateDriver = {
.initialize = qemuStartup,
.cleanup = qemuShutdown,
.reload = qemuReload,
- .active = qemuActive,
.stop = qemuStop,
};
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index dcdff9f..7faf4bd 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3229,6 +3229,10 @@ qemuProcessReconnect(void *opaque)
if (obj->def->id >= driver->nextvmid)
driver->nextvmid = obj->def->id + 1;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
endjob:
if (!qemuDomainObjEndJob(driver, obj))
obj = NULL;
@@ -3437,6 +3441,10 @@ int qemuProcessStart(virConnectPtr conn,
qemuDomainSetFakeReboot(driver, vm, false);
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_UNKNOWN);
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
/* Run an early hook to set-up missing devices */
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
char *xml = qemuDomainDefFormatXML(driver, vm->def, 0);
@@ -4003,6 +4011,10 @@ void qemuProcessStop(struct qemud_driver *driver,
*/
vm->def->id = -1;
+ driver->nactive--;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(false, driver->inhibitOpaque);
+
if ((logfile = qemuDomainCreateLog(driver, vm, true)) < 0) {
/* To not break the normal domain shutdown process, skip the
* timestamp log writing if failed on opening log file. */
@@ -4233,6 +4245,10 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
vm->def->id = driver->nextvmid++;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
if (virFileMakePath(driver->logDir) < 0) {
virReportSystemError(errno,
_("cannot create log directory %s"),
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 1bfdc4a..9fafbf6 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -150,7 +150,9 @@ static char *get_transport_from_scheme (char *scheme);
#ifdef WITH_LIBVIRTD
static int
-remoteStartup(bool privileged ATTRIBUTE_UNUSED)
+remoteStartup(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
/* Mark that we're inside the daemon so we can avoid
* re-entering ourselves
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index cf15240..b108399 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -101,8 +101,7 @@ struct _virNetServer {
virNetTLSContextPtr tls;
unsigned int autoShutdownTimeout;
- virNetServerAutoShutdownFunc autoShutdownFunc;
- void *autoShutdownOpaque;
+ size_t autoShutdownInhibitions;
virNetServerClientPrivNew clientPrivNew;
virNetServerClientPrivPreExecRestart clientPrivPreExecRestart;
@@ -707,19 +706,33 @@ bool virNetServerIsPrivileged(virNetServerPtr srv)
void virNetServerAutoShutdown(virNetServerPtr srv,
- unsigned int timeout,
- virNetServerAutoShutdownFunc func,
- void *opaque)
+ unsigned int timeout)
{
virNetServerLock(srv);
srv->autoShutdownTimeout = timeout;
- srv->autoShutdownFunc = func;
- srv->autoShutdownOpaque = opaque;
virNetServerUnlock(srv);
}
+
+void virNetServerAddShutdownInhibition(virNetServerPtr srv)
+{
+ virNetServerLock(srv);
+ srv->autoShutdownInhibitions++;
+ virNetServerUnlock(srv);
+}
+
+
+void virNetServerRemoveShutdownInhibition(virNetServerPtr srv)
+{
+ virNetServerLock(srv);
+ srv->autoShutdownInhibitions--;
+ virNetServerUnlock(srv);
+}
+
+
+
static sig_atomic_t sigErrors = 0;
static int sigLastErrno = 0;
static int sigWrite = -1;
@@ -932,7 +945,7 @@ static void virNetServerAutoShutdownTimer(int timerid
ATTRIBUTE_UNUSED,
virNetServerLock(srv);
- if (srv->autoShutdownFunc(srv, srv->autoShutdownOpaque)) {
+ if (!srv->autoShutdownInhibitions) {
VIR_DEBUG("Automatic shutdown triggered");
srv->quit = 1;
}
diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h
index ff2dc94..38cccfe 100644
--- a/src/rpc/virnetserver.h
+++ b/src/rpc/virnetserver.h
@@ -60,9 +60,10 @@ typedef int (*virNetServerAutoShutdownFunc)(virNetServerPtr srv, void
*opaque);
bool virNetServerIsPrivileged(virNetServerPtr srv);
void virNetServerAutoShutdown(virNetServerPtr srv,
- unsigned int timeout,
- virNetServerAutoShutdownFunc func,
- void *opaque);
+ unsigned int timeout);
+
+void virNetServerAddShutdownInhibition(virNetServerPtr srv);
+void virNetServerRemoveShutdownInhibition(virNetServerPtr srv);
typedef void (*virNetServerSignalFunc)(virNetServerPtr srv, siginfo_t *info, void
*opaque);
diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c
index c7aabfc..d9ba42b 100644
--- a/src/secret/secret_driver.c
+++ b/src/secret/secret_driver.c
@@ -1073,7 +1073,9 @@ secretDriverCleanup(void)
}
static int
-secretDriverStartup(bool privileged)
+secretDriverStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
char *base = NULL;
@@ -1166,7 +1168,6 @@ static virStateDriver stateDriver = {
.initialize = secretDriverStartup,
.cleanup = secretDriverCleanup,
.reload = secretDriverReload,
- .active = NULL /* All persistent state is immediately saved to disk */
};
int
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 681673a..07a768d 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -128,7 +128,9 @@ storageDriverAutostart(virStorageDriverStatePtr driver) {
* Initialization function for the QEmu daemon
*/
static int
-storageDriverStartup(bool privileged)
+storageDriverStartup(bool privileged,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
char *base = NULL;
@@ -202,33 +204,6 @@ storageDriverReload(void) {
return 0;
}
-/**
- * virStorageActive:
- *
- * Checks if the storage driver is active, i.e. has an active pool
- *
- * Returns 1 if active, 0 otherwise
- */
-static int
-storageDriverActive(void) {
- unsigned int i;
- int active = 0;
-
- if (!driverState)
- return 0;
-
- storageDriverLock(driverState);
-
- for (i = 0 ; i < driverState->pools.count ; i++) {
- virStoragePoolObjLock(driverState->pools.objs[i]);
- if (virStoragePoolObjIsActive(driverState->pools.objs[i]))
- active = 1;
- virStoragePoolObjUnlock(driverState->pools.objs[i]);
- }
-
- storageDriverUnlock(driverState);
- return active;
-}
/**
* virStorageShutdown:
@@ -2437,7 +2412,6 @@ static virStateDriver stateDriver = {
.initialize = storageDriverStartup,
.cleanup = storageDriverShutdown,
.reload = storageDriverReload,
- .active = storageDriverActive,
};
int storageRegister(void) {
diff --git a/src/uml/uml_conf.h b/src/uml/uml_conf.h
index ebae24e..9bddedc 100644
--- a/src/uml/uml_conf.h
+++ b/src/uml/uml_conf.h
@@ -45,11 +45,14 @@ struct uml_driver {
virMutex lock;
bool privileged;
+ virStateInhibitCallback inhibitCallback;
+ void *inhibitOpaque;
unsigned long umlVersion;
int nextvmid;
virDomainObjList domains;
+ size_t nactive;
char *configDir;
char *autostartDir;
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index ea65448..731947d 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -372,6 +372,11 @@ reread:
}
dom->def->id = driver->nextvmid++;
+
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(true, driver->inhibitOpaque);
+ driver->nactive++;
+
virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_BOOTED);
@@ -419,7 +424,9 @@ cleanup:
* Initialization function for the Uml daemon
*/
static int
-umlStartup(bool privileged)
+umlStartup(bool privileged,
+ virStateInhibitCallback callback,
+ void *opaque)
{
char *base = NULL;
char *userdir = NULL;
@@ -428,6 +435,8 @@ umlStartup(bool privileged)
return -1;
uml_driver->privileged = privileged;
+ uml_driver->inhibitCallback = callback;
+ uml_driver->inhibitOpaque = opaque;
if (virMutexInit(¨_driver->lock) < 0) {
VIR_FREE(uml_driver);
@@ -585,27 +594,6 @@ umlReload(void) {
return 0;
}
-/**
- * umlActive:
- *
- * Checks if the Uml daemon is active, i.e. has an active domain or
- * an active network
- *
- * Returns 1 if active, 0 otherwise
- */
-static int
-umlActive(void) {
- int active = 0;
-
- if (!uml_driver)
- return 0;
-
- umlDriverLock(uml_driver);
- active = virDomainObjListNumOfDomains(¨_driver->domains, 1);
- umlDriverUnlock(uml_driver);
-
- return active;
-}
static void
umlShutdownOneVM(void *payload, const void *name ATTRIBUTE_UNUSED, void *opaque)
@@ -1154,6 +1142,10 @@ static void umlShutdownVMDaemon(struct uml_driver *driver,
vm->def->id = -1;
vm->newDef = NULL;
}
+
+ driver->nactive--;
+ if (!driver->nactive && driver->inhibitCallback)
+ driver->inhibitCallback(false, driver->inhibitOpaque);
}
@@ -2634,7 +2626,6 @@ static virStateDriver umlStateDriver = {
.initialize = umlStartup,
.cleanup = umlShutdown,
.reload = umlReload,
- .active = umlActive,
};
int umlRegister(void) {
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index 584a7b4..c63cd83 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -201,7 +201,9 @@ done:
#ifdef WITH_LIBVIRTD
static int
-xenInitialize (bool privileged ATTRIBUTE_UNUSED)
+xenInitialize(bool privileged ATTRIBUTE_UNUSED,
+ virStateInhibitCallback callback ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
{
inside_daemon = true;
return 0;
--
1.7.12.1