]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE12-callback-rxcon-protection-20031114
authorDerrick Brashear <shadow@dementia.org>
Mon, 18 Oct 2004 04:19:39 +0000 (04:19 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 18 Oct 2004 04:19:39 +0000 (04:19 +0000)
FIXES 2498

        CheckHost() sets the HOSTDELETED flag on a host, does its
        touch, calls H_UNLOCK at the end of its function;
        AddCallBCal1 in a different thread grabs the lock, does its
        thing.  Gets to GetSomeSpace_r(), which calls
        h_Enumerate_r; the host in question isn't held, so
        h_Enumerate_r calls h_Hold_r and h_Release_r on the host
        that CheckHost() set the HOSTDELETED flag on; h_Release_r
        sees the HOSTDELETED flag and calls h_TossStuff_r, poof, we
        have our broken host entry for ClearHostCallbacks_r to trip

(cherry picked from commit 4458dd4410207fcdf8dec6789f0397adc6ce7b01)

src/viced/callback.c

index be5561a1d24e1ae5dacda3ff4251c8e038890344..98c3521de3102d05edc540fdff54163d9b5ff2c4 100644 (file)
@@ -1376,17 +1376,23 @@ CleanupTimedOutCallBacks_r()
 
 
 static struct host *lih_host;
+static int lih_host_held = 0;
 
 static int lih_r(host, held, hostp)
     register struct host *host, *hostp;
     register int held;
 
 {
+    lih_host_held = 0;
     if (host->cblist
           && ((hostp && host != hostp) || (!held && !h_OtherHolds_r(host)))
            && (!lih_host || host->ActiveCall < lih_host->ActiveCall) ) {
        lih_host = host;
     }
+    if (!held) {
+        held = 1;
+        lih_host_held = 1;
+    }
     return held;
 
 } /*lih*/
@@ -1415,8 +1421,13 @@ static int GetSomeSpace_r(hostp, locked)
        hp = lih_host;
        if (hp) {
            cbstuff.GSS4++;
-           if ( ! ClearHostCallbacks_r(hp, 0 /* not locked or held */) )
-               return;
+            if (!ClearHostCallbacks_r(hp, 0 /* not locked or held */ )) {
+                if (lih_host_held) 
+                    h_Release_r(hp);
+                return 0;
+            }
+            if (lih_host_held) 
+                h_Release_r(hp);
            hp2 = hp->next;
        } else {
            hp2 = hostList;