Ta-Da! Finally the commit you've been waiting for. This is yet
one of the bottlenecks. Each API has to go through the list of
network objects to find the correct one to work on. But currently
it's done in suboptimal way: every single network object is
locked, and then compared. If found, it's returned, if not it's
unlocked and the loop continues with its sibling. This is not
optimal as locking every network object can make us waiting for
other APIs finish their job. Therefore we serialize here
effectively. Fortunately, with previous patches we are sure that
network definition will not change as we traverse the list.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/conf/network_conf.c | 26 ++++++++++++++++++++------
src/conf/network_conf.h | 1 +
2 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 007cebb..a1bdaf5 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -162,13 +162,20 @@ virNetworkObjFindByUUIDLocked(virNetworkObjListPtr nets,
size_t i;
for (i = 0; i < nets->count; i++) {
- virObjectLock(nets->objs[i]);
if (!memcmp(nets->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN)) {
ret = nets->objs[i];
virObjectRef(ret);
break;
}
- virObjectUnlock(nets->objs[i]);
+ }
+
+ if (ret) {
+ virObjectLock(ret);
+ if (ret->removing) {
+ virObjectUnref(ret);
+ virObjectUnlock(ret);
+ ret = NULL;
+ }
}
return ret;
@@ -193,13 +200,20 @@ virNetworkObjFindByNameLocked(virNetworkObjListPtr nets,
size_t i;
for (i = 0; i < nets->count; i++) {
- virObjectLock(nets->objs[i]);
if (STREQ(nets->objs[i]->def->name, name)) {
ret = nets->objs[i];
virObjectRef(ret);
break;
}
- virObjectUnlock(nets->objs[i]);
+ }
+
+ if (ret) {
+ virObjectLock(ret);
+ if (ret->removing) {
+ virObjectUnref(ret);
+ virObjectUnlock(ret);
+ ret = NULL;
+ }
}
return ret;
@@ -675,17 +689,17 @@ void virNetworkRemoveInactive(virNetworkObjListPtr nets,
{
size_t i;
+ net->removing = true;
virObjectUnlock(net);
virObjectLock(nets);
+ virObjectLock(net);
for (i = 0; i < nets->count; i++) {
- virObjectLock(nets->objs[i]);
if (nets->objs[i] == net) {
VIR_DELETE_ELEMENT(nets->objs, i, nets->count);
virObjectUnlock(net);
virObjectUnref(net);
break;
}
- virObjectUnlock(nets->objs[i]);
}
virObjectUnlock(nets);
}
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index c2e1885..29d13c9 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -273,6 +273,7 @@ struct _virNetworkObj {
unsigned long long floor_sum; /* sum of all 'floor'-s of attached NICs */
unsigned int taint;
+ bool removing;
};
virNetworkObjPtr virNetworkObjNew(void);
--
2.0.5