]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Solaris: stop NetIfPoller on shutdown
authorAndrew Deason <adeason@sinenomine.net>
Wed, 12 May 2010 18:59:06 +0000 (13:59 -0500)
committerDerrick Brashear <shadow@dementia.org>
Wed, 12 May 2010 19:44:20 +0000 (12:44 -0700)
The NetIfPoller code that is enabled on AFS_SUN510_ENV never gets
shutdown properly. The current code looks as if it was intended for
NetIfPoller to recognize the appropriate termState and just return,
but we never wait for it, and so we can complete the shutdown sequence
without NetIfPoller ever knowing that we are shutting down. This can
cause the machine to panic, as we keep attempting to run NetIfPoller
even after libafs has been unloaded.

Since NetIfPoller is fired by default every 30 seconds, we probably do
not want to wait for it to fire during shutdown. Instead, just destroy
the necessary timeout and task queue, which will wait for NetIfPoller
to complete if running, and will just prevent it from running in the
future otherwise.

Change-Id: I25f9536d2713baf524a2450400c428ac506525f1
Reviewed-on: http://gerrit.openafs.org/1957
Tested-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
src/afs/afs_call.c
src/rx/SOLARIS/rx_knet.c
src/rx/rx_prototypes.h

index 64ae4367a3fac345b57e5fd39ea93a0992c69dd5..3b5093694f1e91b4e410424b6c8b5775f4617ad2 100644 (file)
@@ -1281,10 +1281,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;
+
 #ifdef AFS_AIX51_ENV
     shutdown_daemons();
 #endif
index 46c76f07b1ca5ded5d87abd4fc7e222237ab4222..22c85a6eb72f04b33f093ce6bb4afd4541105cef 100644 (file)
@@ -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);
 
+    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 */
-    (void) timeout((void(*) (void *)) osi_StartNetIfPoller, NULL,
-        drv_usectohz((clock_t)afs_if_poll_interval * MICROSEC));
+    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 */
 
index c8b4ed14d8c094ec0e729f0de14b81e7d1e120e8..77ee085608efbe7b987f8566b1c349188b06b54e 100644 (file)
@@ -434,6 +434,7 @@ extern int osi_NetReceive(osi_socket so, struct sockaddr_in *addr,
 # if 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);