diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-05-16 21:41:42 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-05-16 21:41:42 +0200 |
commit | 6e284eaad57843950a54f44f02f920216dd3fc88 (patch) | |
tree | 6abd320805cff612a155b11692f73bc63cbf81db /sys/src/cmd/ndb | |
parent | 5c2b4dfc8173355629e70a6437ccfc378f0bf757 (diff) |
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().
Diffstat (limited to 'sys/src/cmd/ndb')
-rw-r--r-- | sys/src/cmd/ndb/cs.c | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/sys/src/cmd/ndb/cs.c b/sys/src/cmd/ndb/cs.c index 71e2d9e0b..4451f223f 100644 --- a/sys/src/cmd/ndb/cs.c +++ b/sys/src/cmd/ndb/cs.c @@ -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 { |