Improve locking of creating and dropping links in the graph, acquiring
the topology mutex in the following functions, that manipulate pointers to peer nodes: - ng_bypass() - ng_path2noderef() when switching to the next node in sequence. Rewrite the function a bit. - ng_address_hook() - ng_address_path() This patch improves stability of large mpd5 installations.
This commit is contained in:
parent
0380bf4d79
commit
a7da736a64
@ -1162,11 +1162,13 @@ ng_bypass(hook_p hook1, hook_p hook2)
|
||||
TRAP_ERROR();
|
||||
return (EINVAL);
|
||||
}
|
||||
mtx_lock(&ng_topo_mtx);
|
||||
hook1->hk_peer->hk_peer = hook2->hk_peer;
|
||||
hook2->hk_peer->hk_peer = hook1->hk_peer;
|
||||
|
||||
hook1->hk_peer = &ng_deadhook;
|
||||
hook2->hk_peer = &ng_deadhook;
|
||||
mtx_unlock(&ng_topo_mtx);
|
||||
|
||||
NG_HOOK_UNREF(hook1);
|
||||
NG_HOOK_UNREF(hook2);
|
||||
@ -1643,10 +1645,8 @@ ng_path2noderef(node_p here, const char *address,
|
||||
node_p *destp, hook_p *lasthook)
|
||||
{
|
||||
char fullpath[NG_PATHSIZ];
|
||||
char *nodename, *path, pbuf[2];
|
||||
char *nodename, *path;
|
||||
node_p node, oldnode;
|
||||
char *cp;
|
||||
hook_p hook = NULL;
|
||||
|
||||
/* Initialize */
|
||||
if (destp == NULL) {
|
||||
@ -1664,11 +1664,6 @@ ng_path2noderef(node_p here, const char *address,
|
||||
TRAP_ERROR();
|
||||
return EINVAL;
|
||||
}
|
||||
if (path == NULL) {
|
||||
pbuf[0] = '.'; /* Needs to be writable */
|
||||
pbuf[1] = '\0';
|
||||
path = pbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* For an absolute address, jump to the starting node.
|
||||
@ -1690,41 +1685,41 @@ ng_path2noderef(node_p here, const char *address,
|
||||
NG_NODE_REF(node);
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
if (lasthook != NULL)
|
||||
*lasthook = NULL;
|
||||
*destp = node;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now follow the sequence of hooks
|
||||
* XXX
|
||||
* We actually cannot guarantee that the sequence
|
||||
* is not being demolished as we crawl along it
|
||||
* without extra-ordinary locking etc.
|
||||
* So this is a bit dodgy to say the least.
|
||||
* We can probably hold up some things by holding
|
||||
* the nodelist mutex for the time of this
|
||||
* crawl if we wanted.. At least that way we wouldn't have to
|
||||
* worry about the nodes disappearing, but the hooks would still
|
||||
* be a problem.
|
||||
*
|
||||
* XXXGL: The path may demolish as we go the sequence, but if
|
||||
* we hold the topology mutex at critical places, then, I hope,
|
||||
* we would always have valid pointers in hand, although the
|
||||
* path behind us may no longer exist.
|
||||
*/
|
||||
for (cp = path; node != NULL && *cp != '\0'; ) {
|
||||
for (;;) {
|
||||
hook_p hook;
|
||||
char *segment;
|
||||
|
||||
/*
|
||||
* Break out the next path segment. Replace the dot we just
|
||||
* found with a NUL; "cp" points to the next segment (or the
|
||||
* found with a NUL; "path" points to the next segment (or the
|
||||
* NUL at the end).
|
||||
*/
|
||||
for (segment = cp; *cp != '\0'; cp++) {
|
||||
if (*cp == '.') {
|
||||
*cp++ = '\0';
|
||||
for (segment = path; *path != '\0'; path++) {
|
||||
if (*path == '.') {
|
||||
*path++ = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Empty segment */
|
||||
if (*segment == '\0')
|
||||
continue;
|
||||
|
||||
/* We have a segment, so look for a hook by that name */
|
||||
hook = ng_findhook(node, segment);
|
||||
|
||||
mtx_lock(&ng_topo_mtx);
|
||||
/* Can't get there from here... */
|
||||
if (hook == NULL
|
||||
|| NG_HOOK_PEER(hook) == NULL
|
||||
@ -1732,15 +1727,7 @@ ng_path2noderef(node_p here, const char *address,
|
||||
|| NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))) {
|
||||
TRAP_ERROR();
|
||||
NG_NODE_UNREF(node);
|
||||
#if 0
|
||||
printf("hooknotvalid %s %s %d %d %d %d ",
|
||||
path,
|
||||
segment,
|
||||
hook == NULL,
|
||||
NG_HOOK_PEER(hook) == NULL,
|
||||
NG_HOOK_NOT_VALID(hook),
|
||||
NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook)));
|
||||
#endif
|
||||
mtx_unlock(&ng_topo_mtx);
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
@ -1757,21 +1744,25 @@ ng_path2noderef(node_p here, const char *address,
|
||||
NG_NODE_UNREF(oldnode); /* XXX another race */
|
||||
if (NG_NODE_NOT_VALID(node)) {
|
||||
NG_NODE_UNREF(node); /* XXX more races */
|
||||
node = NULL;
|
||||
mtx_unlock(&ng_topo_mtx);
|
||||
TRAP_ERROR();
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
/* If node somehow missing, fail here (probably this is not needed) */
|
||||
if (node == NULL) {
|
||||
TRAP_ERROR();
|
||||
return (ENXIO);
|
||||
if (*path == '\0') {
|
||||
if (lasthook != NULL) {
|
||||
if (hook != NULL) {
|
||||
*lasthook = NG_HOOK_PEER(hook);
|
||||
NG_HOOK_REF(*lasthook);
|
||||
} else
|
||||
*lasthook = NULL;
|
||||
}
|
||||
mtx_unlock(&ng_topo_mtx);
|
||||
*destp = node;
|
||||
return (0);
|
||||
}
|
||||
mtx_unlock(&ng_topo_mtx);
|
||||
}
|
||||
|
||||
/* Done */
|
||||
*destp = node;
|
||||
if (lasthook != NULL)
|
||||
*lasthook = (hook ? NG_HOOK_PEER(hook) : NULL);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/***************************************************************\
|
||||
@ -3501,12 +3492,14 @@ ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr)
|
||||
* that the peer is still connected (even if invalid,) we know
|
||||
* that the peer node is present, though maybe invalid.
|
||||
*/
|
||||
mtx_lock(&ng_topo_mtx);
|
||||
if ((hook == NULL) ||
|
||||
NG_HOOK_NOT_VALID(hook) ||
|
||||
NG_HOOK_NOT_VALID(peer = NG_HOOK_PEER(hook)) ||
|
||||
NG_NODE_NOT_VALID(peernode = NG_PEER_NODE(hook))) {
|
||||
NG_FREE_ITEM(item);
|
||||
TRAP_ERROR();
|
||||
mtx_unlock(&ng_topo_mtx);
|
||||
return (ENETDOWN);
|
||||
}
|
||||
|
||||
@ -3518,6 +3511,9 @@ ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr)
|
||||
NGI_SET_HOOK(item, peer);
|
||||
NGI_SET_NODE(item, peernode);
|
||||
SET_RETADDR(item, here, retaddr);
|
||||
|
||||
mtx_unlock(&ng_topo_mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -3539,10 +3535,9 @@ ng_address_path(node_p here, item_p item, char *address, ng_ID_t retaddr)
|
||||
return (error);
|
||||
}
|
||||
NGI_SET_NODE(item, dest);
|
||||
if ( hook) {
|
||||
NG_HOOK_REF(hook); /* don't let it go while on the queue */
|
||||
if (hook)
|
||||
NGI_SET_HOOK(item, hook);
|
||||
}
|
||||
|
||||
SET_RETADDR(item, here, retaddr);
|
||||
return (0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user