windows-free-server-deadlock-20080813
authorJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 14 Aug 2008 03:36:43 +0000 (03:36 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 14 Aug 2008 03:36:43 +0000 (03:36 +0000)
LICENSE MIT

avoid a deadloc when freeing servers.  cm_serverLock must be released
around cm_GCConnections()

src/WINNT/afsd/cm_server.c
src/WINNT/afsd/cm_server.h

index be2b7fd..0a442fc 100644 (file)
@@ -1191,16 +1191,32 @@ void cm_RandomizeServer(cm_serverRef_t** list)
 void cm_FreeServer(cm_server_t* serverp)
 {
     cm_server_vols_t * tsrvp, *nextp;
+    int delserver = 0;
 
     cm_PutServerNoLock(serverp);
     if (serverp->refCount == 0)
     {
-        /* we need to check to ensure that all of the connections
+        /* 
+         * we need to check to ensure that all of the connections
          * for this server have a 0 refCount; otherwise, they will
          * not be garbage collected 
+         *
+         * must drop the cm_serverLock because cm_GCConnections
+         * obtains the cm_connLock and that comes first in the 
+         * lock hierarchy.  
          */
+        lock_ReleaseWrite(&cm_serverLock);
         cm_GCConnections(serverp);  /* connsp */
+        lock_ObtainWrite(&cm_serverLock);
+    }
 
+
+    /* 
+     * Once we have the cm_serverLock locked check to make
+     * sure the refCount is still zero before removing the 
+     * server entirely.
+     */
+    if (serverp->refCount == 0) {
        if (!(serverp->flags & CM_SERVERFLAG_PREF_SET)) {
             switch (serverp->type) {
             case CM_SERVER_VLDB:
index 143ff4c..93001b6 100644 (file)
@@ -128,6 +128,8 @@ extern cm_server_t * cm_FindServerByIP(afs_uint32 addr, int type);
 
 extern void cm_SetLanAdapterChangeDetected(void);
 
+extern void cm_RemoveVolumeFromServer(cm_server_t * serverp, afs_uint32 volID);
+
 /* Protected by cm_syscfgLock (rw) */
 extern int cm_noIPAddr;         /* number of client network interfaces */
 extern int cm_IPAddr[CM_MAXINTERFACE_ADDR];    /* client's IP address in host order */