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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: "Daniel P. Berrange" <berrange@xxxxxxxxxx>

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@xxxxxxxxxx>
---
 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(&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 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

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]