Windows: cm_UpdateCell must hold cell lock across server random
authorJeffrey Altman <jaltman@your-file-system.com>
Sat, 17 Apr 2010 02:52:20 +0000 (22:52 -0400)
committerJeffrey Altman <jaltman@openafs.org>
Sat, 17 Apr 2010 03:10:03 +0000 (20:10 -0700)
cm_UpdateCell fails to hold the cell lock across the server
randomization.  As a result the vlserver list can be destroyed
while randomization is taking place.

LICENSE MIT

Change-Id: I7753e7e9f8a7d536ce0e2082aaca7b62ab745504
Reviewed-on: http://gerrit.openafs.org/1767
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>

src/WINNT/afsd/cm_cell.c

index bb08f7a..b1094c6 100644 (file)
@@ -76,11 +76,13 @@ cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags)
 {
     long code = 0;
     cm_cell_rock_t rock;
+    afs_uint32 mxheld = 0;
 
     if (cp == NULL)
         return NULL;
 
     lock_ObtainMutex(&cp->mx);
+    mxheld = 1;
     if ((cp->vlServersp == NULL 
 #ifdef AFS_FREELANCE_CLIENT
           && !(cp->flags & CM_CELLFLAG_FREELANCE)
@@ -90,14 +92,15 @@ cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags)
          ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID)))
             ) 
     {
-        lock_ReleaseMutex(&cp->mx);
-
         /* must empty cp->vlServersp */
         if (cp->vlServersp) {
             cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE);
             cp->vlServersp = NULL;
         }
 
+        lock_ReleaseMutex(&cp->mx);
+        mxheld = 0;
+
         rock.cellp = cp;
         rock.flags = flags;
         code = cm_SearchCellRegistry(1, cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock);
@@ -105,8 +108,8 @@ cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags)
             code = cm_SearchCellFileEx(cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock);
         if (code == 0) {
             lock_ObtainMutex(&cp->mx);
+            mxheld = 1;
            cp->timeout = time(0) + 7200;
-            lock_ReleaseMutex(&cp->mx);
         }
         else {
             if (cm_dnsEnabled) {
@@ -115,10 +118,10 @@ cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags)
                 code = cm_SearchCellByDNS(cp->name, NULL, &ttl, cm_AddCellProc, &rock);
                 if (code == 0) {   /* got cell from DNS */
                     lock_ObtainMutex(&cp->mx);
+                    mxheld = 1;
                     cp->flags |= CM_CELLFLAG_DNS;
                     cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
                    cp->timeout = time(0) + ttl;
-                    lock_ReleaseMutex(&cp->mx);
 #ifdef DEBUG
                     fprintf(stderr, "cell %s: ttl=%d\n", cp->name, ttl);
 #endif
@@ -127,18 +130,19 @@ cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags)
                      * current entry alone 
                     */
                     lock_ObtainMutex(&cp->mx);
+                    mxheld = 1;
                     cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
-                    lock_ReleaseMutex(&cp->mx);
                 }
            }
        }
-    } else {
-        lock_ReleaseMutex(&cp->mx);
     }
 
     if (code == 0)
         cm_RandomizeServer(&cp->vlServersp);
 
+    if (mxheld)
+        lock_ReleaseMutex(&cp->mx);
+
     return code ? NULL : cp;
 }