summaryrefslogtreecommitdiff
path: root/sys/src/9/ip/ethermedium.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2022-02-16 22:31:31 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2022-02-16 22:31:31 +0000
commit7289f371a0b113c12add274c4d4aa84d0c147dee (patch)
treecaaadea3c6dff299367b9079558141efc2f1ea65 /sys/src/9/ip/ethermedium.c
parent755880b19f365c3f98eac5c7de1d8b25f773ace3 (diff)
devip: dont hold ifc wlock during medium bind/unbind
Wlock()'ing the ifc causes a deadlock with Medium bind/unbind as the routine can walk /net, while ndb/dns or ndb/cs are currently blocked enumerating /net/ipifc/*. The fix is to have a fake medium, called "unbound", that is set temporarily during the call of Medium bind and unbind. That way, the interface rwlock can be released while bind/unbind is in progress. The ipifcunbind() routine will refuse to unbind a ifc that is currently assigned to the "unbound" medium, preventing any accidents.
Diffstat (limited to 'sys/src/9/ip/ethermedium.c')
-rw-r--r--sys/src/9/ip/ethermedium.c10
1 files changed, 0 insertions, 10 deletions
diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c
index fb6d05279..8a2a50899 100644
--- a/sys/src/9/ip/ethermedium.c
+++ b/sys/src/9/ip/ethermedium.c
@@ -107,7 +107,6 @@ static char *nbmsg = "nonblocking";
/*
* called to bind an IP ifc to an ethernet device
- * called with ifc wlock'd
*/
static void
etherbind(Ipifc *ifc, int argc, char **argv)
@@ -200,9 +199,6 @@ etherbind(Ipifc *ifc, int argc, char **argv)
kproc("recvarpproc", recvarpproc, ifc);
}
-/*
- * called with ifc wlock'd
- */
static void
etherunbind(Ipifc *ifc)
{
@@ -210,7 +206,6 @@ etherunbind(Ipifc *ifc)
while(waserror())
;
-
/* wait for readers to start */
while(er->arpp == (void*)-1 || er->read4p == (void*)-1 || er->read6p == (void*)-1)
tsleep(&up->sleep, return0, 0, 300);
@@ -221,19 +216,14 @@ etherunbind(Ipifc *ifc)
postnote(er->read6p, 1, "unbind", 0);
if(er->arpp != nil)
postnote(er->arpp, 1, "unbind", 0);
-
poperror();
- wunlock(ifc);
while(waserror())
;
-
/* wait for readers to die */
while(er->arpp != nil || er->read4p != nil || er->read6p != nil)
tsleep(&up->sleep, return0, 0, 300);
-
poperror();
- wlock(ifc);
if(er->mchan4 != nil)
cclose(er->mchan4);