]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
h_TossStuff_r: check held-ness after lock
authorAndrew Deason <adeason@sinenomine.net>
Mon, 15 Feb 2010 16:55:33 +0000 (10:55 -0600)
committerRuss Allbery <rra@debian.org>
Mon, 22 Mar 2010 22:39:34 +0000 (15:39 -0700)
h_TossStuff_r checks if a host is held or locked by another thread
before trying to delete the host. Unfortunately, it checks if it is
locked before checking if it is held, and the lock check drops H_LOCK.
Thus, another thread could hold the host while we don't have H_LOCK, and
we could delete a host that is being held.

Although it is a bug if any thread holds a host that is being deleted,
some instances of this still exist, so make the check more robust.
Reverse the order of the tests, so we detect if someone held the host
while the lock check dropped H_LOCK.

Also log when this happens, as it indicates a bug occurring.

FIXES 126454

Reviewed-on: http://gerrit.openafs.org/1312
Tested-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Alistair Ferguson <alistair.ferguson@mac.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
(cherry picked from commit 45aceee9842265fb0ccdb5e8f3f6d32c8d2b99ea)

Change-Id: Ibce716b0d57d02d1ad912276dfa9f4b169294947
Reviewed-on: http://gerrit.openafs.org/1367
Tested-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
(cherry picked from commit 94a439668b8ef90027f922e9fb85fe1f3e983100)

src/viced/host.c

index 77f66c9aff1b87f87fefaabec3303ddc53f9fe26..3711645e173313b44b490a6d6a3cf1c9b59dd34e 100644 (file)
@@ -914,11 +914,6 @@ h_TossStuff_r(register struct host *host)
     register struct client **cp, *client;
     int i;
 
-    /* if somebody still has this host held */
-    for (i = 0; (i < h_maxSlots) && (!(host)->holds[i]); i++);
-    if (i != h_maxSlots)
-       return;
-
     /* if somebody still has this host locked */
     if (h_NBLock_r(host) != 0) {
        char hoststr[16];
@@ -930,6 +925,18 @@ h_TossStuff_r(register struct host *host)
        h_Unlock_r(host);
     }
 
+    /* if somebody still has this host held */
+    /* we must check this _after_ h_NBLock_r, since h_NBLock_r can drop and
+     * reacquire H_LOCK */
+    for (i = 0; (i < h_maxSlots) && (!(host)->holds[i]); i++);
+    if (i != h_maxSlots) {
+       char hoststr[16];
+       ViceLog(0,
+               ("Warning:  h_TossStuff_r failed; Host %s:%d was held.\n",
+                afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
+       return;
+    }
+
     /* ASSUMPTION: rxi_FreeConnection() does not yield */
     for (cp = &host->FirstClient; (client = *cp);) {
        if ((host->hostFlags & HOSTDELETED) || client->deleted) {