From cbe580fee176c9e9e083379129c309fd15d0f24c Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 23 Oct 2009 09:54:35 -0500 Subject: [PATCH] Check for (hostFlags & HOSTDELETED) after h_Lock_r 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 Tested-by: Derrick Brashear --- src/viced/callback.c | 37 ++++++++++++++++++++----------------- src/viced/host.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/viced/callback.c b/src/viced/callback.c index 26f1bb2..e49d400 100644 --- a/src/viced/callback.c +++ b/src/viced/callback.c @@ -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; diff --git a/src/viced/host.c b/src/viced/host.c index 7308539..eed4430 100644 --- a/src/viced/host.c +++ b/src/viced/host.c @@ -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; -- 1.9.4