7289f371a0
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.
50 lines
691 B
C
50 lines
691 B
C
#include "u.h"
|
|
#include "../port/lib.h"
|
|
#include "mem.h"
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
#include "../port/error.h"
|
|
|
|
#include "ip.h"
|
|
|
|
static void
|
|
nullbind(Ipifc*, int, char**)
|
|
{
|
|
error("cannot bind null device");
|
|
}
|
|
|
|
static void
|
|
nullunbind(Ipifc*)
|
|
{
|
|
}
|
|
|
|
static void
|
|
nullbwrite(Ipifc*, Block *bp, int, uchar*, Routehint*)
|
|
{
|
|
freeb(bp);
|
|
error("nullbwrite");
|
|
}
|
|
|
|
Medium nullmedium =
|
|
{
|
|
.name= "null",
|
|
.bind= nullbind,
|
|
.unbind= nullunbind,
|
|
.bwrite= nullbwrite,
|
|
};
|
|
|
|
/* used in ipifc to prevent unbind while bind is in progress */
|
|
Medium unboundmedium =
|
|
{
|
|
.name= "unbound",
|
|
.bind= nullbind,
|
|
.unbind= nullunbind,
|
|
.bwrite= nullbwrite,
|
|
};
|
|
|
|
void
|
|
nullmediumlink(void)
|
|
{
|
|
addipmedium(&nullmedium);
|
|
}
|