[libvirt] [PATCH 08/10] Replace polling for active VMs with signalling by drivers

Daniel P. Berrange berrange at redhat.com
Tue Nov 27 18:18:18 UTC 2012


From: "Daniel P. Berrange" <berrange at 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 at 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 1ebbac1..f7046f6 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);
@@ -1270,9 +1274,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 4026a15..6109e56 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1597,12 +1597,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 0e73d64..78da7c5 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 8d649bf..6e99f28 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1580,6 +1580,7 @@ xdr_virNetMessageError;
 # virnetserver.h
 virNetServerAddProgram;
 virNetServerAddService;
+virNetServerAddShutdownInhibition;
 virNetServerAddSignalHandler;
 virNetServerAutoShutdown;
 virNetServerClose;
@@ -1589,6 +1590,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 ae4451a..c67d95a 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 6cb3fe2..fbadbcb 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 94a74dd..81124f1 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);
@@ -1131,6 +1135,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];
 
@@ -1301,6 +1309,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 67ee262..d8f5989 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -330,7 +330,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;
@@ -464,33 +467,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:
@@ -3307,7 +3283,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 bc4e2e9..c9ca00c 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 a0ee4f1..cc81914 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 186b79f..655055d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -610,7 +610,10 @@ qemuDomainFindMaxID(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;
@@ -631,6 +634,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;
@@ -972,28 +977,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:
@@ -14975,7 +14958,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 cdaa2df..de15494 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3228,6 +3228,10 @@ qemuProcessReconnect(void *opaque)
             goto error;
     }
 
+    if (!driver->nactive && driver->inhibitCallback)
+        driver->inhibitCallback(true, driver->inhibitOpaque);
+    driver->nactive++;
+
 endjob:
     if (!qemuDomainObjEndJob(driver, obj))
         obj = NULL;
@@ -3436,6 +3440,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);
@@ -4002,6 +4010,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 01cebb4..7ef69d6 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 d27bb41..3cb2312 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:
@@ -2445,7 +2420,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 5a87e31..7eedaf1 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(&uml_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(&uml_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 5a40757..15e760d 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.11.7




More information about the libvir-list mailing list