diff --git a/src/afs/afs_call.c b/src/afs/afs_call.c index 5e0058cab1..345f7d57c9 100644 --- a/src/afs/afs_call.c +++ b/src/afs/afs_call.c @@ -1964,9 +1964,15 @@ afs_shutdown(void) afs_osi_Sleep(&afs_termState); } #endif -#else - afs_termState = AFSOP_STOP_COMPLETE; #endif + +#ifdef AFS_SUN510_ENV + afs_warn("NetIfPoller... "); + osi_StopNetIfPoller(); +#endif + + afs_termState = AFSOP_STOP_COMPLETE; + afs_warn("\n"); #ifdef AFS_AIX51_ENV diff --git a/src/rx/SOLARIS/rx_knet.c b/src/rx/SOLARIS/rx_knet.c index 46c76f07b1..22c85a6eb7 100644 --- a/src/rx/SOLARIS/rx_knet.c +++ b/src/rx/SOLARIS/rx_knet.c @@ -591,6 +591,8 @@ osi_NetReceive(osi_socket so, struct sockaddr_in *addr, struct iovec *dvec, /* set afs:afs_if_poll_interval = integer (value is in seconds) */ static int afs_if_poll_interval = 30; +static timeout_id_t afs_if_poller_timeout = 0; + /* Global array which holds the interface info for consumers */ struct afs_ifinfo afsifinfo[ADDRSPERSITE]; @@ -622,14 +624,6 @@ osi_NetIfPoller() uint_t mtu; uint64_t flags; - if (afs_termState == AFSOP_STOP_NETIF) { - afs_warn("NetIfPoller... "); - rw_destroy(&afsifinfo_lock); - ddi_taskq_destroy(afs_taskq); - afs_termState = AFSOP_STOP_COMPLETE; - osi_rxWakeup(&afs_termState); - return; - } /* Get our permissions */ cr = CRED(); @@ -765,10 +759,35 @@ osi_NetIfPoller() if (li) (void) ldi_ident_release(li); - /* Schedule this to run again after afs_if_poll_interval seconds */ - (void) timeout((void(*) (void *)) osi_StartNetIfPoller, NULL, - drv_usectohz((clock_t)afs_if_poll_interval * MICROSEC)); + if (afs_shuttingdown) { + /* do not schedule to run again if we're shutting down */ + return; + } + /* Schedule this to run again after afs_if_poll_interval seconds */ + afs_if_poller_timeout = timeout((void(*) (void *)) osi_StartNetIfPoller, + NULL, drv_usectohz((clock_t)afs_if_poll_interval * MICROSEC)); +} + +void +osi_StopNetIfPoller(void) +{ + /* it's okay if untimeout races with StartNetIfPoller/NetIfPoller; + * it can handle being passed invalid ids. If StartNetIfPoller is + * in the middle of running, untimeout will not return until + * StartNetIfPoller is done */ + untimeout(afs_if_poller_timeout); + + /* if NetIfPoller is queued or running, ddi_taskq_destroy will not + * return until it is done */ + ddi_taskq_destroy(afs_taskq); + + rw_destroy(&afsifinfo_lock); + + if (afs_termState == AFSOP_STOP_NETIF) { + afs_termState = AFSOP_STOP_COMPLETE; + osi_rxWakeup(&afs_termState); + } } #endif /* AFS_SUN510_ENV */ diff --git a/src/rx/rx_prototypes.h b/src/rx/rx_prototypes.h index b61e6983dd..cbe676320f 100644 --- a/src/rx/rx_prototypes.h +++ b/src/rx/rx_prototypes.h @@ -406,6 +406,7 @@ extern int osi_NetReceive(osi_socket so, struct sockaddr_in *addr, #if defined(KERNEL) && defined(AFS_SUN510_ENV) extern void osi_StartNetIfPoller(void); extern void osi_NetIfPoller(void); +extern void osi_StopNetIfPoller(void); extern struct afs_ifinfo afsifinfo[ADDRSPERSITE]; #endif extern void osi_StopListener(void);