avoid-client-connection-mismatches-20030213
[openafs.git] / src / viced / host.c
index 93292ba..209a006 100644 (file)
@@ -682,7 +682,7 @@ struct host *h_LookupUuid_r(afsUUID *uuidp)
  */
 
 /* 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.
  */
@@ -696,6 +696,16 @@ int h_TossStuff_r(register struct host *host)
     if  (i!=h_maxSlots)
        return;
 
+    /* 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: r_FreeConnection() does not yield */
     for (cp = &host->FirstClient; (client = *cp); ) {
        if ((host->hostFlags & HOSTDELETED) || client->deleted) {
@@ -1273,7 +1283,7 @@ ticket name length != 64
        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.
           */
@@ -1342,6 +1352,16 @@ ticket name length != 64
             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++;
@@ -1425,7 +1445,8 @@ ticket name length != 64
      * 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 */
     }