devip: avoid media bind/unbind kproc reader startup race, simplify etherbind
mark reader process pointers with (void*)-1 to mean not started yet. this avoids the race condition when media unbind happens before the kproc has set its Proc* pointer. then we would not post the note and the reader would continue running after unbind. etherbind can be simplified by reading the #lX/addr file to get the mac address, avoiding the temporary buffer.
This commit is contained in:
parent
ed3a576e8b
commit
a25819c43a
3 changed files with 65 additions and 64 deletions
|
@ -122,32 +122,49 @@ static char *nbmsg = "nonblocking";
|
||||||
static void
|
static void
|
||||||
etherbind(Ipifc *ifc, int argc, char **argv)
|
etherbind(Ipifc *ifc, int argc, char **argv)
|
||||||
{
|
{
|
||||||
Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6, *schan;
|
char addr[Maxpath], dir[Maxpath];
|
||||||
char addr[Maxpath]; //char addr[2*KNAMELEN];
|
|
||||||
char dir[Maxpath]; //char dir[2*KNAMELEN];
|
|
||||||
char *buf;
|
|
||||||
int n;
|
|
||||||
char *ptr;
|
|
||||||
Etherrock *er;
|
Etherrock *er;
|
||||||
|
Chan *c;
|
||||||
|
int n;
|
||||||
|
|
||||||
if(argc < 2)
|
if(argc < 2)
|
||||||
error(Ebadarg);
|
error(Ebadarg);
|
||||||
|
|
||||||
mchan4 = cchan4 = achan = mchan6 = cchan6 = nil;
|
/*
|
||||||
buf = nil;
|
* get mac address
|
||||||
|
*/
|
||||||
|
snprint(addr, sizeof(addr), "%s/addr", argv[2]);
|
||||||
|
c = namec(addr, Aopen, OREAD, 0);
|
||||||
if(waserror()){
|
if(waserror()){
|
||||||
if(mchan4 != nil)
|
cclose(c);
|
||||||
cclose(mchan4);
|
nexterror();
|
||||||
if(cchan4 != nil)
|
}
|
||||||
cclose(cchan4);
|
n = devtab[c->type]->read(c, addr, sizeof(addr)-1, 0);
|
||||||
if(achan != nil)
|
if(n < 0)
|
||||||
cclose(achan);
|
error(Eio);
|
||||||
if(mchan6 != nil)
|
addr[n] = 0;
|
||||||
cclose(mchan6);
|
if(parsemac(ifc->mac, addr, sizeof(ifc->mac)) != 6)
|
||||||
if(cchan6 != nil)
|
error("could not find mac address");
|
||||||
cclose(cchan6);
|
cclose(c);
|
||||||
if(buf != nil)
|
poperror();
|
||||||
free(buf);
|
|
||||||
|
er = smalloc(sizeof(*er));
|
||||||
|
er->read4p = er->read6p = er->arpp = (void*)-1;
|
||||||
|
er->mchan4 = er->cchan4 = er->mchan6 = er->cchan6 = er->achan = nil;
|
||||||
|
er->f = ifc->conv->p->f;
|
||||||
|
|
||||||
|
if(waserror()){
|
||||||
|
if(er->mchan4 != nil)
|
||||||
|
cclose(er->mchan4);
|
||||||
|
if(er->cchan4 != nil)
|
||||||
|
cclose(er->cchan4);
|
||||||
|
if(er->mchan6 != nil)
|
||||||
|
cclose(er->mchan6);
|
||||||
|
if(er->cchan6 != nil)
|
||||||
|
cclose(er->cchan6);
|
||||||
|
if(er->achan != nil)
|
||||||
|
cclose(er->achan);
|
||||||
|
free(er);
|
||||||
nexterror();
|
nexterror();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,39 +175,12 @@ etherbind(Ipifc *ifc, int argc, char **argv)
|
||||||
* this device.
|
* this device.
|
||||||
*/
|
*/
|
||||||
snprint(addr, sizeof(addr), "%s!0x800", argv[2]); /* ETIP4 */
|
snprint(addr, sizeof(addr), "%s!0x800", argv[2]); /* ETIP4 */
|
||||||
mchan4 = chandial(addr, nil, dir, &cchan4);
|
er->mchan4 = chandial(addr, nil, dir, &er->cchan4);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make it non-blocking
|
* make it non-blocking
|
||||||
*/
|
*/
|
||||||
devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0);
|
devtab[er->cchan4->type]->write(er->cchan4, nbmsg, strlen(nbmsg), 0);
|
||||||
|
|
||||||
/*
|
|
||||||
* get mac address and speed
|
|
||||||
*/
|
|
||||||
snprint(addr, sizeof(addr), "%s/stats", argv[2]);
|
|
||||||
buf = smalloc(512);
|
|
||||||
schan = namec(addr, Aopen, OREAD, 0);
|
|
||||||
if(waserror()){
|
|
||||||
cclose(schan);
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
n = devtab[schan->type]->read(schan, buf, 511, 0);
|
|
||||||
cclose(schan);
|
|
||||||
poperror();
|
|
||||||
buf[n] = 0;
|
|
||||||
|
|
||||||
ptr = strstr(buf, "addr: ");
|
|
||||||
if(!ptr)
|
|
||||||
error(Eio);
|
|
||||||
ptr += 6;
|
|
||||||
parsemac(ifc->mac, ptr, 6);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* open arp conversation
|
|
||||||
*/
|
|
||||||
snprint(addr, sizeof(addr), "%s!0x806", argv[2]); /* ETARP */
|
|
||||||
achan = chandial(addr, nil, nil, nil);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* open ipv6 conversation
|
* open ipv6 conversation
|
||||||
|
@ -199,25 +189,22 @@ etherbind(Ipifc *ifc, int argc, char **argv)
|
||||||
* this device.
|
* this device.
|
||||||
*/
|
*/
|
||||||
snprint(addr, sizeof(addr), "%s!0x86DD", argv[2]); /* ETIP6 */
|
snprint(addr, sizeof(addr), "%s!0x86DD", argv[2]); /* ETIP6 */
|
||||||
mchan6 = chandial(addr, nil, dir, &cchan6);
|
er->mchan6 = chandial(addr, nil, dir, &er->cchan6);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make it non-blocking
|
* make it non-blocking
|
||||||
*/
|
*/
|
||||||
devtab[cchan6->type]->write(cchan6, nbmsg, strlen(nbmsg), 0);
|
devtab[er->cchan6->type]->write(er->cchan6, nbmsg, strlen(nbmsg), 0);
|
||||||
|
|
||||||
er = smalloc(sizeof(*er));
|
/*
|
||||||
er->mchan4 = mchan4;
|
* open arp conversation
|
||||||
er->cchan4 = cchan4;
|
*/
|
||||||
er->achan = achan;
|
snprint(addr, sizeof(addr), "%s!0x806", argv[2]); /* ETARP */
|
||||||
er->mchan6 = mchan6;
|
er->achan = chandial(addr, nil, nil, nil);
|
||||||
er->cchan6 = cchan6;
|
|
||||||
er->f = ifc->conv->p->f;
|
|
||||||
ifc->arg = er;
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
poperror();
|
poperror();
|
||||||
|
|
||||||
|
ifc->arg = er;
|
||||||
|
|
||||||
kproc("etherread4", etherread4, ifc);
|
kproc("etherread4", etherread4, ifc);
|
||||||
kproc("etherread6", etherread6, ifc);
|
kproc("etherread6", etherread6, ifc);
|
||||||
kproc("recvarpproc", recvarpproc, ifc);
|
kproc("recvarpproc", recvarpproc, ifc);
|
||||||
|
@ -231,6 +218,10 @@ etherunbind(Ipifc *ifc)
|
||||||
{
|
{
|
||||||
Etherrock *er = ifc->arg;
|
Etherrock *er = ifc->arg;
|
||||||
|
|
||||||
|
/* wait for readers to start */
|
||||||
|
while(er->arpp == (void*)-1 || er->read4p == (void*)-1 || er->read6p == (void*)-1)
|
||||||
|
tsleep(&up->sleep, return0, 0, 300);
|
||||||
|
|
||||||
if(er->read4p != nil)
|
if(er->read4p != nil)
|
||||||
postnote(er->read4p, 1, "unbind", 0);
|
postnote(er->read4p, 1, "unbind", 0);
|
||||||
if(er->read6p != nil)
|
if(er->read6p != nil)
|
||||||
|
|
|
@ -28,6 +28,7 @@ loopbackbind(Ipifc *ifc, int, char**)
|
||||||
LB *lb;
|
LB *lb;
|
||||||
|
|
||||||
lb = smalloc(sizeof(*lb));
|
lb = smalloc(sizeof(*lb));
|
||||||
|
lb->readp = (void*)-1;
|
||||||
lb->f = ifc->conv->p->f;
|
lb->f = ifc->conv->p->f;
|
||||||
lb->q = qopen(1024*1024, Qmsg, nil, nil);
|
lb->q = qopen(1024*1024, Qmsg, nil, nil);
|
||||||
ifc->arg = lb;
|
ifc->arg = lb;
|
||||||
|
@ -41,11 +42,15 @@ loopbackunbind(Ipifc *ifc)
|
||||||
{
|
{
|
||||||
LB *lb = ifc->arg;
|
LB *lb = ifc->arg;
|
||||||
|
|
||||||
if(lb->readp)
|
/* wat for reader to start */
|
||||||
|
while(lb->readp == (void*)-1)
|
||||||
|
tsleep(&up->sleep, return0, 0, 300);
|
||||||
|
|
||||||
|
if(lb->readp != nil)
|
||||||
postnote(lb->readp, 1, "unbind", 0);
|
postnote(lb->readp, 1, "unbind", 0);
|
||||||
|
|
||||||
/* wait for reader to die */
|
/* wait for reader to die */
|
||||||
while(lb->readp != 0)
|
while(lb->readp != nil)
|
||||||
tsleep(&up->sleep, return0, 0, 300);
|
tsleep(&up->sleep, return0, 0, 300);
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
|
|
|
@ -49,6 +49,7 @@ netdevbind(Ipifc *ifc, int argc, char **argv)
|
||||||
mchan = namec(argv[2], Aopen, ORDWR, 0);
|
mchan = namec(argv[2], Aopen, ORDWR, 0);
|
||||||
|
|
||||||
er = smalloc(sizeof(*er));
|
er = smalloc(sizeof(*er));
|
||||||
|
er->readp = (void*)-1;
|
||||||
er->mchan = mchan;
|
er->mchan = mchan;
|
||||||
er->f = ifc->conv->p->f;
|
er->f = ifc->conv->p->f;
|
||||||
|
|
||||||
|
@ -65,10 +66,14 @@ netdevunbind(Ipifc *ifc)
|
||||||
{
|
{
|
||||||
Netdevrock *er = ifc->arg;
|
Netdevrock *er = ifc->arg;
|
||||||
|
|
||||||
|
/* wait for reader to start */
|
||||||
|
while(er->readp == (void*)-1)
|
||||||
|
tsleep(&up->sleep, return0, 0, 300);
|
||||||
|
|
||||||
if(er->readp != nil)
|
if(er->readp != nil)
|
||||||
postnote(er->readp, 1, "unbind", 0);
|
postnote(er->readp, 1, "unbind", 0);
|
||||||
|
|
||||||
/* wait for readers to die */
|
/* wait for reader to die */
|
||||||
while(er->readp != nil)
|
while(er->readp != nil)
|
||||||
tsleep(&up->sleep, return0, 0, 300);
|
tsleep(&up->sleep, return0, 0, 300);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue