The nwfilter conf update mutex is held whenever a virt
driver is starting a VM, or when an nwfilter define/undefine
operation is taking place. As such this serializes startup
of VMs which is highly undesirable.
The VM startup process doesn't make changes to the nwfilter
configuration, so it can be relaxed to only hold a read
lock. Only the define/undefine operations need write locks.
Thus using a read/write lock removes contention when starting
guests, unless concurrent nwfilter updates are taking place.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/conf/nwfilter_conf.c | 17 +++++++++++------
src/conf/nwfilter_conf.h | 3 ++-
src/libvirt_private.syms | 3 ++-
src/lxc/lxc_driver.c | 4 ++--
src/nwfilter/nwfilter_driver.c | 4 ++--
src/qemu/qemu_driver.c | 4 ++--
src/uml/uml_driver.c | 4 ++--
7 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
index e712ca5..52e1c06 100644
--- a/src/conf/nwfilter_conf.c
+++ b/src/conf/nwfilter_conf.c
@@ -143,17 +143,22 @@ static const struct int_map chain_priorities[] = {
/*
* only one filter update allowed
*/
-static virMutex updateMutex;
+static virRWLock updateLock;
static bool initialized = false;
void
-virNWFilterLockFilterUpdates(void) {
- virMutexLock(&updateMutex);
+virNWFilterReadLockFilterUpdates(void) {
+ virRWLockRead(&updateLock);
+}
+
+void
+virNWFilterWriteLockFilterUpdates(void) {
+ virRWLockWrite(&updateLock);
}
void
virNWFilterUnlockFilterUpdates(void) {
- virMutexUnlock(&updateMutex);
+ virRWLockUnlock(&updateLock);
}
@@ -3477,7 +3482,7 @@ int virNWFilterConfLayerInit(virDomainObjListIterator domUpdateCB,
initialized = true;
- if (virMutexInitRecursive(&updateMutex) < 0)
+ if (virRWLockInit(&updateLock) < 0)
return -1;
return 0;
@@ -3489,7 +3494,7 @@ void virNWFilterConfLayerShutdown(void)
if (!initialized)
return;
- virMutexDestroy(&updateMutex);
+ virRWLockDestroy(&updateLock);
initialized = false;
virNWFilterDomainFWUpdateOpaque = NULL;
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 6b8b515..0d09b6a 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -716,7 +716,8 @@ virNWFilterDefPtr virNWFilterDefParseFile(const char *filename);
void virNWFilterObjLock(virNWFilterObjPtr obj);
void virNWFilterObjUnlock(virNWFilterObjPtr obj);
-void virNWFilterLockFilterUpdates(void);
+void virNWFilterWriteLockFilterUpdates(void);
+void virNWFilterReadLockFilterUpdates(void);
void virNWFilterUnlockFilterUpdates(void);
int virNWFilterConfLayerInit(virDomainObjListIterator domUpdateCB, void *opaque);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index eb91693..a4b1c14 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -575,7 +575,6 @@ virNWFilterDefParseString;
virNWFilterInstFiltersOnAllVMs;
virNWFilterJumpTargetTypeToString;
virNWFilterLoadAllConfigs;
-virNWFilterLockFilterUpdates;
virNWFilterObjAssignDef;
virNWFilterObjDeleteDef;
virNWFilterObjFindByName;
@@ -587,6 +586,7 @@ virNWFilterObjSaveDef;
virNWFilterObjUnlock;
virNWFilterPrintStateMatchFlags;
virNWFilterPrintTCPFlags;
+virNWFilterReadLockFilterUpdates;
virNWFilterRegisterCallbackDriver;
virNWFilterRuleActionTypeToString;
virNWFilterRuleDirectionTypeToString;
@@ -594,6 +594,7 @@ virNWFilterRuleProtocolTypeToString;
virNWFilterTestUnassignDef;
virNWFilterUnlockFilterUpdates;
virNWFilterUnRegisterCallbackDriver;
+virNWFilterWriteLockFilterUpdates;
# conf/nwfilter_ipaddrmap.h
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index b1f8a89..aeaa2da 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1015,7 +1015,7 @@ static int lxcDomainCreateWithFiles(virDomainPtr dom,
virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, -1);
- virNWFilterLockFilterUpdates();
+ virNWFilterReadLockFilterUpdates();
if (!(vm = lxcDomObjFromDomain(dom)))
goto cleanup;
@@ -1112,7 +1112,7 @@ lxcDomainCreateXMLWithFiles(virConnectPtr conn,
virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, NULL);
- virNWFilterLockFilterUpdates();
+ virNWFilterReadLockFilterUpdates();
if (!(caps = virLXCDriverGetCapabilities(driver, false)))
goto cleanup;
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
index 8518e90..f8952c9 100644
--- a/src/nwfilter/nwfilter_driver.c
+++ b/src/nwfilter/nwfilter_driver.c
@@ -556,7 +556,7 @@ nwfilterDefineXML(virConnectPtr conn,
virNWFilterPtr ret = NULL;
nwfilterDriverLock(driver);
- virNWFilterLockFilterUpdates();
+ virNWFilterWriteLockFilterUpdates();
virNWFilterCallbackDriversLock();
if (!(def = virNWFilterDefParseString(xml)))
@@ -596,7 +596,7 @@ nwfilterUndefine(virNWFilterPtr obj) {
int ret = -1;
nwfilterDriverLock(driver);
- virNWFilterLockFilterUpdates();
+ virNWFilterWriteLockFilterUpdates();
virNWFilterCallbackDriversLock();
nwfilter = virNWFilterObjFindByUUID(&driver->nwfilters, obj->uuid);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2e55cfd..e246e6f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1576,7 +1576,7 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn,
if (flags & VIR_DOMAIN_START_AUTODESTROY)
start_flags |= VIR_QEMU_PROCESS_START_AUTODESTROY;
- virNWFilterLockFilterUpdates();
+ virNWFilterReadLockFilterUpdates();
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
goto cleanup;
@@ -6098,7 +6098,7 @@ qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
VIR_DOMAIN_START_BYPASS_CACHE |
VIR_DOMAIN_START_FORCE_BOOT, -1);
- virNWFilterLockFilterUpdates();
+ virNWFilterReadLockFilterUpdates();
if (!(vm = qemuDomObjFromDomain(dom)))
return -1;
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 19b5f62..ae34a0e 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -1574,7 +1574,7 @@ static virDomainPtr umlDomainCreateXML(virConnectPtr conn, const
char *xml,
virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, NULL);
- virNWFilterLockFilterUpdates();
+ virNWFilterReadLockFilterUpdates();
umlDriverLock(driver);
if (!(def = virDomainDefParseString(xml, driver->caps, driver->xmlopt,
1 << VIR_DOMAIN_VIRT_UML,
@@ -1999,7 +1999,7 @@ static int umlDomainCreateWithFlags(virDomainPtr dom, unsigned int
flags) {
virCheckFlags(VIR_DOMAIN_START_AUTODESTROY, -1);
- virNWFilterLockFilterUpdates();
+ virNWFilterReadLockFilterUpdates();
umlDriverLock(driver);
vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
--
1.8.4.2