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(¨_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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list