#endif /* FS_STATS_DETAILED */
-
+/* Assumptions: called with held host */
void
h_gethostcps_r(register struct host *host, register afs_int32 now)
{
register int code;
- int slept=0, held;
-
- /* at this point, the host might not be locked, nor held */
- /* make sure that we do not disappear behind the RPC */
- if ( !(held = h_Held_r(host)) )
- h_Hold_r(host);
+ int slept=0;
- /* wait if somebody else is already doing the getCPS call */
+ /* wait if somebody else is already doing the getCPS call */
while ( host->hostFlags & HCPS_INPROGRESS )
{
slept = 1; /* I did sleep */
ViceLog(0, ("LWP_NoYieldSignal returns %d\n", code));
#endif /* AFS_PTHREAD_ENV */
}
-
- /* if we had held the host, release it now */
- if ( !held )
- h_Release_r(host);
}
-void h_flushhostcps(hostaddr, hport)
- register afs_uint32 hostaddr, hport; /* net byte order */
+/* args in net byte order */
+void h_flushhostcps(register afs_uint32 hostaddr, register afs_uint32 hport)
{
register struct host *host;
int held;
h_Release_r(host);
H_UNLOCK
-return;
+ return;
}
host->hostFlags = 0;
host->hcps.prlist_val = NULL;
host->hcps.prlist_len = 0;
- host->hcps.prlist_val = NULL;
host->interface = 0;
#ifdef undef
host->hcpsfailed = 0; /* save cycles */
- h_gethostcps(host); /* do this under host lock */
+ h_gethostcps(host); /* do this under host hold/lock */
#endif
host->FirstClient = 0;
h_Hold_r(host);
* membership list for the host. Note this could be the
* first time that the host is added to a group. Also
* here we also retry on previous legitimate hcps failures.
+ *
+ * If we get here we still have a host hold.
*/
- h_gethostcps_r(host,now);
+ h_gethostcps_r(host,now);
}
break;
}
*/
/* h_TossStuff_r: Toss anything in the host structure (the host or
- * clients marked for deletion. Called from r_Release ONLY.
+ * clients marked for deletion. Called from h_Release_r ONLY.
* To be called, there must be no holds, and either host->deleted
* or host->clientDeleted must be set.
*/
if (i!=h_maxSlots)
return;
- /* ASSUMPTION: r_FreeConnection() does not yield */
+ /* if somebody still has this host locked */
+ if (h_NBLock_r(host) != 0) {
+ char hoststr[16];
+ ViceLog(0, ("Warning: h_TossStuff_r failed; Host %s:%d was locked.\n",
+ afs_inet_ntoa_r(host->host, hoststr), host->port));
+ return;
+ } else {
+ h_Unlock_r(host);
+ }
+
+ /* ASSUMPTION: rxi_FreeConnection() does not yield */
for (cp = &host->FirstClient; (client = *cp); ) {
if ((host->hostFlags & HOSTDELETED) || client->deleted) {
if ((client->ViceId != ANONYMOUSID) && client->CPS.prlist_val) {
free(client->CPS.prlist_val);
client->CPS.prlist_val = NULL;
}
+ client->CPS.prlist_len = 0;
if (client->tcon) {
rx_SetSpecific(client->tcon, rxcon_client_key, (void *)0);
}
h_Hold_r(client->host);
if (client->prfail != 2) { /* Could add shared lock on client here */
/* note that we don't have to lock entry in this path to
- * ensure CPS is initialized, since we don't call rxr_SetSpecific
+ * ensure CPS is initialized, since we don't call rx_SetSpecific
* until initialization is done, and we only get here if
* rx_GetSpecific located the client structure.
*/
if (client->tcon && (client->tcon != tcon)) {
ViceLog(0, ("*** Vid=%d, sid=%x, tcon=%x, Tcon=%x ***\n",
client->ViceId, client->sid, client->tcon, tcon));
+ oldClient = (struct client *) rx_GetSpecific(client->tcon,
+ rxcon_client_key);
+ if (oldClient) {
+ if (oldClient == client)
+ rx_SetSpecific(client->tcon, rxcon_client_key, NULL);
+ else
+ ViceLog(0,
+ ("Client-conn mismatch: CL1=%x, CN=%x, CL2=%x\n",
+ client, client->tcon, oldClient));
+ }
client->tcon = (struct rx_connection *)0;
}
client->refCount++;
if (!client) {
client = GetCE();
ObtainWriteLock(&client->lock);
+ client->refCount = 1;
client->host = host;
client->next = host->FirstClient;
host->FirstClient = client;
client->sid = rxr_CidOf(tcon);
client->VenusEpoch = rxr_GetEpoch(tcon);
client->CPS.prlist_val = 0;
- client->refCount = 1;
+ client->CPS.prlist_len = 0;
CurrentConnections++; /* increment number of connections */
}
}
free(client->CPS.prlist_val);
}
client->CPS.prlist_val = NULL;
+ client->CPS.prlist_len = 0;
client->ViceId = viceid;
client->expTime = expTime;
* required). So, before setting the RPC's rock, we should disconnect
* the RPC from the other client structure's rock.
*/
- if ((oldClient = (struct client *) rx_GetSpecific(tcon, rxcon_client_key))) {
+ oldClient = (struct client *) rx_GetSpecific(tcon, rxcon_client_key);
+ if (oldClient && oldClient->tcon == tcon) {
oldClient->tcon = (struct rx_connection *) 0;
/* rx_SetSpecific will be done immediately below */
}