ndb/cs: prevent deadlock with ndb/cs by mounting /srv/dns *AFTER* /net
the dnsquery() library function should not start mouting /srv/dns on its own. this problem arrises only for ndb/cs as it is started before ndb/dns. the issue with mounting /srv/dns before /net is when ndb/cs attempts to read the list of interfaces, accessing /net/ipifc, which triggers a rpc to ndb/dns as it is ontop of the mount. this can yield a deadlock when ndb/dns blocks its 9p loop waiting for requests to complete on a refresh and the requests are stuck waiting for ndb/cs to translate a dial string for announce().
This commit is contained in:
parent
5c2b4dfc81
commit
6e284eaad5
2 changed files with 51 additions and 33 deletions
|
@ -1081,12 +1081,8 @@ netinit(int background)
|
|||
Network *np;
|
||||
|
||||
if(background){
|
||||
switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
if(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT) != 0)
|
||||
return;
|
||||
}
|
||||
qlock(&netlock);
|
||||
}
|
||||
|
||||
|
@ -1627,6 +1623,43 @@ slave(char *host)
|
|||
|
||||
}
|
||||
|
||||
static int
|
||||
mountdns(void)
|
||||
{
|
||||
static QLock mountlock;
|
||||
static int mounted;
|
||||
char buf[128], *p;
|
||||
int fd;
|
||||
|
||||
if(mounted)
|
||||
return 0;
|
||||
|
||||
qlock(&mountlock);
|
||||
snprint(buf, sizeof(buf), "%s/dns", mntpt);
|
||||
if(access(buf, AEXIST) == 0)
|
||||
goto done;
|
||||
if(strcmp(mntpt, "/net") == 0)
|
||||
snprint(buf, sizeof(buf), "/srv/dns");
|
||||
else {
|
||||
snprint(buf, sizeof(buf), "/srv/dns%s", mntpt);
|
||||
while((p = strchr(buf+8, '/')) != nil)
|
||||
*p = '_';
|
||||
}
|
||||
if((fd = open(buf, ORDWR)) < 0){
|
||||
err:
|
||||
qunlock(&mountlock);
|
||||
return -1;
|
||||
}
|
||||
if(mount(fd, -1, mntpt, MAFTER, "") < 0){
|
||||
close(fd);
|
||||
goto err;
|
||||
}
|
||||
done:
|
||||
mounted = 1;
|
||||
qunlock(&mountlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Ndbtuple*
|
||||
dnsip6lookup(char *mntpt, char *buf, Ndbtuple *t)
|
||||
{
|
||||
|
@ -1662,6 +1695,11 @@ dnsiplookup(char *host, Ndbs *s, int v6)
|
|||
return nil;
|
||||
}
|
||||
|
||||
if(mountdns() < 0){
|
||||
qlock(&dblock);
|
||||
return nil;
|
||||
}
|
||||
|
||||
if(strcmp(ipattr(host), "ip") == 0)
|
||||
t = dnsquery(mntpt, host, "ptr");
|
||||
else {
|
||||
|
|
|
@ -12,13 +12,12 @@ static Ndbtuple *doquery(int, char *dn, char *type);
|
|||
* search for a tuple that has the given 'attr=val' and also 'rattr=x'.
|
||||
* copy 'x' into 'buf' and return the whole tuple.
|
||||
*
|
||||
* return 0 if not found.
|
||||
* return nil if not found.
|
||||
*/
|
||||
Ndbtuple*
|
||||
dnsquery(char *net, char *val, char *type)
|
||||
{
|
||||
char rip[128];
|
||||
char *p;
|
||||
char buf[128];
|
||||
Ndbtuple *t;
|
||||
int fd;
|
||||
|
||||
|
@ -28,37 +27,18 @@ dnsquery(char *net, char *val, char *type)
|
|||
|
||||
if(net == nil)
|
||||
net = "/net";
|
||||
snprint(rip, sizeof(rip), "%s/dns", net);
|
||||
fd = open(rip, ORDWR);
|
||||
if(fd < 0){
|
||||
if(strcmp(net, "/net") == 0)
|
||||
snprint(rip, sizeof(rip), "/srv/dns");
|
||||
else {
|
||||
snprint(rip, sizeof(rip), "/srv/dns%s", net);
|
||||
p = strrchr(rip, '/');
|
||||
*p = '_';
|
||||
}
|
||||
fd = open(rip, ORDWR);
|
||||
if(fd < 0)
|
||||
return nil;
|
||||
if(mount(fd, -1, net, MBEFORE, "") < 0){
|
||||
close(fd);
|
||||
return nil;
|
||||
}
|
||||
/* fd is now closed */
|
||||
snprint(rip, sizeof(rip), "%s/dns", net);
|
||||
fd = open(rip, ORDWR);
|
||||
if(fd < 0)
|
||||
return nil;
|
||||
}
|
||||
|
||||
snprint(buf, sizeof(buf), "%s/dns", net);
|
||||
if((fd = open(buf, ORDWR)) < 0)
|
||||
return nil;
|
||||
|
||||
/* zero out the error string */
|
||||
werrstr("");
|
||||
|
||||
/* if this is a reverse lookup, first lookup the domain name */
|
||||
if(strcmp(type, "ptr") == 0){
|
||||
mkptrname(val, rip, sizeof rip);
|
||||
t = doquery(fd, rip, "ptr");
|
||||
mkptrname(val, buf, sizeof buf);
|
||||
t = doquery(fd, buf, "ptr");
|
||||
} else
|
||||
t = doquery(fd, val, type);
|
||||
|
||||
|
|
Loading…
Reference in a new issue