Check for (hostFlags & HOSTDELETED) after h_Lock_r
authorJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 23 Oct 2009 14:54:35 +0000 (09:54 -0500)
committerDerrick Brashear <shadow|account-1000005@unknown>
Tue, 3 Nov 2009 20:08:43 +0000 (12:08 -0800)
Many callers of h_Lock_r do not check if the HOSTDELETED flag is set,
even though it could have been set while waiting for the host lock. Add
checks for it everywhere we call h_Lock_r and we care if the host has
been deleted.

FIXES 125507

Change-Id: Id1430529a1afdb5e2af29d40148877f5e4260a41
Reviewed-on: http://gerrit.openafs.org/716
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/viced/callback.c
src/viced/host.c

index 26f1bb2..e49d400 100644 (file)
@@ -518,12 +518,13 @@ int
 AddCallBack1(struct host *host, AFSFid * fid, afs_uint32 * thead, int type,
             int locked)
 {
-    int retVal;
+    int retVal = 0;
     H_LOCK;
     if (!locked) {
        h_Lock_r(host);
     }
-    retVal = AddCallBack1_r(host, fid, thead, type, 1);
+    if (!(host->hostFlags & HOSTDELETED))
+        retVal = AddCallBack1_r(host, fid, thead, type, 1);
 
     if (!locked) {
        h_Unlock_r(host);
@@ -564,6 +565,11 @@ AddCallBack1_r(struct host *host, AFSFid * fid, afs_uint32 * thead, int type,
     if (!locked) {
        h_Lock_r(host);         /* this can yield, so do it before we get any */
        /* fragile info */
+        if (host->hostFlags & HOSTDELETED) {
+            host->Console &= ~2;
+            h_Unlock_r(host);
+            return 0;
+        }
     }
 
     fe = FindFE(fid);
@@ -745,12 +751,14 @@ MultiBreakCallBack_r(struct cbstruct cba[], int ncbas,
 
                        H_LOCK;
                        h_Lock_r(hp); 
-                       hp->hostFlags |= VENUSDOWN;
-               /**
-                 * We always go into AddCallBack1_r with the host locked
-                 */
-                       AddCallBack1_r(hp, afidp->AFSCBFids_val, itot(idx),
-                                      CB_DELAYED, 1);
+                        if (!(hp->hostFlags & HOSTDELETED)) {
+                            hp->hostFlags |= VENUSDOWN;
+                            /**
+                             * We always go into AddCallBack1_r with the host locked
+                             */
+                            AddCallBack1_r(hp, afidp->AFSCBFids_val, itot(idx),
+                                           CB_DELAYED, 1);
+                        }
                        h_Unlock_r(hp); 
                        H_UNLOCK;
                    }
@@ -885,6 +893,7 @@ DeleteCallBack(struct host *host, AFSFid * fid)
     cbstuff.DeleteCallBacks++;
 
     h_Lock_r(host);
+    /* do not care if the host has been HOSTDELETED */
     fe = FindFE(fid);
     if (!fe) {
        h_Unlock_r(host);
@@ -1116,16 +1125,10 @@ MultiBreakVolumeCallBack_r(struct host *host, int isheld,
 
     if (host->hostFlags & VENUSDOWN) {
        h_Lock_r(host);
-       if (host->hostFlags & HOSTDELETED) {
-           h_Unlock_r(host);
-           return 0;           /* Release hold */
-       }
-       ViceLog(8,
-               ("BVCB: volume call back for Host %x (%s:%d) failed\n",
-                 host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
+        /* Do not care if the host is now HOSTDELETED */
        if (ShowProblems) {
            ViceLog(0,
-                   ("CB: volume callback for Host %x (%s:%d) failed\n",
+                   ("BVCB: volume callback for Host %x (%s:%d) failed\n",
                     host, afs_inet_ntoa_r(host->host, hoststr),
                     ntohs(host->port)));
        }
@@ -1642,7 +1645,7 @@ ClearHostCallbacks_r(struct host *hp, int locked)
     DeleteAllCallBacks_r(hp, 1);
     if (hp->hostFlags & VENUSDOWN) {
        hp->hostFlags &= ~RESETDONE;    /* remember that we must do a reset */
-    } else {
+    } else if (!(hp->hostFlags & HOSTDELETED)) {
        /* host is up, try a call */
        hp->hostFlags &= ~ALTADDR;      /* alternate addresses are invalid */
        cb_conn = hp->callback_rxcon;
index 7308539..eed4430 100644 (file)
@@ -1503,8 +1503,11 @@ h_GetHost_r(struct rx_connection *tcon)
            goto gethost_out;
        }
        h_Lock_r(host);
-       if (!(host->hostFlags & ALTADDR)) {
-           /* Another thread is doing initialization */
+       if (!(host->hostFlags & ALTADDR) ||
+            (host->hostFlags & HOSTDELETED)) {
+           /* Another thread is doing initialization
+             * or this host was deleted while we
+             * waited for the lock. */
            h_Unlock_r(host);
            ViceLog(125,
                    ("Host %" AFS_PTR_FMT " (%s:%d) starting h_Lookup again\n",
@@ -1834,10 +1837,19 @@ h_GetHost_r(struct rx_connection *tcon)
            } else if (code == 0) {
                oldHost = h_LookupUuid_r(&identP->uuid);
                 if (oldHost) {
-                    int probefail = 0;
-
                    h_Hold_r(oldHost);
                    h_Lock_r(oldHost);
+
+                   if (oldHost->hostFlags & HOSTDELETED) {
+                       h_Unlock_r(oldHost);
+                       h_Release_r(oldHost);
+                       oldHost = NULL;
+                   }
+               }
+
+               if (oldHost) {
+                   int probefail = 0;
+
                    oldHost->hostFlags |= HWHO_INPROGRESS;
 
                     if (oldHost->interface) {
@@ -2235,7 +2247,7 @@ h_FindClient_r(struct rx_connection *tcon)
        host = h_GetHost_r(tcon);       /* Returns with incremented refCount  */
 
        if (!host) 
-           return 0;
+           return NULL;
 
     retryfirstclient:
        /* First try to find the client structure */
@@ -2253,6 +2265,11 @@ h_FindClient_r(struct rx_connection *tcon)
        /* Still no client structure - get one */
        if (!client) {
            h_Lock_r(host);
+            if (host->hostFlags & HOSTDELETED) {
+                h_Unlock_r(host);
+                h_Release_r(host);
+                return NULL;
+            }
            /* Retry to find the client structure */
            for (client = host->FirstClient; client; client = client->next) {
                if (!client->deleted && (client->sid == rxr_CidOf(tcon))
@@ -2374,6 +2391,25 @@ h_FindClient_r(struct rx_connection *tcon)
     /* Avoid chaining in more than once. */
     if (created) {
        h_Lock_r(host);
+
+        if (host->hostFlags & HOSTDELETED) {
+            h_Unlock_r(host);
+            h_Release_r(host);
+
+            host = NULL;
+            client->host = NULL;
+
+            if ((client->ViceId != ANONYMOUSID) && client->CPS.prlist_val)
+                free(client->CPS.prlist_val);
+            client->CPS.prlist_val = NULL;
+            client->CPS.prlist_len = 0;
+
+            client->refCount--;
+            ReleaseWriteLock(&client->lock);
+            FreeCE(client);
+            return NULL;
+        }
+
        client->next = host->FirstClient;
        host->FirstClient = client;
        h_Unlock_r(host);
@@ -3433,8 +3469,8 @@ CheckHost(register struct host *host, int flags, void *rock)
     }
     if (host->LastCall < checktime) {
        h_Lock_r(host);
-       host->hostFlags |= HWHO_INPROGRESS;
        if (!(host->hostFlags & HOSTDELETED)) {
+            host->hostFlags |= HWHO_INPROGRESS;
            cb_conn = host->callback_rxcon;
            rx_GetConnection(cb_conn);
            if (host->LastCall < clientdeletetime) {
@@ -3502,8 +3538,8 @@ CheckHost(register struct host *host, int flags, void *rock)
            rx_PutConnection(cb_conn);
            cb_conn=NULL;
            H_LOCK;
+            host->hostFlags &= ~HWHO_INPROGRESS;
        }
-       host->hostFlags &= ~HWHO_INPROGRESS;
        h_Unlock_r(host);
     }
     H_UNLOCK;